This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.

Title

TIL: <c>nth-of-type()</c> and <c>na+b</c> in CSS

Description

I've known about <c>nth-child(n)</c> for a long time. It selects the nth child from a structure if that child happens to match the given tag. You can always select the nth child by omitting the tag. For example, <c>div :nth-child(2)</c> (two selectors) will match the second child of any div, regardless of type. However, <c>div span:nth-child(2)</c> will only match if the second child is also a span. You cannot write a selector that says "select the second span" using <c>nth-child</c>. That's where <c>nth-of-type(n)</c> comes in. The selector <c>div span:nth-of-type(2)</c> does exactly that. I can't recall that I've ever had this need before, but it's also possible that I ended up adding extra tags or convoluted selectors in order to achieve what could have been more elegantly done with <c>nth-of-type</c>. Additionally, while I was aware that <c>nth-child</c> supported constants and the keywords <c>odd</c> and <c>even</c>, I didn't know that it also supported a formula <c>a<i>n</i> + b</c>. The <i>a</i> is a multiplier and <i>b</i> is an offset. With this formula, you can select every <i>third</i> or <i>fifth</i> (or whatever) element and then move the selection by a given <i>offset</i>. The selectors <c>first-of-type</c>, <c>last-of-type</c>, etc. also exist, as well as <c>only-of-type</c>, which matches an element when it's the only child of that type in the parent. See <a href="https://css-tricks.com/pseudo-class-selectors/" author="Chris Coyier" source="CSS Tricks">Meet the Pseudo Class Selectors</a> for more information. You may see where this is heading. The article <a href="https://chenhuijing.com/blog/the-wondrous-world-of-css-counters/#pure-css-fizzbuzz" author="Chen Hui Jeng" source="">The wondrous world of CSS counters</a> includes an example where he writes the famous FizzBuzz program with CSS. Start with an ordered list, <code>
  1. …add more li elements, like 30 of them…
</code> Then apply the following CSS to it, <code> ol { list-style-position: inside } /* To line-up all items neatly */ li:nth-of-type(3n+3), li:nth-of-type(5n+5), li:nth-of-type(3n+3):nth-of-type(5n+5) { list-style: none /* When text of Fizz, Buzz or FizzBuzz appears, get rid of the numbers */ } li:nth-of-type(3n+3)::before { content: "Fizz" } li:nth-of-type(5n+5)::before { content: "Buzz" } li:nth-of-type(3n+3):nth-of-type(5n+5)::before { content: "FizzBuzz" } </code> Put it all together and you get <a href="{att_link}css_fizz_buzz.html">CSS FizzBuzz</a>.