Search code examples
csscss-selectorspseudo-class

Applying :nth-of-type to a pseudoselector rather than a class or element type (without jQuery or even JS)


I have this:

<ol>
<li class="letter">
<li class="letter">
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
</ol>

I want the first 9 of the li elements not of class "letter" to be styled a certain way. So, my thinking is, I select those not of class "letter", then select using nth-of-type:

li:not(.letter):nth-of-type(-n+9):before { ... }

However, this selects the first 9 regardless of class, the same result I get using:

li:nth-child(-n+9):before { ... }

I see examples out there of selecting based on E:nth-of-type and .c:nth-of-type. How come it stops there? Why can't I build a selection using nth-of-type off a pseudo-class like I can off an element or class? (Or can I somehow?)


Solution

  • Because the word "type" in :nth-of-type() specifically refers to "element type", and nothing else.

    Even examples that you see that qualify :nth-of-type() with a class selector are doing it wrong; they're really matching by the nth sibling of its element type, and not by its class. The class selector is there to say "only match this element if it has this class", and isn't actually considered when counting siblings. This is why you get the same result with both selectors in your example.

    With the current Selectors specification, you're not able to select the nth sibling that matches a complex combination of selectors, so what you want to achieve is currently not possible with CSS without knowing about or having control over the HTML structure. Of course, if you know that only the first two li elements will ever have the class then you could just do

    li:nth-child(n+2):nth-child(-n+9)::before { ... }
    

    But that's not very useful if your HTML structure will vary.

    There's an :nth-match() being proposed in Selectors 4 for this specific purpose, but no word on implementations yet. So for now, you're out of luck when it comes to pure CSS.