Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS last three children only if condition

I'm trying to learn how to select the <li> among the last three elements of a <ul> such that their (one-based) index is greater than the greatest multiple of 3 which is smaller than the number of list elements.

So for example:

  • if there are 9 <li> elements in <ul>, I want elements 1-6 to have font-weight:normal and elements 7,8 and 9 to have font-weight:bold.
  • if there are 8 <li> elements in <ul>, I want elements 1-6 to have font-weight:normal and elements 7 and 8 to have font-weight:bold.
  • if there are 7 <li> elements in <ul>, I want elements 1-6 to have font-weight:normal and element 7 to have font-weight:bold.

I tried this CSS selector but it seems to make everything bold:

li:nth-last-child(1n+0),
li:nth-last-child(2n+0),
li:nth-last-child(3n+0) {font-weight:bold;}

How else do I do this?

like image 431
John Avatar asked Oct 18 '22 19:10

John


1 Answers

I think you want

li:nth-last-child(-n+3):nth-child(3n+1),
li:nth-last-child(-n+3):nth-child(3n+1) ~ * {
   font-weight: bold;
}

That is, it selects the element among the last 3 whose index mod 3 is 1. And then it also adds the following siblings (if any).

/* Tests */
document.styleSheets[0].ownerNode.textContent += ".fail { color: red; } .fail::after { content: ' - FAIL'; }"
for (var i=0; i<10; ++i) {
  var ul = document.body.appendChild(document.createElement('ul'));
  for (var j=0; j<=i; ++j) {
    var li = ul.appendChild(document.createElement('li'));
    li.appendChild(document.createTextNode(j+1+'-th item '));
  }
  for (var j=0; j<=i; ++j) {
    var li = ul.children[j];
    var isSelected = getComputedStyle(li).fontWeight === '700';
    if(isSelected !== (j >= Math.floor(i/3)*3)) li.className = "fail";
  }
}
li:nth-last-child(-n+3):nth-child(3n+1),
li:nth-last-child(-n+3):nth-child(3n+1) ~ * {
   font-weight: bold;
}

In case there are more than three elements, you can simplify it to

li:nth-last-child(-n+4):nth-child(3n) ~ * {
   font-weight: bold;
}

That is, it gets the element(s) among the last 4 whose index is a multiple of 3. And then it selects the following siblings.

/* Tests */
document.styleSheets[0].ownerNode.textContent += ".fail { color: red; } .fail::after { content: ' - FAIL'; }"
for (var i=0; i<10; ++i) {
  var ul = document.body.appendChild(document.createElement('ul'));
  for (var j=0; j<=i; ++j) {
    var li = ul.appendChild(document.createElement('li'));
    li.appendChild(document.createTextNode(j+1+'-th item '));
  }
  for (var j=0; j<=i; ++j) {
    var li = ul.children[j];
    var isSelected = getComputedStyle(li).fontWeight === '700';
    if(isSelected !== (j >= Math.floor(i/3)*3)) li.className = "fail";
  }
}
li:nth-last-child(-n+4):nth-child(3n) ~ * {
  font-weight:bold;
}

And if you dislike universal selectors,

li:nth-last-child(-n+3):nth-child(3n+1),
li:nth-last-child(-n+2):nth-child(3n+2),
li:nth-last-child(-n+1):nth-child(3n+3)

/* Tests */
document.styleSheets[0].ownerNode.textContent += ".fail { color: red; } .fail::after { content: ' - FAIL'; }"
for (var i=0; i<10; ++i) {
  var ul = document.body.appendChild(document.createElement('ul'));
  for (var j=0; j<=i; ++j) {
    var li = ul.appendChild(document.createElement('li'));
    li.appendChild(document.createTextNode(j+1+'-th item '));
  }
  for (var j=0; j<=i; ++j) {
    var li = ul.children[j];
    var isSelected = getComputedStyle(li).fontWeight === '700';
    if(isSelected !== (j >= Math.floor(i/3)*3)) li.className = "fail";
  }
}
li:nth-last-child(-n+3):nth-child(3n+1),
li:nth-last-child(-n+2):nth-child(3n+2),
li:nth-last-child(-n+1):nth-child(3n+3) {
  font-weight: bold;
}
like image 136
Oriol Avatar answered Oct 20 '22 09:10

Oriol