Process every nth element separately in JQuery

Viewed 53

I have an html structure like this:

Each <li> has <p> and <img> element that has a different height, therefore I had to make every <li> element has the same height by finding the highest <p> and <img> and apply the height to every <p> and <img> inside the <li> element like this script which works perfectly, and i have separated the list into 3 columns for each row, so roughly it will look like this:

+------+ +------+ +------+  
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
+------+ +------+ +------+
+------+ +------+ +------+
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
+------+ +------+ +------+
+------+ +------+ 
|      | |      | 
|      | |      |
|      | |      | 
|      | |      |  
+------+ +------+ 

Since i process every element inside li at the same time to get the highest height of <p> and <img> element, it will make one of the <li> height is too much, i want to process <li> into a separate batch (each row with 3 columns) , so they will have the same height only for the same row, for example:

+------+ +------+ +------+   
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
+------+ +------+ +------+
+------+ +------+ +------+
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
|      | |      | |      |
+------+ +------+ +------+
+------+ +------+ 
|      | |      | 
|      | |      |
+------+ +------+

$(document).ready(function() {
  adjustHeights()

  function adjustHeights() {
    var classes = ['.product-name', '.product-image'];
    var mainClass = '#product-list';
    $.each(classes, function(index, elementClass) {
      adjustHeight(mainClass, elementClass)
    });
  }

  function adjustHeight(mainClass, elementClass) {
    var productElem = $(mainClass).find(elementClass);
    var i = 0;
    var elementHeights = productElem.map(function() {
      return $(this).height();
    }).get();
    var maxHeight = Math.max.apply(null, elementHeights);
    productElem.height(maxHeight);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="product-list">
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
  <li>
    <p class="product-name">XXXXX</p>
    <img class="product-image" src="XXXX">
  </li>
</ul>

1 Answers

CSS Flexbox can help you align your content, this can be scaled easily and doesn't require any JS.

For the example i removed the images and placed some random <br/> tags.

#product-list {
  display: flex;
  flex-wrap: wrap; /* Allow elements to overflow downwards */
  padding: 0;
}

#product-list li {
  flex: 0 0 calc(33.333333% - 10px); /* 33% for 3 column layouts, remove 10px because of margin left and right*/
  margin: 0 5px 10px;
  background: red;
  list-style-type: none;
  
  display: flex;
  align-items: stretch; /* Force same height on image and p tag */
}

p {
  margin: 0;
  background: green;
  flex: 0 0 50%; /* make 50% width of LI */
}

.fake-img {
  background: blue;
  flex: 0 0 50%; /* make 50% width of LI */
}
<ul id="product-list">
  <li>
   <p class="product-name">XXX<br/>XX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XX<br/>XXX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XX<br/><br/>XXX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XX<br/>XXX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XXXXX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XXX<br/>XX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XXXXX</p>
   <span class="fake-img">IMG</span>
  </li>
  <li>
   <p class="product-name">XXXXX</p>
   <span class="fake-img">IMG</span>
  </li> 
</ul>

Related