Grow your CSS skills. Land your dream job.

Use Cases for Multiple Pseudo Elements

Published by Chris Coyier

I used to do an entire talk on pseudo elements. One of the things I mentioned was that there used to be a CSS3 spec that included "multiple" pseudo elements, but it was removed. That was kind of a bummer, because sometimes just ::before and ::after aren't enough. Why the seemingly arbitrary limitation?

Now Alan Stearns from Adobe is heading up a new draft for the CSSWG for getting this added back to the spec (and make it work in browsers). He needs some help! He needs visual use cases on why designers want this.

One example I thought of right away was the speech bubble thing. The speech bubble arrow can be made from a pseudo element, but what if you need those pseudo elements for other things? For instance, a blockquote might have opening and closing quotes around it.

Or you might need to use the clearfix on it if it's possible there are floated elements inside. The clearfix (usually) uses both available pseudo elements on an element.

On a larger scale, take a browse around CodePen. There are lots of awesome examples like this one with a shooting tank. A lot of those style demos are built from a big set of HTML elements for each part of them. Why pollute the DOM with semantic elements used for non-semantic purposes? All this stuff could be done with pseudo elements instead.

So let's have it folks! What are some use cases you've come across where you wanted multiple pseudo elements but didn't have them? Helping Alan out with this helps move the web forward.


  1. William Malo
    Permalink to comment#

    Having more :before and :after pseudo elements is sometimes useful, but what would really be amazing a wrapper pseudo element. I would allow hacks like “uncle dave’s box” to be made with one element instead of 2 (sometimes even 3).

  2. Reinier Kaper
    Permalink to comment#

    Blockquotes should have paragraphs in them, so you could target the first and last paragraphs for the quotes and still use the pseudo elements on the blockquote ;-)

    But I think it would be nice if you could chain pseudo elements, like:

    Although that would get a little messy I guess ;-)

  3. William Malo
    Permalink to comment#

    Could also allow complex css animations without 100 divs.

    It would be very useful for people who work on css, but that aren’t allowed to modify the html.

    Personally 1 in 2 of my websites have non-semantic divs in them… and I think all of them have superfluous tags like a link inside a li tag, or a p inside an article…

    It kindof annoys me sometimes.

  4. This is something I’ve always wondered about. Perhaps setting it like this would work? It seems like a good way to do it, because multiple elements could call upon the same predefined pseudo element.

    @pseudo-element nameOfElement {
    //css properties here
    @pseudo-element otherElement {
    //css properties here
    .element {
    pseudo-before: "nameOfElement, otherElement";
    pseudo-after: "otherElement";
    • This looks like a really mature solution I could definitely work with. It would be so much more scalable than chaining pseudo elements (on a side note you’d totally get mixed up with ::before::after and ::after::before) or making ::more up. It also fits in with the sass syntax you’d get by embedding pseudo elements as we are now.

      @mixin pseudo-before {
      // css
      @mixin pseudo-after {
      // other css
      .element {
      &::before  {@include psuedo-before;}
      &::after {@include psuedo-after;}
  5. Ryan
    Permalink to comment#

    I can already imagine the support threads: “No, ::after comes before ::after::after, and ::before::before comes before ::before… not after!

  6. Strangely enough I was monkeying with a circle today that did some folding panel business using :before and :after and I was all like…

    “I want more panels but I only have 1 :before pseudo and 1 :after pseudo and I need extra pseudos so I can have more panels to flip through. AHHHH SHIZ!”

    Pseudo Example

  7. Salman Abbas
    Permalink to comment#

    Would be awesome if this gets added to the spec.

    Also, how about ::outer-before and ::outer-after for “replaced elements”.

  8. Permalink to comment#

    I would love to be able to make a 3D cube using a single element. I have been able to create something that is pretty close (, but the rotations are limited, as it is really only the front three panels!

  9. What would make more sense is:

    div::before {} /* Same as ::before(1), but applies also to all subsequent ::before's
    div::before(2) {}
    div::after(1) {}
    div::after(2) {}
    div::after(3) {}
    • Geoff Thibeau
      Permalink to comment#

      I’d like to extend Corey’s method to behave like :nth-child selectors.
      E.g., ::before(2), ::before(2n+1)

      Not sure how you would specify how many existed though. Perhaps as a property?
      element{ margin:0; before:6; after:2; }

      But this way you could open all kinds of possibilities for CSS to replace images and/or extra elements.

    • cnwtx
      Permalink to comment#

      Excatly my idea! Even include something like ::before(even) or ::before(-1) To specify even/odd and count backwards from the end, or even something like :first-line::after(2).

  10. James
    Permalink to comment#

    I want to see a pseudo-element :bad-ass in the spec. I don’t care what is does, I just want to see that in the spec.

  11. Ryan Wheale
    Permalink to comment#

    A common use case for me is having a bordered box with a bordered arrow… which is accomplished by having a smaller :after arrow sitting on top of a slightly larger :before arrow to give the appearance of the border. However, this ties up both of the pseudo elements.

    I have gotten in the practice of realizing these situations while I am building DOM and going ahead and coding up an inner-wrap element for all my other potential pseudo-element needs. I know it’s not exactly semantic… but consistency and future flexibility trumps semantics for me :(.

  12. I like the way you present new introductions Chris. Use these pseudo classes while styling blockquotes and pictogram nav.

  13. Permalink to comment#

    That’s my tank ! But I have to agree, it sucks that I had to use many elements to such a purpose.

    Actually, I came to a point where I don’t even take the time to think about how could I use pseudo-elements to reduce the number of elements in the DOM when I use more than one or two elements in it. It doesn’t worth it, or not on CodePen demo’s at least.

    Long time since I wanted multiple pseudo-elements to build some absolutly non-semantic things (such as a shooting tank crossing the screen). Something like #element:before:after:before:before… or better #element:pseudo(N).

    • Shaun Lynn
      Permalink to comment#

      I really like your idea of combining ::after and ::before into a single pseudo-element like ::pseudo(x). I think the names ‘before’ and ‘after’ are acting as arbitrary semantic limitations due to their real world associations. It’s harder to argue the case that you need multiple pseudo elements if a physical object normally only has a single back and front. The current spec is inadvertently applying a flawed analogy to HTML elements.

  14. Make a site logo with just an anchor element: <a id="logo" href="/">My Site!</a>
    Although, I think there’s one thing I desire. Even if we can’t make multiple pseudo-elements, but at least I hope they can be compared with the original element: Selectable, and Transitionable (transitionable as well as on Firefox) :\

  15. Benjamin
    Permalink to comment#

    You can make a image hover effect without additional markup (a.img-sprite-hover-fade:hover:after):

    Sadly CSS-Transitions dont work in current browser versions on generated content..

  16. Hmm it looks like a really nice addition to the CSS specs, but what I do not understand is that you are asking us for examples to make de W3C working group consider this spec.

    Because if it’s a very wanted CSS spec, why do you need to ask us for examples? There must be tons of them, if people really wanted to use them, but the couldn’t.

    Off course the won’t be visible, because these pseudo classes aren’t available for now, but if they’re really wanted you would not even have to ask it, because the examples are just there.

    Back to the article, the spec does look very cool. I really like the approach of @corey (just like you’d also mentioned in your presentation). I like the way Nicolas used the pseudo classes, to build GUI elements (

    The pseudo classes are also very nice for adding really nice shadows to your elements. (

  17. Permalink to comment#

    This really does make sense, especially for visual content that is purely CSS-based. I always feel that I’m adding pointless content to the DOM just to evade pseudo CSS limitations…especially when it’s something as simple as showing an extra bit of visual material that has no interaction.

    I totally support the ideas raised by Corey (index numbers for multiple before/after selectors) and Alex Kempton (multiple custom-named before/after selectors that are pre-defined).

    The method that seems most appropriate would be Alex’s, and it makes a lot of sense considering there are already things in the CSS standard that use custom names, eg. CSS animations.

    Also here’s something that it would be useful for:
    A speech bubble with quotes, the arrow and also static icons floating over the top corner if the message is pinned (or faved, popular, important, etc).

    That way one can simply use this HTML:

    <p class="pinned">
    This is a great idea, it makes my brain and DOM happy!

    Combined with this CSS:

    #messages p:before(1)
    { /* Speech bubble arrow styling */ }
    #messages p:before(2)
    { /* Speech bubble open quote */ }
    #messages p:after(1)
    { /* Speech bubble closing quote */ }
    #messages p.pinned:after(2)
    { /* 'pinned' icon over top-right of bubble corner */ }

    Or the other CSS method, mentioned by Alex:

    @pseudo msg-pin 
    { //css properties }
    @pseudo msg-arrow
    { //css properties }
    @pseudo msg-left-quote 
    { //css properties }
    @pseudo msg-right-quote
    { //css properties }
    #messages p
    before: msg-arrow, msg-left-quote;
    after: msg-right-quote;
    #messages p.pinned
    after: msg-pin;

    Instead of having more in the DOM like this...

    • I really dig the indexing example. Makes a ton of sense and I even feel like I’m actually using something similar to multiple background-images and the :nth-child properties

      /*based on the :nth-child() indexing*/

      I still don’t understand this whole double colon thing going on? What is this?

    • Shaun Lynn
      Permalink to comment#

      Although not required, the spec says the double colon is the “proper” way to denote psuedo-elements.

  18. Wander
    Permalink to comment#

    It would be interesting if an ::inbetween existed, selecting the space between the children of the selected element

    ul::inbetween{ content: ‘|’ ; }
    Would turn a list into

    Instead of using content, it would of course be possible to make small blocks, images, and so on, to use as separation between a set of elements (articles, menu items, form elements, etc)

  19. maybe two different functions of (something like) ::content-before/after and ::display-before/after, just to separate simple things like the blockquote example above.

  20. Hmmm…. demo this (FYI: The styling isn’t perfect. )

    I’m thinking this is what I could have done if I had multiple pseudo elements at my disposal.

    Name: Edit
  21. Hmmm…. demo this (FYI: The styling isn’t perfect. )

    I’m thinking this is what I could have done if I had multiple pseudo elements at my disposal.

    <label>Name: <a href=”#” id=”clickme” class=”a few classes here to mange the styles”>Edit<input type=”input” name=”pwd” value=”enter first name” /></li></ul></label>

  22. I think some of the use cases will eventually end up being handled by Web Components instead…but maybe not all of them.

  23. Permalink to comment#

    What about something like this:

    #element::before[id="before-element"] {}
    #element::after[id="after-element"] {}
    #before-element::before {}
    #after-element::after {}

    In this case, we are assigning a specific ID (or CLASS, if you want to) to the initial pseudo-element. You can then assign a new pseudo to your original pseudo element.

    Technically, with this type of syntax, CSS could write an entire HTML document with only a tag.

    • Permalink to comment#

      The last line should end
      ‘… could write an entire HTML document with only a BODY tag.’

  24. Making text automaticly to links:

    I have done it now with jQuery:

    $("tr td:nth-child(2)").each(function(index)
    	if($(this).html() != '')

    With CSS:

    tr td:nth-child(2):before
    content: <a href="' attr(text) '&hl=nl&t=m&z=11">';
    tr td:nth-child(2):after
    content: '</a>';

    This is a small cube done with ::pseudo and of course, that would be awesome to create the missing 3 faces via pseudo elements too!

  26. A CSS “loading” or “spinner” icon using a single html element (assuming better support for animating pseudo elements)

    Dabblet Example (using multiple divs instead):

  27. I wanted to build a stack of photos representing an album. i could only get three piled photos: the ::before the ::after and the element itself.

    like chuck neely said, animation on pseudo elements is also an issue. i also had this spinner problem.

    • C. L.
      Permalink to comment#

      Yep, same stack of photos use here. I used the ::before for the extra photo border but ::after was already used up by a clearfix.

  28. Were pseudo-elements actually intended for the reason we like them so much now? I always assumed that using them as styling hooks was somewhat of a workaround rather than intended behavior (which goes a long way explaining why there are only two).

    I too have sometimes wished we had more than two pseudo-elements (usually to do with icons, triangles and clearfixes all defined on one single element), though these cases are rare and I wonder if we’re not overusing this (admittedly very useful) workaround, instead forgetting more conventional styling means (like multiple backgrounds)?

  29. Here’s an example where I could use some extra pseudo-elements, so I don’t have to use an extra span tag.

  30. I don’t know if we need more boxes or a way to divide boxes in smaller chuncks. Anyway, I think the region spec is the most amazing use case source for this.

    BTW, I use the ::slot() notation in those samples:

    /* divide an element into slots */
    article {
        local-flow: header, body, footer;
        content: slot(header) slot(body) slot(footer);
    /* redirect elements to the good slot */
    article > *           { flow-to: body;   }
    article > h1          { flow-to: header; }
    article > .aside      { flow-to: footer; }
    article > .footnote   { flow-to: footer; }
    /* format the slots the way we like */
    article::slot(header) { ... content: flow-from(header); ... }
    article::slot(body)   { ... content: flow-from(body); ...   }
    article::slot(aside)  { ... content: flow-from(aside); ...  }
    article::slot(footer) { ... content: flow-from(footer); ... }

    This is also solving cases like the speech bubble:

    .message::before { content: slot(bubble) open-quote; ... }
    .message::slot(bubble) { ... }

    From what I saw here ::between-elements seemed nice to me.

    The advantage of using a CSS property and not a pseudo-element is that as soon as the CSS WG find out a solution to allow multiple stylesheet to add elements to a list-valued property without clearing the one added somewhere else in the stylesheet we’ll have the possibility to add slots to content() without worrying about using an unique index (::after(1),::after(2)…) for each of our additions.

  31. thank you for making writing very interesting to see and understand.

  32. Having n amount of pseudo elements would finally make us able to separate content from style.

    At the moment we all(?) add spurious nonsensical mock-up to add extra elements on a page that are purely for presentational purposes, such as:

    <span class="space-ship-flying"></span>

    This only has relation to the presentation of the page, not the content (so it’s just as bad as using the font tag!).

    It would be much better practice if that whole element could be moved completely to the presentational layer:

    content: url("img/space-ship-flying.png");
    position: absolute;
    etcetera: etcetera;

    Or using code mentioned above:

    @pseudo space-ship-flying 
    { //css properties }
    pseudo: @space-ship-flying;
  33. It would be great to have pseudo elements that are completely divorced from the DOM. Most uses of :after and :before aren’t really what they were originally intended for. It would be good if you could create a pseudo element and then give it instructions on where it should appear in the page something like this

        content: "blah";
        dom: article header .avatar;
  34. Permalink to comment#

    Interesting idea Rachel. I think it would probably break away from the CSS standard if we had to put that sort of “dom” selector inside the actual properties of a pseudo element.

    Based on how most CSS selectors work, as well as the ideas being presented here so far, I’d probably go for this solution:

    @pseudo article_avatar
        content: "blah"; 
    article header .avatar
        before: article_avatar;

    This would then allow us to use the pseudo element called "article_avatar" in places other than just "article header .avatar",
    plus it's simple and clean :)

  35. Another use case I’ve come a cross is when you want to display the cite attribute of a quote in a style different from the closing quote. I put together a pen to illustrate.

    In addition I’d see great help in more pseudo-elements when working with sprites!

    That being said, there are a lot of creative ideas in this discussion. Personally I’d like to keep this as simple as possible. CSS3 introduced double quotes for pseudo elements. What about freely naming pseudo elements to our own preference, just like IDs and classes?

    Then you’d easily solve the initial “speech bubble thing” adding either

    (1) a second ::after element:

    q::after(2) { }

    (2) a chained ::after element:

    q::after::after { }

    (3) a custom chained element:


    …or (4) a completely stand alone element:

    q::bubble-tip { }
  36. Pat
    Permalink to comment#

    What I’d really love is to be able to see pseudo-elements in the DevTools DOM inspector in Firefox/Chrome like how it’s done in Dragonfly on Opera!

  37. I could totally see countless benefits to multiple pseudo-elements. One example I happened across recently was in an attempt to create a folder tab like button with pure CSS. The type of tab that has an “S” curve on either side. I was easily able to create one side of it with a before and after. One was used as a mask type layer with a border radius and the other filled the gap in between the mask and the actual element. With just one more pseudo-element I would have been able to mask the other side and achieve a perfect folder tab button with pure CSS. Unfortunately, I had to settle for right justifying the tab and only having an “S” curve on one side :(

  38. Did you ever think of creating divs within the content: “” that could have their own pseudo :before?

    • Ryan McKay
      Permalink to comment#

      Creating actual elements with the content attribute would probably be crossing streams again, as it’s effecting a little too much in the DOM than just good ol’ pseudo elements with text added through an attribute.

    • runeform
      Permalink to comment#

      this is an interesting idea. by adding the selector for the div to the style you would effectively create an infinite loop. this cant possibly work though. i’ll have to try it. trying to think of a practical use for this hurts my brain.

       content: '<div class="loop"></div>';   
  39. derylius
    Permalink to comment#

    I’d prefer the ::after::after syntax as for me it makes more sense.

    One of the possible usage I ran into is

        content: '„';
        content: '“';
        content: attr(cite);

    which would totally make sense in a basic CSS layout, yet achievable only in JavaScript at the moment.

  40. While we’re at it, let’s bring back the ::outside psuedo wrapper as well, which already has a proposed means of multiples (with a syntax in the form of ::outside(2)/::outside(3) etc). Not that I’m tied to this paren-numbered syntax for the multiples format, but it works—it’s sensible, clean and allows us to give semantic order/organization to the multiple pseudo elements, whether they be ::outside or ::before or ::after or ::whathaveyou and would be slightly cleaner (less code) than the syntax format derylius described (::after::after) though you’d think the latter would already exist and work.

    Anyway, this idea was proposed in the 2003 CSS3 Working Draft:

    Guessing William Malo didn’t know that this had already been spec’d, but I’m glad to see I’m not the only one who wants this or had thought of this! Another use case to add to those that Mr. Malo mentioned:

    ‘twould make vertical centering simpler without the use of extra non-semantic elements (hate em!). Or the powers that be could just allow vertical-align: middle to work for divs. That’d be great, too.

    In any case, here’s to reducing the non-semantic pollution in our HTML waters!

  41. What’s the status on this? More pseudo elements to css would be like having hovercars in real life.

  42. Alexandros T.

    In my case, I needed to have a speech bubble, but with a double outline. That could work very easily with one additional ::before / ::after pseudoelement.

  43. I’d love to use multiple pseudo elements to create (more) complex loading animations. That way I could just add a loading class on the component of my UI that is waiting for data and have everything else in the stylesheet.

  44. Seph Coster wrote in:

    I’m currently running into a problem where I’d like to prepend text to an element (“back to” for navigation breadcrumbs), and I’d also like to prepend font icon with different border options and styling. I currently can’t do this, and it’d be a great use case for allowing multiple pseudo-elements in the spec.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".