Séane
Séane

Reputation: 101

Hide list items if more than a certain number exist

<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
</ul>

What I would like is for / within each <ul class="parent">:

If count is: 3 > li <=6 hide the <li> above 3. If it is 6 > li <=9, we hide the <li> above 6.

In fact, I have a row with elements. I always want to display 3 elements per row, but when there is less than 3 element on the last row, I want to hide this row completely.

Additionally, depending on the size of the browser (this seems to be easy), I want to change the factor number to 4 elements per row.

This does not seems to be possible in pure CSS, so I'm turning towards JS.

Upvotes: 2

Views: 4030

Answers (3)

S&#233;ane
S&#233;ane

Reputation: 101

Based on @soulshined answer, I was able to do what I was looking for. Thank you all for your kind answers.

If width below 960, allow only 3 items per line, up to 6 items max. If on second line there is less than 6 items (and more than 3, first line), hide all of the items.

If width above 960, allow 4 items per line, up to 8 items max. If on second line there is less than 8 items (and more than 4, first line), hide all of the items.

Code:

@media screen and (max-width: 960px) {
  .product-sheet {
    width: calc((100% / 3) - 34px);
  }

  .product-list-tpl .product-sheet:nth-child(n + 7) {
    /* select all but the first 6 elements, allow 2 rows of 3 elements (3 X 2) and hide them */
    display: none;
  }

  .product-list-tpl
    .product-sheet:nth-child(n + 4):nth-last-child(-n
      + 2):not(:nth-child(5)):not(:nth-child(6)) {
    /* select all but the first 3 elements, so 4 and above and select the element before the last (last-1) of the list, so position 1 in second row / 4th item and hide it */
    background: red;
  }

  .product-list-tpl
    .product-sheet:nth-child(n + 4):nth-last-child(-n + 1):not(:nth-child(6)) {
    /* select all but the first 3 elements, so 4 and above and select the last element, so position 2 in second row / 5th item and hide it */
    background: purple;
  }
}

@media screen and (min-width: 960px) {
  .product-sheet {
    width: calc((100% / 4) - 34px);
  }

  .product-list-tpl .product-sheet:nth-child(n + 9) {
    /* select all but the first 8 elements, allow 2 rows of 4 elements (4 X 2) and hide them */
    display: none;
  }

  .product-list-tpl
    .product-sheet:nth-child(n + 5):nth-last-child(-n + 1):not(:nth-child(8)) {
    /* select all but the first 4 elements, so 5 and above and select the last element, so position 3 in second row / 7 th item and hide it */
    display: none;
  }

  .product-list-tpl
    .product-sheet:nth-child(n + 5):nth-last-child(-n
      + 2):not(:nth-child(7)):not(:nth-child(8)) {
    /* select all but the first 4 elements, so 5 and above and select the element before last element, so position 2 in second row / 6 th item and hide it */
    display: none;
  }

  .product-list-tpl
    .product-sheet:nth-child(n + 5):nth-last-child(-n
      + 3):not(:nth-child(6)):not(:nth-child(7)):not(:nth-child(8)) {
    /* select all but the first 4 elements, so 5 and above and select the last element, so position 1 in second row / 5 th item and hide it */
    display: none;
  }
}

Upvotes: 1

soulshined
soulshined

Reputation: 10612

This does not seems to be possible in pure CSS

Challenge accepted.

The trick is to cascade nth counts, but only if it is x away from last child. Disclaimer, I kind of "cheated" to exclude some elements like :not(:nth-child(5)), but this comes at an advantage of not using things like !important

.parent li:nth-child(n+4):nth-last-child(3):not(:nth-child(5)):not(:nth-child(6)) {
 display: none;
}
.parent li:nth-child(n+4):nth-last-child(-n+2):not(:nth-child(6)) {
 display: none;
}
.parent li:nth-child(n+4):nth-last-child(-n+1) {
 display: none;
}
.parent li:nth-child(n+7) {
 display: none;
}




/* just for styling */
body{ 
  display: flex;
  flex-flow: row wrap;
}

ul:before {
 content: "I started with " attr(data-count) " li's";
 background-color: lightgrey;
}
<ul class="parent" data-count="3">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
</ul>

<ul class="parent" data-count="4">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
</ul>
<ul class="parent" data-count="5">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
</ul>
<ul class="parent" data-count="6">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
</ul>
<ul class="parent" data-count="7">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
</ul>
<ul class="parent" data-count="8">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
</ul>
<ul class="parent" data-count="9">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
</ul>

By the way you asked way to many questions in the OP, so I elected to provide a solution to what I think is the priority of your question. You can adjust accordingly.

Upvotes: 5

kockburn
kockburn

Reputation: 17616

Using Array#forEach and accessing the children of ul's you can do something like this.

const uls = Array.from(document.getElementsByClassName("parent"));

const factor = 3;
const offset = 3;
uls.forEach(ul=>{
  const children = Array.from(ul.children);
  
  //if less than 3 hide everrything
  if(children.length < factor){
    children.forEach(li=>li.style.display = "none");
    return;
  }
 
  //default config to hide from 3 to 6
  let start = factor;
  let end   = factor + offset;
  //if length is greater than 6 and shorter than 9 hide those lis
  if(children.length > 6 && children.length <= 9){
    start = 6;
    end = 9;
  }
  
  children.slice(start, end).forEach(li=>li.style.display = "none");
  
});
body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
  <li class="children">3</li>
  <li class="children">4</li>
  <li class="children">5</li>
  <li class="children">6</li>
  <li class="children">7</li>
  <li class="children">8</li>
  <li class="children">9</li>
  <li class="children">10</li>
</ul>
<ul class="parent">
  <li class="children">1</li>
  <li class="children">2</li>
</ul>

Upvotes: 1

Related Questions