I have a confession to make: I kind of love the ::before
and ::after
pseudoelements.
They’re like a couple of henchmen along on any styling adventure.
Like never having to face the world alone - for everywhere there was 1, there is now 3.
3 times the power. 3 times the number of styleable pieces. 3 times the amazing visual effects you can create.
What are pseudoelements?
Now if you’ve never encountered ::before
and ::after
before, you may be asking “what is this ::before psuedoelementyou speak of?”
Here’s the 30 second overview:
Pseudo-elements are “pretend” elements that you can get insert into a document by using CSS. For example, if I were towrite the very simple CSS:
p::before {
content: "Hello!"
}
Suddenly every single p
element on my page will have the word “Hello” inserted before its content. The ::after
pseudoelement is similar, but goes after the content instead.
The content
property sets what they show inside of them, but these elements are completely styleable in exactly the same way as any other element is, so you don’t actually need there to be textual content inside. In fact, many of the most interesting uses are completelhy visual.
If you want a more thorough introduction, I recommend this piece on SmashingMagazine. Forthis article, I’m going to focus less on how pseudo-elements work and more on a range of amazing examples of the thingsyou can do.
That said, one quick gotcha I want to highlight because it has gotten me so many times. Many of the uses we will exploreinvolve graphics but no actual word content. This is great, but you must set both the content
property, and if your content is empty the display
property or the pseudoelement will not show up. I’ve been bitten by this many times… so always rememberto start by setting content. If your use is entirely visual, simply set:
content: ""
display: inline-block
Simple uses for ::before and ::after
Let’s start with some simple uses for ::before
and ::after
.
Custom Icons
One simple and common but very useful use for ::before is to add icons to elements with a particular class. For example,FontAwesome uses this technique to implement its icons. You can use the same approach to doyour own custom icons.
Now FontAwesome does this with a custom font and the content
property, which has the benefit of automatically sizingbased on the element it is placed on. If we want to use an image, we will need to explicitly size it or thepseudoelement will have size 0 and not be visible.
For example, if I wanted to make every element on the page with a .kball
class on it show a30x30 circle with my profile picture it, I could do something like this:
See the Pen qvQJNG by Kevin Ball (@kball) on CodePen.
Quotes
Another great use of ::before
and ::after
is to add quote marks around a quote. For example, we could create a ‘quote’class that applies double quotes before and after, and even an attribution class that prepends an m-dash:
See the Pen Quotes using Before and After by Kevin Ball (@kball) on CodePen.
There’s a ton of additional stuff we could cover as common uses, but I want to move on to some of the more excitingthings. If you want more like this check out thisarticle.
Advanced Uses of Before and After
Making Shapes
One of the challenges of working in HTML and CSS is the limited number of “basic” shapes you have to work with.
Essentially, every element is a rectangle… and then through clever uses of border-radius and borders you can either round that rectangle into an oval or circle, skew the angles of the corners, or create atriangle out of it. You can of course rotate it once you’re doneusing transform
, but that’s about it…
But now with ::before
and ::after
, you have 3 times as many “blocks” to play with. Each can be transformed, separatelypositioned, and rotated. That leads to a phenomenal selection of shapes you can create with pure CSS.
Chris Coyier of CSS Tricks pulled together a great list of the possible shapes here, of which I’ve reproduced myfavorite below using ZenDev.com’s color scheme. Believe it or not, this is just 1 HTML element!
See the Pen Alexander Futekov YinYang in Blue by Kevin Ball (@kball) on CodePen.
Displaying Attribute Values
Another super cool use for the ::before or ::after pseudoelement is to display the contents of an attribute.
You can do this by setting content
to include attr([attributename])
For example, if you’re using a JavaScript-powered widget that stores some sort of value as a attribute, you canactually display that attribute automatically without having to use any JavaScript to watch it or look at it!
One place I’ve used this before is with the ZURB Foundation slider. The slider works by changing the value in a hiddeninput… but what if we wanted to make the current value visible on the slider itself? The handle that is beingmanipulated is just a span… but it gets an aria attribute for the current value, aria-valuenow
. By referencing thatin a pseudoelement with content: attr(aria-valuenow)
we can display it right inline on the handle.
See the Pen Displaying slider value using ::before by Kevin Ball (@kball) on CodePen.
Multistage Animations
One of the most interesting applications I’ve seen is to create multi-stage animations.
These once again take advantage of the fact that pseudoelements give you entire additional elements to manipulate in ananimation. You can animate the core element in one direction, and then animate each pseudoelement independently.
For example, this article shows how to create a fancy “sheen” effect on a button on hover (shown in the pen below).
See the Pen Sheen Button Effect by Kevin Ball (@kball) on CodePen.
There’s all sorts of fun things we could potentially do with this. to create super cool microinteractions. Anotherexample here hides the word content visually and swirls it in on click or hover.
See the Pen Word In Button Effect by Kevin Ball (@kball) on CodePen.
Wrapping Up
There is so much that can be done with these pseudoelements it’s hard to cover it all. These are some of the examplesI find particularly fascinating - you might also enjoy this roundup onCSS-Tricks - and if you have any examples that get YOU really pumped, do link me to them in the comments below!
If keeping up in frontend development is something you care about, you might also be interested in my weekly newsletter the Friday Frontend. Every Friday I send out 15 links to the best articles, tutorials, and announcements in CSS/SCSS, JavaScript, and assorted other awesome Front-end News. Sign up here: https://zendev.com/friday-frontend.html
Top comments (7)
One use that
::before
and::after
allows for is also to extend the clickable area of interactive elements such as buttons and links: instead of making an element (say, a card) clickable and having it emulates the link behavior, use an actual anchor tag, set its::after
with absolute positionning so that it wraps the whole element.The benefit is that you keep both your interactivity semantic (as it’s still the link that is clicked) and the browser’s expected behavior (ctrl-click to open in a new tab, etc.).
What's the difference between
:before
and::before
? I use:before
all the time but I'd never seen the double-colon syntax before.There's a bit of a history here... essentially, these were originally shipped with single colons
:before
and:after
. Later, the committees decided they should draw a distinction between pseudo-elements (of which these are) and pseudoselectors, so they::before
and::after
, but browsers would continue to support single.TBH, I typically still use single colon (and I think many folks who started in CSS quite a while ago still do), but when I originally published with that there were some very loud complainers, to the extent that it seemed to be distracting from the point of the article, so I updated to use double in the text.
Ah, that makes total sense. And yeah I've been using
:before
and:after
ever since they became a part of CSS (even before they were widely-supported), so seeing the::
versions caught me by surprise.Anyway, thanks for the clarification! It all makes sense in retrospect, although it still seems weird to me that they decided that there needs to be specific syntax for pseudo-elements vs. pseudo-classes. It doesn't seem likely that they'd ever allow the two to collide, for example...
stackoverflow.com/questions/101817...
There are a bunch of good answers.
TLDR:
::
- pseudo-classes:
- pseudo-elementsI'm not really clear on the distinction of what one does vs. the other, from a practical standpoint, but at least that led me to this explanation of the difference which... seems that it's the other way around?
::
seems to be pseudo-element and:
seems to be pseudo-class.I think what I got from that link is that
::
specifies things that modify the DOM (i.e. a false element) whereas:
specifies things that query against existing objects in the DOM (i.e. a false class), and so I at least kinda-sorta see why that would exist, but it also seems that user-agents are going to have to support:
for the legacy pseudo-elements for quite some time. But this will help me out if I ever run into trouble with a new pseudo-element that a browser correctly distinguishes syntactically.You can actually create a whole website only with pseudo elements (and one html tag) - github.com/scriptex/no-html