0

How do I target the last child of a class when there are siblings with another class after it? It would be nice to have a :last-sibling and :last-sibling-of-type.

FIDDLE

<div class="grid">
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div> /* How do I target this if its nth position is unknowable? */
  <div class="grid-orphan"></div>
  <div class="grid-orphan"></div>
  <div class="grid-orphan"></div>
</div>
Kirk Ross
  • 6,413
  • 13
  • 61
  • 104
  • possible duplicate : https://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class (there is the last-element variant but not able to find it ..) – Temani Afif Jun 10 '19 at 21:15
  • CSS is too short for this task. Add the second class (when you generated this markup) or use JavaScript. – pavel Jun 10 '19 at 21:17
  • 1
    If the only variant here is the number of grid-item, you can still use nth-last-child(4), but you might consider using a class modifier instead – Quentin Veron Jun 10 '19 at 21:35

4 Answers4

0

If you need to get the last .grid-item element out of the document, regardless of what it's inside, then you can't do that in CSS. In CSS, you can only select the first, last, or nth element at one particular level of the hierarchy, you can't select the last element of some type regardless of what it's nested in.

Here is one way to get the last div inside of .grid

.grid div:last-of-type

Here's another way to get the last child of some outer div:

div :last-child

BUT The thing you probably need is some js:

You could do this the jquery approach (like below), or just do getElementsByClassNameand then set the last element in the list in the same manner.

function getlastchild() {

  var items = $(".grid-item");

  items.last().css("background-color", "red");
  //OR even as one-liner: $(".grid-item").last().css("background-color", "red");

}
.grid {
  width: 200px;
}

.grid div:last-of-type {
  color: white;
}

div:last-child {
  background-color: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="grid">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-orphan">5</div>
  <div class="grid-orphan">6</div>
  <div class="grid-orphan">7</div>
</div>

<button onclick="getlastchild()">Press me to get last grid-item</button>
DigitalJedi
  • 1,577
  • 1
  • 10
  • 29
0

I see 4 possibilities here:

Case 1:

You already know the number of grid-orphan items, so you can use nth-last-child.

.grid-item:nth-last-child(4) {
    background: blue;
}

Case 2:

You are an adventurer and this is not for production: use the newest version of nth-child and nth-last-child:

.grid-item:nth-last-child(1 of .grid-item) {
    background: blue;
}

However, it only works on Safari for now (12.99%).

See specs

Case 3:

Use JavaScript.

const items = document.querySelectorAll('.grid-item')
const selectedItem = [].slice.call(items).pop();

selectedItem.style.background = 'blue';

Case 4:

Just add an extra class.

<div class="grid-item grid-item--special"></div>
.grid-item.grid-item--special {
    background: blue;
}
Quentin Veron
  • 3,079
  • 1
  • 14
  • 32
  • This is great. For case 1 I think you meant just "last-child" as nth-last-child is Case 2. – Kirk Ross Jun 11 '19 at 06:26
  • I meant `nth-last-child` for both cases. Just note that the first case is in the context of all children (*grid-item* and *grid-orphan*) while the second one is in the context of *grid-item* only. – Quentin Veron Jun 11 '19 at 06:52
-1

You can use either :nth-last-child or :nth-last-of-type if you are able to put all your .grid-orphan elements inside another div.

HTML

<div class="grid">
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-item"></div>
  <div class="grid-orphans">
    <div class="grid-orphan"></div>
    <div class="grid-orphan"></div>
    <div class="grid-orphan"></div>
  </div>
</div>

SCSS

.grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;

  .grid-item {
    background: gray;
    border: 1px solid white;
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100px;
    width: calc(25% - 20px);
    min-width: 360px;
    flex-grow: 2;
    justify-content: flex-start;
    cursor: pointer;

    &:nth-last-child(2) {
      background: navy;
    }
  }

  .grid-orphan {
    height: 0;
    border: 0;
    display: flex;
    flex-direction: column;
    width: calc(25% - 20px);
    min-width: 360px;
    flex-grow: 2;
    justify-content: flex-start;
    cursor: pointer;
  }
}

Jsfiddle available here.

Otherwise, a CSS-only approach would be limited to only Apple's browsers, that is Safari desktop and on iOS, since they are the only ones that implement the selector list argument, which allows you to narrow down the elements by a class selector. For seeing this just change &:nth-last-child(2) with &:nth-last-child(1 of .grid-item)

Siavas
  • 4,992
  • 2
  • 23
  • 33
-1

All those answers are great. Thank you. I ended up just making the orphans <span>'s and then .grid-item:last-child worked fine. I knew I could do that but was wondering if it could be done (easily) when the orphans were the same element type as the grid items.

Kirk Ross
  • 6,413
  • 13
  • 61
  • 104
  • 1
    You mean `.grid-item:last-of-type`? – Quentin Veron Jun 11 '19 at 10:35
  • Quite likely he did `last-of-type` @QuentinVeron. OP, as you are able to change your markup I'd rather do it with my approach (nesting `.grid-orphan`s into another div and using `.nth-last-child(2)`. [`span`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span) should be used only for phrasing content. – Siavas Jun 11 '19 at 13:24