A Call for ::nth-everything

Avatar of Chris Coyier
Chris Coyier on (Updated on )

With CSS3, we have positional pseudo class selectors to help us select specific elements when there are no other distinguishing characteristics other than where it is in the DOM in relation to it’s siblings.

:first-child
:last-child
:nth-child
:nth-last-child

:first-of-type
:last-of-type
:nth-of-type
:nth-last-of-type

:only-child
:only-of-type

We also get a couple of text-specific pseudo elements to help with our typography needs:

::first-letter
::first-line

That’s a great start, but it really would be useful if we could extend the whole “:nth” concept to these typographic selectors. Let me convince you.

Please note that most of the code below is not valid. It’s example code. Like “wouldn’t it be cool if” code.

::nth-line() / ::last-line / ::nth-last-line()

We already have ::first-line, so to complete the set let’s add ::nth-line(), ::last-line, and ::nth-last-line().

With these, we could select the first two lines of a poem to highlight.

article.poem p:first-child::nth-line(-n+2) {
  font-variant-caps: small-caps;
  color: red;
}
I don’t know from poetry, Brendon.

Or perhaps we could fade out the end of a passage.

article.poem p:last-child::nth-last-line(3) {
   color: hsla(26, 5%, 25%, 1);
   font-size: 70%;
}
article.poem p:last-child::nth-last-line(2) {
   color: hsla(26, 5%, 50%, 1);
   font-size: 60%;
}
article.poem p:last-child::nth-last-line(1) {
   color: hsla(26, 5%, 75%, 1);
   font-size: 50%
}

If we were allowed to use generated content on these line pseudo elements, we could accomplish something like line numbering without having to resort to intrusive markup.

pre::nth-line(n)::before {
  content: counter(line) ". ";
  color: #999;
}
Look ma, easy practical multi-line code styling.

Relevant article by Adam Prescott.

::nth-word() / ::first-word / ::last-word / ::nth-last-word()

We currently don’t have any word-based pseudo elements. We do have word-spacing though, which is notable.

One use case is similar to using ::first-letter for drop caps, only doing a whole word.

article p::first-word {
  float: left;
  font-size: 300%;
  margin: 0 10px 10px 0;
}

Also similar to the “fade out” of lines above, we could fade out a passage word-by-word using ::nth-last-word(n).

::nth-letter() / ::last-letter() / ::nth-last-letter()

We already have ::first-letter, which sees pretty decent usage, so why not complete the set?

Of all of these “new” selectors, ::nth-letter is likely the most useful. For instance, Lettering.js wraps letters in s for us so that we can select individual letters. This would be entirely unnecessary with ::nth-letter.

Take this example:

h1.fancy::nth-letter(n) {
  display: inline-block;
  padding: 20px 10px;
}
h1.fancy::nth-letter(odd) {
  transform: skewY(15deg);
  background: url(light-red-pattern.png);
}
h1.fancy::nth-letter(even) {
  transform: skewY(-15deg);
  background: url(dark-red-pattern.png);
}
h1.fancy::nth-word(n) {
  margin-right: 20px;
}
h1.fancy::last-word {
  margin-right: 0;
}

Check out all the examples at Lettering.js — all of those are good examples of the need for this.

Another word/letter combination example is a formal “letter”, like:

Dear Emily,

yadda yadda yadda.

Love, Chris.

Perhaps this “letter” is generated by dynamic content from a database, but we want to ensure the proper capitalization and style of the opening and closing lines.

.letter p:first-child::nth-word(-n+2)::nth-letter(1),
.letter p:last-child:nth-word(-n+2):nth-letter(1) {
  text-transform: uppercase;
}

The Complete Set

So if we get all of this, the complete set would be:

:first-child        :first-of-type        :only-child
:last-child         :last-of-type         :only-of-type                  
:nth-child          :nth-of-type    
:nth-last-child     :nth-last-of-type

::first-letter      ::first-line          ::first-word
::last-letter       ::last-line           ::last-word
::nth-letter        ::nth-line            ::nth-word
::nth-last-letter   ::nth-last-line       ::nth-last-word 

Again, just wishful thinking. If there is anyone I can put this in front of that can do something about it, I will. And I’ll also keep this updated with the feedback on it, positive or negative.

For the record, this isn’t a new request. Anne van Kesteren called for it in 2003.