When using or researching CSS pseudo-elements, you may have come across different syntax for the :before
and :after
pseudo-elements, specifically in the form of a preceding double colon, instead of the traditional single colon. This seems a little confusing at first, but there’s actually a pretty simple explanation.
I had assumed that there would be some difference in the way each functioned, but that’s not the case, as the short and long answers below make clear.
The Short Answer
Putting aside browser support, there’s no difference between :before
and ::before
, or between :after
and ::after
.
The Long Answer
The single colon syntax (e.g. “:before” or “:first-child”) is the syntax used for both pseudo-classes and pseudo-selectors in all versions of CSS prior to CSS3. With the introduction of CSS3, in order to make a differentiation between pseudo-classes and pseudo-elements (yes, they’re different), in CSS3 all pseudo-elements must use the double-colon syntax, and all pseudo-classes must use the single-colon syntax.
The spec says:
This [double-colon] notation is introduced … in order to establish a discrimination between pseudo-classes and pseudo-elements. For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after). This compatibility is not allowed for the new pseudo-elements introduced in CSS level 3.
Too Little Too Late?
While I certainly welcome beneficial improvements made to the spec, it almost seems like this change is happening too late. There are literally hundreds of millions of web pages out in the wild with stylesheets that could be using the single-colon syntax for pseudo-elements.
As the above quote points out, all modern user agents must support the old syntax, basically for all eternity. For example, if ten years from now at some point Firefox gets as high as version 7, they still have to support the single-colon syntax in order to avoid “breaking the web”.
So what’s the point of even doing it? It seems like a case of too little too late. Yes, modern websites will have the newer syntax, but only if the developers are keeping up with these changes — which is going to be the case for only a small percentage of developers.
I guess, if anything, it serves to help differentiate the two kinds of selectors for easier maintenance of stylesheets.
What about CSS2.1 browsers? I suppose this breaks the compatibility with them, so we have to wait until they’re phased out.
I like to think developers are good at keeping up with things like this…but obviously there are some slackers out there just writing code that gets by ;)
Yeah I never understood this. What is the need to differentiate between pseudo-selectors and pseudo-elements? I think the usage is pretty clear from the selector. You couldn’t really have
:before
adding a pseudo class, for example. Selecting “stuff before the specified element” is vague and ambiguous.Agreed, is there really a need for this? If you have to rely on a double colon to differentiate between a pseudo-selector and pseudo-element then should you really be coding?
Also I’m sure the W3C have bigger problems to worry about then pushing the use of a double colon to make things ‘pretty’
Thanks for the clarification.
The interesting thing is that CSS2 specs say that :first-child is a pseudo-class but :first-line, :first-letter are pseudo-elements. You can read about them here: http://www.w3.org/TR/CSS2/selector.html#pseudo-elements.
CSS3 draft specs consider the same: http://www.w3.org/TR/css3-selectors/#pseudo-classes.
For me the difference is not so big so I suppose that only working with them on a regular basis will help us switch to the new rules and forget about the old ones.
Yeah, the CSS3 spec still considers the single-colon syntax acceptable for any pre-existing pseudo-elements, so I guess it’s not technically “obsolete” (which goes back to my point about why they’re even doing it).
But if a pseudo-element is introduced in CSS3 (i.e. it didn’t exist in CSS2), then it must have the double-colon syntax (as in the case of “::selection”).
In other words, if you write “:selection” (with one colon) then browsers should not recognize that, because it must be written with a double colon. But you can write “:first-line”, even though it’s a “pseudo-element” and part of CSS3. Kind of confusing, but that’s how it is.
I don’t think it’s so strange at all that :first-child is a pseudo-class yet ::first-line and ::first-letter are pseudo-elements.
Think of it this way: a :first-child, :last-of-type or :nth-child() is an entire element, like the first
li
in anol
, the lastp
in adiv
or whatever. Because the entire element is selected by this rule, all that has to be used to style it is a pseudo-class.::select, ::before and ::first-line however are not already existing elements by themselves, but rather parts of an element. To give that particular part of the document another style, a pseudo-element is wrapped around it with the proper style. In the case of::select, think of it as surrounding the selected part with a
span
and then styling that. It’s a pseudo-element, because there wasn’t a real element available to add the style to.I hope that makes it a little easier to understand/memorize the difference?
(Also: Louis, a preview button would be really useful, I’m always afraid I butterfly up my code examples)
::select should be ::selection, sorry.
First of all thanks for this article.
It makes me thinking about this again.
Thx Stephan for this explanation.
It may sound a bit crazy imagining a span in the DOM. But that helped me to finally get this right.
If the entire Element is selected it is a class! Thats easy enough!
thanks Stephan, it does make a lot of sense
That makes a lot of sense. Thank you.
Yes! this :before and :after is making lot of waves via crazy drop shadows, borders in web space these days. Enough to droll web workers
I started using :before and :after pseudo elements for a lot of things lately (multiple borders and backgrounds, generated content etc.), but with a single colon syntax. I should probably change this habit now to get used to the new rules defined in the CSS3 spec :)
BTW, Dean Edward’s IE8.js script doesn’t seem to enable :before and :after pseudo elements in IE7. I’ve used IETester and Expression Web Superpreview for IE to check if it works, but none of these are showing my pseudo elements on the page. If anyone knows the alternative way to enable these in IE7, please share it with me.
Thanks :)
Cant find the link right now (@ iphone) but google Selectivizr. Or click through my site, I posted about it a week or 2 ago.
Thanks a lot for trying to help me Stephan, but I don’t believe this will work :) You see, I knew about Selectivizr for some time now and that it only supports two pseudo elements, namely ::first-letter and ::first-line, but not ::before and ::after as well :(
Hmm, appears you’re right. Afraid I can’t help you then :(
any news about:before and :after ie7 enable script?
Dean`s somehow works but totally mess the layout!
Thx
ten years from now at some point Firefox gets as high as version 7
you just had to get in that dig…
Heh, i’m downloading Firefox 10 atm lolz
Yeah, when I wrote that FF was not yet at version 4.
And they hadn’t started the rapid-release schedule. So I never would have thought that versions 1-4 would take something like 8 years, while versions 4-10 would take less than 1! :)
Of course this is still an extensive job if you own many projects.
Thanks for your explanation.
I’m designing a theme via a child theme, and it gets me confused when I saw the ::before being used.
Before you know, Firefox’s version numbering has accelerated and it’s already 40 today!
So now it’s ff version no. 50! and your article and the discussion about two or four little points meaning half the world of a designer still goes on. ;)
I just happened to notice that even font awesome ist using the pseudo-element “before” and “after” with just one colon – even today.
So the rebellion goes on?