Reputation: 101
<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
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
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
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