loading...

::before and ::after pseudo-elements explained

ferueda profile image Felipe Rueda ・5 min read

If you're like me, using pseudo-elements ::before and ::after used to be like black magic, how they worked was a complete mystery and I just knew what they were supposed to do but not how they did it, so today I want to explain what's behind them and how they work.

We'll start from a basic HTML paragraph and some presentational CSS code and build from there.

Initial HTML code

 <body>
   <p>This is a paragraph.</p>
 </body>

Initial CSS code

/* regular css resetting */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* presentational styles */
body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #3b3b3b;
  color: #ddd;
}

p {
  font-size: 2rem;
  margin: 2.5rem;
}

Output in our browser

Alt Text

But before starting, we need to know what pseudo-elements are. The official definition for pseudo-elements is:

A keyword added to a selector that lets you style a specific part of the selected element(s).

Basically, pseudo-elements let us style a specific part of an element without having to change it entirely. For example, you could set the color of the first letter of our paragraph p to red, using the ::first-letter pseudo-element, and it would set the color of the word "this" to red.

p::first-letter {color: red;}

Initially, pseudo-elements used the single colon convention but CSS3 introduced a new convention, a single colon for pseudo-classes like :hover and :link and double colons for pseudo-elements like ::before and ::after. This was introduced to differentiate pseudo-classes from pseudo-elements.

There is still browser support for :before and :after but it's important that we use the double colons convention, given that adoption from browsers keeps progressing and we don't know if they'll stop supporting the single column convention in the future.

Now that we know what pseudo-elements are, we can start looking into ::before and ::after pseudo-elements.

Before and after pseudo-elements

::before and ::after creates a pseudo-element that will be the first and last child respectively of the selected element, so when opening a ::before and ::after pseudo-element, the first thing we want to add is the content through the content: property. This will insert the defined content inside our selected element.

As an example, we'll add a ::before pseudo-element to our p paragraph, set its content: value to "before the content" and the color to red.

p::before {
  content: "before the content"; /* string */
  color: red;
}

This will result in a red "before the content" string right before our p element main content ("This is a paragraph.").

Alt Text

When looking at the chrome devtools, it’s important to note that the ::before content comes before the p content but not the element itself. The p element still contains the ::before content.

Alt Text

If we add the ::after pseudo-element to our p paragraph, it'll result in the same as before but the content will be placed after the main element's content.

p::after {
  content: "after the content"; /* string */
  color: orange;
}

Alt Text

Same as before, our ::after content will be placed just after the p element content but inside the p element itself.

Alt Text

We could say that we are creating elements within elements. It’s also important to note that you can’t select the content within pseudo-elements, as you can see in the image below.

Alt Text

We can apply any normal CSS property to the pseudo-element, like color, width, height, etc. These properties will affect only the pseudo-element content and not the original content of the element.

Let's apply some a light grey background color, padding, border and margin to our pseudo-element.

p::before {
  content: "before the content"; /* string */
  color: red;
  background-color: lightgrey;
  padding: 15px;
  border-top: 5px solid green;
  border-bottom: 3px dotted red;
  margin-right: 10px;
}

What we get is

Alt Text

We can even change the display property of our pseudo-element with display: block;.

Alt Text

What happens if we don’t include the content property inside our pseudo-element? In the example below, I commented out the content property of the ::after pseudo-element.

p::after {
  /* content: "after the content"; */ /* string */
  color: orange;
}

What we get is

Alt Text

We can see that the pseudo-element ::after is gone, even though it’s still in our code. When we don't set the content: property, the default display is set to none (display: none;) so the element won't show.

If we leave the content as an empty string (content: "";), as the example below shows, we get back our pseudo-element and we can see it in our dev tools and even style it.

p::after {
  content: ""; /* string */
  width: 30px;
  height: 30px;
  display: inline-block;
  background: tomato;
}

Alt Text

You can do some cool styling with these pseudo-elements and even create animations.

p::before {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  margin-bottom: 5px;
  background-color: tomato;
}

p::after {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  margin-top: 5px;
  background-color: tomato;
}

Alt Text

Adding quotation marks to a paragraph. Remember that you can style those quotation marks, giving them size, color, margin, padding, etc.

p::before {
  content: open-quote;
}

p::after {
  content: close-quote;
}

Alt Text

Now, going back to our reset at the top of our CSS code, we set everything as a border-box and 0 margin and padding but this actually won't apply to our pseudo-elements. To apply these resetting properties we need to add it specifically to each of our pseudo-elements as follows.

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

Alt Text

I hope this short guide helps you have a clearer picture of how pseudo-elements ::before and ::after work and what you can use them for.

If you have any suggestion or would like to add something to the article, please leave a comment below.

Also, if you want to connect with me, you can find me on twitter :)

Posted on by:

ferueda profile

Felipe Rueda

@ferueda

Transitioning from Product Management into Software Engineering 😀. I once quit my job and went snowboarding in Canada for three months 🏂. He/Him.

Discussion

markdown guide
 

Loved this in-depth look at ::before and ::after, however, I'm still confused as to why someone would use this?

What are some real world examples? Sorry to ask, but I'm relatively new to this and would love to finally understand these entirely 😂

 

Yeah! of course. There are a few common uses that come to mind.

The most common one would be the old .clearfix hack for floated elements.

.clearfix::after {
  content: "";
  clear: both;
  display: table;
}

This works because using the ::after pseudo-element clears the float display just after the main element is presented, but is still within the element itself, and before presenting the next element in the DOM.

Another common use case I see a lot is when you don't want users to download certain image from your website, like your profile photo. You can present it using ::before or ::after and users won't be able to select or download it.

Adding little icons to links or buttons. I find this trick really cool and helpful as a visual aid for users. You can add little icons just before or after a link or button is presented in you website without having to hard code them in the DOM.

Let's say that you want to add a fontawesome's PDF icon just after every link that takes you to a PDF download. You could do this using the ::after pseudo-element.

It would look something like this.

a[href$=".pdf"]::after
{
  content:"\f1c1  "; /* This is the awesomefont unicode for a pdf icon */
  font-family: fontawesome;
}

Check this codepen I made so you can see how it would look like.

The last one I can think of right now is creating cool animations when hovering on elements like links or buttons. There are lots of other cool uses but hope you find these useful.

 

Damn, you are awesome!

Totally makes sense now, thank you! I used to think of ::before and ::after as an action before and after and never truly understood how to use them haha.

Thanks for helping me understand, cheers!

 

Nice explanation, but I used to use them in adding font-awesome icons before or after the words.

 

Yeah! I've sern that before. Those little pdf icons just after the word with the download link are really cool.

 

Worth noting: don't put content in these. Screen readers and other assistive technologies tend not to do anything sensible with them.

 

Thanks for pointing that out! Really important to have in mind when using them.

 
 

Wow! That's a great explanation! Tks so much! I started studying coding a month ago and this is very helpful!

 

Thanks for the explanation! I've always been mystified by before and after.