CodeinWP CodeinWP

What’s the Difference Between “:before” and “::before”?

Pseudo-FruitsWhen 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.

25 Responses

  1. bfred.it says:

    What about CSS2.1 browsers? I suppose this breaks the compatibility with them, so we have to wait until they’re phased out.

  2. 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 ;)

  3. Scott says:

    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.

    • Ashw00d says:

      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’

  4. David says:

    Thanks for the clarification.

  5. Lucica says:

    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.

    • Stephan says:

      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 an ol, the last p in a div 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)

  6. Gaurav M says:

    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

  7. onioneye says:

    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 :)

    • Stephan says:

      Cant find the link right now (@ iphone) but google Selectivizr. Or click through my site, I posted about it a week or 2 ago.

      • onioneye says:

        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 :(

    • syd says:

      any news about:before and :after ie7 enable script?
      Dean`s somehow works but totally mess the layout!
      Thx

  8. no says:

    ten years from now at some point Firefox gets as high as version 7

    you just had to get in that dig…

  9. megadroid says:
    
    Find string
    :before
    
    Replace with
    ::before
    
    > Replace All
    

    Of course this is still an extensive job if you own many projects.

  10. Rudd says:

    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.

  11. vimxts says:

    Before you know, Firefox’s version numbering has accelerated and it’s already 40 today!

  12. Holley says:

    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?

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).