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.
::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;
}
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;
}
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.
Great idea, Chris!
How about “first-sentence, last-sentence, nth-sentence, and nth-last-sentence”?
Cool thought! How would you determine exactly what a sentence is though? All the text up until a period?
What about:
Mr. Penguin forgot his shoes in St. Augustine.
I haven’t thought about it for very long, but at a glance it seems like it would be pretty hard to make smart enough to be useful.
Yeah. . . I thought about that. You might, in certain time, get away with a: Period followed by a space, followed by a capital letter. But, that would make your example three sentences. Maybe it’d interpret “.” as the end of a sentence, and . as anything else?
Whoops. . . It took that literally. It’s supposed to be:
o
Hmm. . . Still didn’t work. I’ll put spaces in between the characters this time: & # x 2 E ;
dots is the KING! :D
Don’t sentences also end with question and exclamation marks?
Well, they’re a little easier to deal with, because you’re probably not going to encounter them in the middle of a sentence like you might periods.
How about if the period, exclamation point, and question mark are assumed to represent the ends of sentences and, if there are special cases involving periods within sentences, they require encoding?
Mr. Penguin forgot his shoes in St. Augustine.
Well that didn’t come out well — looked good in the preview though.
A period can be encoded with & # 46;
That was what I was trying to say earlier with
& #x2E;
.Or regular expression selectors that let you select any text you like (define your own “sentence”).
Looooove you.
Let’s :nth() all the things!
http://memegenerator.net/cache/instances/400x/10/10783/11042610.jpg
That was great, I had Coke coming out of my nose here at work :)
This makes good sense. I’d love to see more powerful tools like this built into CSS.
Great ideas Chris :)
Are you going to do something with this if you get enough responses? Can you submit it to the CSS working group for spec consideration/inclusion?
Well Microsoft Word seems to do a good job with it. Word recognition, fragments, etc. I’m sure an algorithm could be created to pretty accurately determine that.
Great article btw. Really good ideas in there.
Wow, great idea.
All I want for Christmas is a parent selector; x < y.
But yes, these would give us a lot more control over styling so I’m all for it!
If you see CSS 4 spec draft the parent selector is already being considered.
Hot damn! :)
What about not equal i.e. <> selectors?
I hope at least some of this gets implemented soon.
::nth-line
alone would be excellent for line numbering. Even an unintrusive solution without presentational markup today still requires a touch of JavaScript to hook into lines.I’m almost certain that these selectors (or ones similar to their functionality) will be added to CSS4.
I took the liberty to post this to the CSS WG mailing ist.
Let’s see if anyone picks it up, especially Fantasai (Elika Etemad) who is the editor of CSS 4 selectors.
Rather than have an epic ton of selectors, why not use more programmatic approaches:
::nth-child()
::nth-line()
::nth-word()
::nth-letter()
Then allow numerical specification for first, last and patternistic:
::nth-line(0) — first line
::nth-word(-1) — last word
::nth-letter(5n) — every 5 letters
I second you sir
Can I add these to this year’s Christmas list?!? Better yet, let’s vote Chris the next WC3 President! Seriously though, this truly addresses the gap between print and web in everything my organization publishes. Anything that carries traditional (and time-honored) print layout techniques to new media is better for everyone anyway.
I would love a :mod-nth-child where you can specify a modulus so you can do interesting things with every 3rd child or something.
Wouldn’t nth-child(3n) select every third child? Read this if you haven’t already: https://css-tricks.com/5452-how-nth-child-works/ . Of course, it’s likely that I totally misunderstood what you want!
That ‘fit to scale’ example looks great!
Very useful for blogazine maniacs! :D
First letter would be great!
We already have first-letter.
great tips. will start using soon.
Thanks Chris.
These were not tips, they were simply wishful thinking. If you attempt to use these they will not work.
One complication is that in some languages / writing systems (Thai, to pick one) words aren’t distinguished by spaces, so defining “nth word” is non-trivial.
Great read as always Chris!
I’m thinking of SitePoint’s “Make Your Own Custom jQuery Selector” (http://ow.ly/7fdQK) and take that for a spin. Yes, yes, it isn’t CSS as we would like it of course, but it could be a start?
Again, if you think about LESS.js, they’ve added their own “&:”, which I think is exclusive to .less files. So that must mean that it could be possible to extend the LESS.js code with the same structure that made the “&:” possible, just with this problem in mind instead? Could be one way. :)
Keep up the amazing work! Your Lynda guide on WordPress really helped me out some time back, thanks for that.
I can only say one word Chris:
COOOOOOOOOOOOOOOOOOOOOOOOOL
man, I knew almost everything about CSS3 new selectors, but I could never think of these usages you mentioned here. Also your new suggestions are exceptionally useful and practical.
wow, so cool. I just know css3 is so powerful. many thanks for share.
There’s some really nice ideas in there Chris. My favourite example is with line numbering for code, something which is generally a pain to markup!
Nice list!
I am going to support some of these nth-everything things in my own JavaScript Engine (wjSelect).
Really like the idea of a :nth-lat-word style selector, I was recently creating a “fade out text at bottom into a read more anchor” style effect (instead of … ). Ended up using positioning and gradients which worked Ok in that scenario but wouldn’t all.
My ratio of caffeine to sleep is insufficient to fully parse these concepts. But I can tell it’s interesting.
wait…what did I just say?
I’ve been thinking similarly just recently – very well put sir!
Dang! I doubt I would have thought of this, but man these things look like they could be handy. Now I’m going to be spending the next little while looking into polyfills.
Good list.
Awesome,, this is useful for me.
nice examples you have mentioned chris………..surely helpful for us.
Good thinking Chris…I was just thinking this would be a neat idea for headline replacement on blog article summaries. In fact you wouldn’t have to write any headlines at all, or add any heading or span tags in your markup…just have the first sentence of the paragraph automatically highlighted in the style of your choice w/link to full article.
Excellent. Where do you find the time to think up these awesome improvements to where we are now? I can’t keep up with what is already out there, let alone extend it into new territory.
What’s the difference between
:after
and::after
/ Your post (this one) suggests that some selectors use a single colon, and some others use a double colon. If so, that how to know which one to use and for what?@aaron:
There are in CSS psuedo classes and psuedo elements. There is no difference between this types in CSS2, but in CSS3 there is a difference.
To make it more logic the developers of CSS added a rule that psuedo elements have a double colon and psuedo classes a single colon.
For instance, an element is ::first-letter. And an class is ::first-child.
You should see it in this way:
With ::first-letter you grab the first letter and push a span around it:
NOTE: This don’t happend in a browser
A span is an element, so psuedo elements.
With :first-child you have more than one child:
With first-child you give a class to the first child. So this is an psuedo class.
So isn’t
::after
and::before
also pseudo-elements? Don’t we usually use:after
and:before
? And I thought pseudo-elements meant false elements, elements you create through CSS. Essentially, I can look at it this way: I create a new element that contains only the first letter of the paragraph, and I style that new element. But when I’m using:first-child
, I’m actually selecting some element already there in the HTML.And what’s the difference between DOM and HTML? What is the full-form of DOM?
Hey guys, what do you think of the AXR Project? Here’s a small alideshare presentation: http://goo.gl/8O6gK
My instinct is that of a vampire who faces garlic (halloween).. It looks kinda exciting tho with being able to move away from images etc in an even more extensive way than what we have.. Altho at a quick glance some things seemed more complicated than html/css when presented as “easier”.
We’d be glad to hear anymore oppinions on this, Jonathan.
I love :nths. But that’s because I care. Most end users will not have the mindset where using these subtleties (which require a modicum of abstraction and imagination to usefully implement) will deliver real benefits, so I don’t don’t how high up on the list of priorities they will be.
Take http://www.nthdegree.com/ for example – please tell me this is a very subtle spoof… my eyes were more glazed than a hand-fired raku pot. I’m squeaking excitedly with anticipation over what they do with ::nth-last-letter :)
‘don’t don’t?’ That was meant to say ‘don’t know’ – see, a grammar-checker is way higher on the list :)
Wonderful ideas — and I’m with Alex Mellor on the value of a parent selector.
I like the potential of ::first-word.
for me this is like a language from hell, i dont understand anything haha
Chris, thanks for your work on this.
I just recognized that there is `p:last-child::nth-last-child(3)` aso. in the second example. Shouldn’t this be `p:last-child::nth-last-line(3)`? Or am I missing the point?
Yep that was incorrect, fixed now.
Thanks! That’s great!
Very cool suggestions to add to the spec. Also, if nth-line would be an inline pseudo-element this would enable easier “Multi-Line Padded Text”. Double win!
Ps. Those fake comments are very annoying. Couldn’t a recaptcha help solve this?
::nth-child()
::nth-line()
::nth-word()
::nth-letter()
last-line
last-child
last-word
all of them above not working for me any one help me to know how to use this
This whole article is about the stuff not working yet. If you really need the functionality, check into jQuery plugins.
Clearly with all of these comments, there are a lot of people thinking the same thing.
Here’s hoping that at least some of these ideas make it in to CSS4.
Dammit – I actually thought these were real, and tried to use them, until I properly read that they were just drafts of possible ideas for implementations.
This is awesome. God awful awesomeness. Thanks for publishing this as I was wondering in there was a global CSS command for differentiating text color.
While we are wistfully wishing for selectors how about:
Sometimes you might want to color an ::character(‘@’) differently, or not use italics on a | or use a different font for number characters, or make all instances of your company name red ::word(‘Apple’) , all swear words display: none or whatever!
I’d love the ability to match subsections of text node content.