Skip to content

Fun with ::before and ::after

I've noted in the past that the CSS pseudoelements represent inserted content in the element (i.e. span::before refers to a virtual element inserted within the <span> before the rest of its contents, not to content that is inserted before the <span> itself. That makes it useful for things like decorative guillemets for next and prev links ( a[rel=next]::before { content: '« '; } a[rel=prev]::after { content: ' »'; } ) (note using rel rather than classes to keep everything really semantic).

But you can insert content even in elements that can't have content, like <hr>. See the last two examples on CSS tricks; especially the last one that sticks a glyph in the middle of the horizonal rule:

hr {
    text-align: center;
hr::after {
    content: "§";
    display: inline-block;
    position: relative; 
    top: -0.7em;  
    font-size: 1.5em;
    padding: 0 0.25em;
    background: white;

Or you can use the pseudoelement to create custom underlines. text-decoration: underline gives a solid underline in the text color. border-bottom gives far more options, but is generally too far away from the text for my taste. You can increase the distance with padding-bottom but you can't use negative values to decrease it. Instead, use a full-width ::after element with a bottom border, and move that:

     position: relative;
     text-decoration: none;
     position: absolute;
     left: 0px;
     bottom: 6px; /* or whatever looks right */
     content: '';
     width: 100%;
     border-bottom: 1px dotted green

Or for numbering paragraphs, use a CSS counter with the ::before element (this is what I used for my line numbering function, and for numbering quotes on

p {
	margin-left: 10em;
	position: relative;
	counter-increment: p-counter;
p::before {
	content: counter(p-counter);
	font-weight: bold;
	position: absolute;
	left: -2em;

Post a Comment

Your email is never published nor shared. Required fields are marked *