Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Push down bottom div when slideDown with multiple columns and rows

I have multiple items organized in multiple columns and rows

 <div class="items">
    <div class="item-1">
    <div class="item-2">
    <div class="item-3">
    <div class="item-4">
    <div class="item-5">
    ...
 </div>

I'm using jQuery slidedown to show hide content of each item when clicks. I want to push the bottom content correctly, ie extend the same column to which the object belongs.

Example with basic float:left and width:33%

http://jsfiddle.net/kurtko/4w8n1frr/

I have tried several methods:

1) Using columns with float:left, then insert items changing the order with PHP. From: 1,2,3,4,5,6,7,8,9 to 1,4,7,2,5,8,3,6,9.

http://jsfiddle.net/kurtko/adLL8gmn/

<div class="items">    
 <div class="column>
   <div class="item-1">
   <div class="item-4">
   <div class="item-7">
 </div>
 <div class="column>
   <div class="item-2">
   <div class="item-5">
   <div class="item-8">
 </div>
</div>

This is a good method, but when I use responsive version with one column the order is incorrect.

2) Masonry. Masonry - Isotope has a custom layout mode called 'masonryColumnShift' but in current version 2 is disabled.

http://isotope.metafizzy.co/v1/custom-layout-modes/masonry-column-shift.html

3) Flexbox. Using:

http://jsfiddle.net/kurtko/7cu5jvrr/

.items {    
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
}

.item {
   width: 33.3%;
}

Good results but not perfect. When an item changes its height a white space is created below the row.

Any ideas?

Thanks.

like image 507
kurtko Avatar asked Nov 10 '22 15:11

kurtko


1 Answers

Update (4/21/15)

This is a pretty major update on what I had before. I'm using jQuery to find all the div's, and sort them into a .new div. When the screen becomes smaller than 600px, I put them back into their original configuration, and stack them in order to be viewed better on a mobile device.

You can see it live here.

$(document).ready(function() {
  var divsAccross = 3;       // DIV's accross
  var elmParent = '.items';  // Container Class
  var elmChild = '.item';    // Elements to be sorted
  var createdDiv = 'new';    // New DIV created to hold the new sort
  var sortBy = 'id';         // Sort Elements by...

  // Shouldn't have to edit anything below.
  var windowSize = $(window).width();
  var totalDivs = [];
  var scrnSize = "large";
  var newWidths = Math.floor(100 / divsAccross);
  var newMargin = (100 % divsAccross) / (divsAccross - 1);

  $(elmChild).each(function() {
    totalDivs.push($(this).attr(sortBy));
  });

  var matrix = listToMatrix(totalDivs, divsAccross);

  if (windowSize > 600) {
    reOrder(matrix);
    scrnSize = "large";
  } else {
    scrnSize = "small";
  }

  $(elmChild).click(function() {
    $(this).find('.hidden').slideToggle(500);
  });

  $(window).resize(function() {
    windowSize = $(window).width();

    if (windowSize <= 600) {
      if (scrnSize == "large") {
        var $mylist = $(elmParent);

        $mylist.find(elmChild).sort(function(a, b) {
          return +a.getAttribute(sortBy) - +b.getAttribute(sortBy);
        }).appendTo($mylist);
        $("." + createdDiv).remove();
        scrnSize = "small";
      }
    } else {
      if (scrnSize == "small") {
        reOrder(matrix);
        scrnSize = "large";
      }
    }
  });

  function reOrder(list) {
    for (var d = 0; d < list.length; d++) {
      for (var n = 0; n < list[d].length; n++) {
        $('#' + list[d][n]).addClass(' ' + d);
      }
      $('.' + d).wrapAll("<div class=" + createdDiv + "></div>");
      $('.' + createdDiv).css({
        'width': newWidths + '%',
        'margin': '0 ' + newMargin + '% 0 0'
      })
    }
  }

  function listToMatrix(list, elementsPerSubArray) {
    var matrix = [],
      i, k;
    var newMatrix = [],
      x, y;

    for (i = 0, k = -1; i < list.length; i++) {
      if (i % elementsPerSubArray === 0) {
        k++;
        matrix[k] = [];
      }
      matrix[k].push(list[i]);
    }

    for (x = 0; x < elementsPerSubArray; x++) {
      newMatrix[x] = [];
      for (y = 0; y < matrix.length; y++) {
        if (matrix[y][x] != null) {
          newMatrix[x].push(matrix[y][x]);
        }
      }
    }
    return newMatrix;
  }
});
* {
  margin: 0;
  padding: 0;
}
.items {
  margin: 0.5%;
  height: 100%;
}
.item {
  padding: 20px 0;
  margin: 0 5px 5px 0;
  background: darkgreen;
  text-align: center;
  width: 100%;
  border: 1px solid red;
  cursor: pointer;
  float: left;
}
.new {
  float: left;
}
.new:last-child {
  margin: 0 !important;
}
.hidden {
  display: none;
  margin-top: 20px;
  width: 100%;
  padding: 150px 0;
  border-top: 1px solid red;
  border-bottom: 1px solid red;
  background-color: orange;
}
@media all and (max-width: 600px) {
  .items {
    display: flex;
    flex-flow: row wrap;
    height: 100%;
  }
  .items > * {
    flex: 1 100%;
    width: 100%;
    float: none;
  }
  .two {
    order: 2;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="items">
  <div class="item" id="1">1
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="2">2
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="3">3
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="4">4
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="5">5
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="6">6
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="7">7
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="8">8
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="9">9
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="10">10
    <div class="hidden">Hide</div>
  </div>
  <div class="item" id="11">11
    <div class="hidden">Hide</div>
  </div>
</div>

Update (4/22/15)

Updated the function in case you plan to have more than nine div's and to put all the controls of everything at the top. You shouldn't need to edit anything beyond the first five variable. The only thing you could do further would be to turn this into a plugin of it's own.

like image 59
Pixel Rubble Avatar answered Nov 15 '22 06:11

Pixel Rubble