Can I make the CSS :after pseudo element append content outside the element?

32,357

Solution 1

Normally you code these menus as ordered lists anyway, so it makes sense to do something like this instead:

#breadcrumb-trail ol { 
    list-style: none; 
    margin: 0;
    padding: 0; 
}

#breadcrumb-trail li { 
    display: inline; 
}

#breadcrumb-trail li:after { 
    content: ' » '; 
}

#breadcrumb-trail li:last-child:after { 
    content: none; 
}
<nav id="breadcrumb-trail">
    <h1>My Amazing Breadcrumb Menu</h1>
    <ol>
        <li><a href="">about</a></li>
        <li><a href="">fos</a></li>
    </ol>
</nav>

Solution 2

The spec says:

As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content.

Note the key phrase at the end of this sentence, which refers to the inner content (or inner text). So, the pseudo-elements are inserted into the beginning of the end within the specified elements' content. Therefore the right double angled quote is being inserted after the text of your hyperlinks, rather than after the hyperlinks.

Here's a visual representation of the tree of the DOM element for one such link with both pseudo-elements:

a
  a:before
  content
  a:after

I guess one workaround to this behavior, is to wrap each link in a span then apply styles to nav#breadcrumb-trail span:after, but that'd result in unnecessary markup... worth a shot in any regard though.

Solution 3

Given the flexibility and awesomeness of CSS, it looks pretty much do-able. Tried this in current Chrome, FF, and IE and it does the job just as expected, without the need to add addtional markup:

#box {
  width: 100px;
  height: 100px;
  background: #eee;
  position: relative;
}

#box:after {
  content: '...appended text outside box';
  position: absolute;
  margin-left: 100%;
  left: 0;
  width: 200px;
}
<div id="box">
  Some Box
</div>

Small Caveat: Absolutely positioned `elements are included in the boxes' dimensions, therefore elements floating or aligned next to it are unable to dynamically respect the width of the pseudo elements' content.

Share:
32,357
Dylan Beattie
Author by

Dylan Beattie

Dylan Beattie is a consultant, software developer and international keynote speaker. He has been building data-driven web applications since the 1990s; he's managed teams, taught workshops, and worked on everything from tiny standalone websites to complex distributed systems. He's a Microsoft MVP, and he regularly speaks at conferences and user groups all over the world. Dylan is the creator of the Rockstar programming language, and he's performed his software-themed parodies of classic rock songs all over the world as Dylan Beattie and the Linebreakers.

Updated on April 24, 2020

Comments

  • Dylan Beattie
    Dylan Beattie about 4 years

    I want to format a breadcrumb trail of links using an HTML &raquo; entity between adjacent links, so it looks like this:

    home » about us » history » this page

    I've added a rule to my CSS:

    nav#breadcrumb-trail a:after {
        content: " » ";
    }
    

    but this is adding the entity INSIDE the link, instead of outside it - i.e. I'm getting this:

    home » about us » history » this page

    Am I misunderstanding the behaviour of the CSS :after pseudo-element? Documentation seems to imply it adds the specified content after the specified element, rather than prepending it to the inside of the element's container. Any ideas?

  • BoltClock
    BoltClock about 13 years
    Also, #breadcrumb-trail li:last-child:after { content: none; }
  • Dylan Beattie
    Dylan Beattie about 13 years
    Give that the order in which the pages are organized has semantic significance, I've used an ordered list rather than an unordered list - but otherwise this works perfectly (except in IE8, but meh)
  • kapa
    kapa about 13 years
    I agree on the last-child stuff and the ordered list either. Thx.
  • BoltClock
    BoltClock about 12 years
    There are proposals in the CSS3 Generated Content Module for an ::outside pseudo-element, but it is not known if it'll be deferred to a future specification or scrapped entirely, as this module is currently fairly low priority to most vendors.
  • Luke
    Luke over 9 years
    This should be the correct answer, as it actually answers the question posed. I understand that kapa provided a good solution to the problem, but BoltClock's post actually answers the question.
  • BoltClock
    BoltClock about 9 years
    Indeed - this depends very much on your interpretation of "outside the element box" and your expected results. You'll simply need to position the pseudo-element manually - you cannot trigger a natural float layout or table layout or some such for example, since the pseudo-element box is always created as a child of the originating element box.
  • Philzen
    Philzen about 9 years
    @Luke So does the approach found in my answer below - even without additional markup.
  • Philzen
    Philzen about 9 years
    @BoltClock Very true, good point. I have added this limitation to my answer.
  • Luke
    Luke about 9 years
    In a sense, yes, except that your solution uses absolute positioning which places some fairly severe limitations on the user (especially considering the breadcrumb application in question) of the and doesn't at all address the expected behaviour of :after, something which BoltClock's answer does very well.
  • jave.web
    jave.web about 8 years
    Finally, someone with a real answer to all these questions (this and all other related)...
  • Toby 1 Kenobi
    Toby 1 Kenobi about 8 years
    It seems the names of these pseudo elements are unintuitive, and would be confusing to many users, especially those used to jQuery, which sensibly uses the names "append" and "prepend" for this sort of thing and "after" and "before" for what the OP was trying to do.
  • majkrzak
    majkrzak almost 2 years
    In the tree it is still inside the element