0

I need to get the last li that has an <a> as child.

<li> test A </li>
<li> <a> test B</a> </li>
<li> test C </li>
<li> <a> test D</a> I want to select this one!</li>
<li> test E </li>
<li> test F </li>

I would need something like:

(li>a):last-child

li {
  background: #babaca;
  border: 1px solid #E4E4E4;
}
li > a {
  background: green;
}

(li>a):last-child {
  background: red;
}

li:last-child{
  background: yellow;
}
<li> test A </li>
<li> <a> test B</a> </li>
<li> test C </li>
<li> <a> test D</a> I want to select this one!</li> 
<li> test E </li>
<li> test F </li>

Any ideas?

Jon P
  • 17,053
  • 7
  • 44
  • 64
  • 2
    well, the short answer is you cannot with CSS (I mean a generic solution to work no matter the number of li and a are) – Temani Afif Feb 12 '18 at 22:00
  • CSS doesn't have any selectors that _ascend_ the tree, only _descend_. (`:has()` is the exception, but is only due to be implemented in JS, and has yet to be done) – jhpratt Feb 12 '18 at 22:19
  • Unfortunately, there is no CSS selectors for this. And no combination of existing selectors can do it either. You best bet is to use JavaScript/jQuery. – Studocwho Feb 12 '18 at 22:24
  • Possible duplicate of [Is there a CSS parent selector?](https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector) – Jon P Feb 12 '18 at 23:31

1 Answers1

0

As other's have commented, this isn't possible with CSS at this time. The :has pseudo-class selector might provide for a way down the road.

In the meantime, here are a few options:

#1 Use jQuery's :has selector

$("li:has(a):last").addClass("last");
li {
  background: #babaca;
  border: 1px solid #E4E4E4;
}

li > a {
  background: green;
}

li.last {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul id="list">
  <li> test A </li>
  <li> <a> test B</a> </li>
  <li> test C </li>
  <li> <a> test D</a> I want to select this one!</li>
  <li> test E </li>
  <li> test F </li>
</ul>

#2 A small plain JavaScript function to find and apply a .last class to the last li > a element.

The function findLastA() accepts a selector to target a ul element, then finds the last li containing an a element, and applies the .last class to it.

Keep in mind this is made specifically for the HTML structure outlined in the question.

function findLastA(el) {
  var listItems = Array.from(document.querySelectorAll(el + " > li"));
  for (let i = listItems.length - 1; i >= 0; i--) {
    let childNodes = listItems[i].children;
    if (childNodes.length && childNodes[0].tagName === "A") {
      listItems[i].classList.add("last")
      break;
    }
  }
}

// Call the function
findLastA("#list");
li {
  background: #babaca;
  border: 1px solid #E4E4E4;
}

li > a {
  background: green;
}

li.last {
  background: red;
}
<ul id="list">
  <li> test A </li>
  <li> <a> test B</a> </li>
  <li> test C </li>
  <li> <a> test D</a> I want to select this one!</li>
  <li> test E </li>
  <li> test F </li>
</ul>
Brett DeWoody
  • 50,328
  • 25
  • 121
  • 168