Understanding Pseudo-Element :before and :after
Cascading Style Sheet (CSS) is primarily intended for applying styles to the HTML markup, however in some cases when adding extra markup to the document is redundant or not possible, there is actually a feature in CSS that allows us to add extra markup without disrupting the actual document, namely the pseudo-elements.
You have heard of this term, especially when you have been following some of our tutorials.
There are actually a few CSS family members that are classified as pseudo-elements such as the :first-line
, :first-letter
, ::selection
, :before
and :after
. But, for this article, we will limit our coverage to only the :before
and :after
, “pseudo-elements” here will specifically refer to both of them. We will look into this particular subject from basics.
The Syntax and Browser Support
The pseudo-elements have actually been around since CSS1, but the :before
and :after
that we are discussing here were released in CSS2.1. At the beginning, the pseudo-elements use single-colon for the syntax, then as the web evolved, in CSS3 the pseudo-elements were revised to use double-colon – becoming ::before
& ::after
– to distinguish it with pseudo-classes (i.e. :hover
, :active
, and so on).
However, whether you use the single-colon or the double-colon format, the browsers will still recognize either. And since Internet Explorer 8 only supports the single-colon format it is safer to use the single-colon if you want wider browser compatibility.
What does it do?
In short, the pseudo-elements will insert an extra element before or after the content’s element, so when we add them both, they are technically equal, with the following markup.
<p> <span>:before</span> This the main content. <span>:after</span> </p>
But those elements are not actually generated on the document. They are still visible on the surface but you will not find them on the document source, so practically speaking they are fake elements.
Using pseudo-elements
Using pseudo-elements is relatively easy; the following syntax selector:before
will add an element before the content’s selector while this syntax selector:after
will add after it, and to add a content inside them we can use the content
property.
For example, the snippet below will add a quotation mark before and after the blockquote
.
blockquote:before { content: open-quote; } blockquote:after { content: close-quote; }
Styling pseudo-elements
Despite being a fake element, the pseudo-elements actually act like a “real” element; we are able to add any styles declaration upon them, such as changing the color, adding background, adjusting the font size, aligning the text inside it and so forth.
blockquote:before { content: open-quote; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; background: #ddd; float: left; position: relative; top: 30px; } blockquote:after { content: close-quote; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; background: #ddd; float: right; position: relative; bottom: 40px; }
Specifying the dimension
The generated elements are by default an inline-level element, so when we are about to specify the height and the width, we have to first define it as a block element using the display: block
declaration.
blockquote:before { content: open-quote; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; background: #ddd; float: left; position: relative; top: 30px; border-radius: 25px; /** define it as a block element **/ display: block; height: 25px; width: 25px; } blockquote:after { content: close-quote; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; background: #ddd; float: right; position: relative; bottom: 40px; border-radius: 25px; /** define it as a block element **/ display: block; height: 25px; width: 25px; }
Attach background image
We can also replace the content with an image rather than only plain text. Although the content
property provides a url()
string to insert an image, but in most cases I much prefer using the background
property for more control over the image attached.
blockquote:before { content: " "; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; float: left; position: relative; top: 30px; border-radius: 25px; background: url(images/quotationmark.png) -3px -3px #ddd; display: block; height: 25px; width: 25px; } blockquote:after { content: " "; font-size: 24pt; text-align: center; line-height: 42px; color: #fff; float: right; position: relative; bottom: 40px; border-radius: 25px; background: url(images/quotationmark.png) -1px -32px #ddd; display: block; height: 25px; width: 25px; }
However, as you can see from the snippet above, we are still declaring the content
property and this time with an empty string. The content
property is a requirement and should always be applied; otherwise the pseudo-element will not work whatsoever.
Combining with pseudo-classes
Although they are a different kind of pseudo, we can use the pseudo-classes along with pseudo-elements together in one CSS rule, for instance, if we want to turn the quotation mark background a bit darker when we hover over the blockquote
.
blockquote:hover:after, blockquote:hover:before { background-color: #555; }
Adding Transition Effect
And we can even apply the transition
property upon them to create a graceful color transition effect.
transition: all 350ms; -o-transition: all 350ms; -moz-transition: all 350ms; -webkit-transition: all 350ms;
Unfortunately though, the transition effect seems to only work in the latest version of Firefox. Hopefully more browsers will catch up to allow the transition property to be applied in pseudo-elements in the future.
Conclusion
Pseudo-elements is simply “cool” and ultimately usable, basically we have two bonus elements for every element we add without interfering with the actual HTML structure at all, and then turning them to almost everything we can ever imagine.
There are actually some improvement for pseudo-elements that is currently being worked on, such as nesting pseudo-elements div::before::before { content: ''; }
and multiple pseudo-elements div::before(3) { content: ''; }
which obviously will open much more possibilities in web design practice in the future. While they are being implemented in current browsers, let’s wait patiently for now.