Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css last-child not working when adding divs of different classes

I have some HTML that looks like this:

<div class="SomeContainer">
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyOtherClass"></div>
</div>

And I use the following CSS

.MyClass{...}
.MyClass:last-child{box-shadow:0px 5px 10px black;}

I wrongly assumed that last-child operated on the last child of a certain class but it actually operates on the last-child of the container if it's of the same class.

Is there some convenient way around? I know I could add a wrapper around the MyClass div and add the CSS for the shadow to the wrapper but I was wondering if there's a better way to do it.

Thanks.

like image 526
frenchie Avatar asked Jan 15 '23 22:01

frenchie


2 Answers

Since you've already tried using CSS3 selectors then this is the correct pseudo class to use

.MyClass:last-of-type

According to CSS3 specification (at least as I understand it) this should work but it seems it doesn't. At least not in latest Chrome (v23) and Firefox (v17) browser versions.

WARNING: Upper information doesn't work and may be misleading that there's a pure CSS solution to this problem... Because as of CSS3 there's none. CSS4 on the other hand will have an additional pseudo class :nth-last-match(n) that will likely cover this exact scenario. But it's too early to say when not all CSS3 selectors have been implemented by browsers.

Additional investigation

Here's a JSFiddle that shows how this pseudo class selector actually works:

  1. get all elements that satisfy CSS selector (without pseudo)
  2. get their different HTML element types (tags)
  3. select all sibling elements of the same type (tag) for each type (tag) group
  4. Reduce each type (tag) group to the last element in the group
  5. Does this remaining element (of each group) satisfy selector (without pseudo)?
  6. If true then apply style otherwise don't

This means (as my example also shows) that several sibling elements can satisfy this selector as long as they're of different type.

This seems to work the same way in Chrome and Firefox. And if we carefully read specification it does say

The :last-of-type pseudo-class represents an element that is the last sibling of its type in the list of children of its parent element.

If it said that it's the last sibling that satisfied selector then my upper solution would work. So lets test my steps.

Run steps through using your HTML

  1. gets first 3 elements
  2. only one type: div
  3. four element (including the last one)
  4. reduce to the last one
  5. satisfies? No
  6. don't set style

Other couple of examples in my fiddle

Just to test this pseudo class selector behaviour I added two additional examples. Here's the HTML:

<!-- First -->
<div class="SomeContainer">
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div> 
    <p class="MyClass">Content</p>
    <p class="MyClass">Content</p>
</div>

<!-- Second -->
<div class="SomeContainer">
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div>
    <div class="MyClass">Content</div>
    <p class="MyOtherClass">Content</p>
</div>

In the first one two elements satisfy selector (last div and last p).
In the second one one element satisfies selector (last div)

Outcome

Having HTML that you provided and assuming that there can be an arbitrary number of elements with .MyClass there's no way to write a general selector in CSS3 that would actually target the last element with particular CSS class.

The best way is to add additional class to elements that represent the last one with particular class and write a selector to target that.

like image 58
Robert Koritnik Avatar answered Jan 17 '23 10:01

Robert Koritnik


It looks like last-of-type will only help you if you make your last element not the same as the rest, classnames don't seem to be relavant here. This example does correctly show two red squares, one green, the one blue.


.SomeContainer > div, .SomeContainer > span { width: 20px; height: 20px; background: red}
.SomeContainer > div:last-of-type {background: green}
.SomeContainer > span:last-child {box-shadow:0px 5px 10px black; background: blue; display: block}
<div class="SomeContainer">
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <div class="MyClass"></div>
    <span class="MyOtherClass"></span>
</div>
like image 33
Lincoln B Avatar answered Jan 17 '23 11:01

Lincoln B