How CSS pseudo-elements work a ridiculously simple explanation for beginners
Tags: css, webdev, beginners, codenewbie
Published: 2021-05-04 09:58:25

Pseudo-elements especially `::before` and `::after` are so hot right now. Amazing sites like [Cyberpunk.net](https://www.cyberpunk.net/us/en/) use them to create amazing affects. However, lots of beginners don’t fully grasp their power. So, before you can harness their power you first need to understand how they work.

When I first started working with pseudo-elements, I had no idea what I was doing or how they actually work. I was just copying and pasting other people's code and not really understanding why it was or wasn’t working.

If you want to harness the power of CSS and get good at it then understanding pseudo-elements is a must. By the end of this post you will have a strong grasp of what pseudo-elements are and how to use them to create stylish elements yourself.

But first, let’s explore what they are.

## What are Pseudo-Elements
In CSS pseudo-elements are a keyword that you add to [selectors](https://www.w3schools.com/cssref/css_selectors.asp). These pseudo elements let you style specific parts of the element you selected. CSS denotes them using two colons `::` which helps you tell them apart from CSS pseudo-classes as they have only one colon `:`.

Let’s look at the general syntax for CSS pseudo-elements before we get into specific pseudo-elements.

### Syntax

```CSS
selector::pseudo-element {
  property: value;
}
```

As you can see, you put the CSS selector before the double colon. Next, inside the curly braces you write CSS property value pairs, like you would for any other element you are styling.

As a real example, we could do something like below.

```CSS
.second::selection {
  color: #fff;
  background-color: mediumspringgreen;
}
```

The example uses the `::selection` pseudo-element on the `second` CSS class selector. Now, when you highlight the paragraph text it is a different color and background.

We’ll explore the `::selection` pseudo element some more later. For now I want you to focus on the two major pseudo-elements `::before` and `::after`.

## What are the before and after pseudo-elements?

The before and after pseudo-elements let you insert content onto a web page. They allow you to do this without the need for it to be in the HTML. Essentially you can insert content through CSS.

One important thing to note when it comes to the before and after pseudo-elements is that when they are created they are not actually on the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction">DOM</a>. In other words, they are <i>fake</i> elements, this is why they are call *“pseudo* elements as the word pseudo means fake. So, the name fits because these elements don’t actually change anything in the document. They are hidden elements that are only visible to the user and not the DOM.

What this looks like in practice is this.

```css
h1::before {
  content: ‘before’;
}

h1::after {
  content: ‘after’;
}
```

The result would be something like this.

```HTML
<h1>
  before
    <!--actual h1 element -->
  after
<h1>
```

Knowing that these elements are fake it’s time to look at the first fake element you will use a lot in web development, the before pseudo-element.

### The before pseudo-element

In CSS, `::before` creates a pseudo-element that is the first child of the selected element. To put it another way, it is a pseudo-element that comes before the content of the CSS selector. So if you have a paragraph element it would look like this `p::before` with `p` being the selector and `::before` being the pseudo-element.

With this in mind let’s look at some examples.

```HTML
<p>Mr. and Mrs. Dursley of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much.</p>
```

```CSS
p {
  font-size: 14px;
  color: #7f0909;
  background-color: #ffc500;
}

p::before {
  content: "the boy who lived";
  text-transform: uppercase;
  font-size: 130%;
  background-color: #5BC8F8;
  border: solid black 1px;
}
```

**Result**

![::before pseudo-element result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ilm1imtlvnlryw0qskp.png)


From the code above, we have added the content *'the boy who lived'* before the CSS selector which in this case is the `p` tag and its content.

We were then able to style the content before the selector however we wanted.

If we check the developer tools in the [codepen](https://codepen.io/pin0s/pen/dyNxvXZ), you will see that there is no element *'the boy who lived'* There is just a pseudo-element `::before`. As it isn't really on the DOM.

![pseudo-element before showing in dev tools but not on the dom](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hghwiq4cytiba8sbh6x.png)

Let's look at another example.

```HTML
<h1>harry potter and the sorcerer's stone</h1>
```

```CSS
h1 {
  display: inline-block;
  text-transform: uppercase;
}

h1::before {
  content: "";
  display: block;
  background: #ffc500;
  height: 5px;
  width: 100%;
}
```

**Result**

![before pseudo-element with block styling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9zwqoyqvhj1uxu5kvlz.png)

In this example, the before pseudo-element is using the `display` property with the value `block`. This then moves the background with a width of 5px above and before the `h1` element.

Now you know what the before pseudo-element does let's look at the after pseudo-element.

### The After pseudo-element

In CSS, `::after` creates a pseudo-element this is the last child of the selected element. So much like the `::before`, it is a pseudo-element that comes after the content of the CSS selector.

Keeping that in mind let’s use the second example from the before section and add a line underneath with the after pseudo-element.

```CSS
h1::after {
  content: "";
  display: block;
  background: #ffc500;
  height: 5px;
  width: 100%;
}
```

**Result**

![before & after pseudo-element with block styling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi16jjzusd8ju3i6izei.png)

We now have a line under the `h1`. How cool is that, we can make our own little styling elements to create great looking elements.

By now, you should now have a good understanding of how the `::before` and `::after` pseudo-elements work. To further improve our knowledge we need to understand what the `content` property is and what it is doing.

## Content property

Did you notice the use of the `content` property, with the `::before` and `::after` pseudo-elements? Objects that are inserted using the `content` property are anonymous replaced [elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element). Put in simpler terms, it is an element whose content is not affected by the current documents styles.

Thus, when using the `::before` and `::after` pseudo-elements, you <b>must</b> use the `content` property to make your styles visible. Did you also notice that the content is inside the element? In spite of the fact that the naming of `::before` and `::after` make it feel like the content should come before or after the element. But, it is definitely before or after the content inside the element.

Next, to better understand the content property let’s look at what values it takes.

### Content Property Accepted Values

The content property takes many types of values. The default value is `normal`. It means 'normally' nothing will be visible to the user. Thus, you give the content property one of the values below.

The other values content can be are:

* A **string** - this sets the content to be the string you specify.
* A **counter** - used to style lists.
* An **image** - this sets the content to be an image you specify with a `url()` or `gradient` data type. The image is inserted at its exact dimensions, meaning you cannot resize the image.
  * please note that to insert alt text you use a `/` after the `url()` and a string description of the image. For example: `content: url("https://www.example.com/test.png") / "This is the alt text";`
* **Nothing** - Useful for inserting images as background-images (set width and height, and can even resize with background-size), or making other cool styling features (link to dev.to post).
* A **attr()** value - Sets the content as the string value of the selected elements attribute.

## Other awesome pseudo-elements

### Selection
`::selection` - This, CSS pseudo-element applies styles to the part of a document that has been highlighted by the user. To put it another way, it makes the highlighter on your page look pretty when people highlight text to copy.

```css
p::selection {
  background-color: cyan;
}
```

### First-letter

`::first-letter` - CSS pseudo-element applies styles to the first letter of the first line of a block-level element, but only when not preceded by other content (such as images or inline tables).

To rephrase the above, this pseudo-element lets you style the first letter of the first line of the element you select. This only happens on elements that are categorized as [block-level elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements) check that link out for a list of block level elements.

As a result, we can use this pseudo-element to make awesome drop caps for our paragraphs, see the example below.

```CSS
p {
  width: 600px;
  line-height: 1.5;
  font-weight: 500;
}

p::first-letter {
  color: white;
  background-color: rgb(55, 97, 117);
  border-radius: 3px;
  box-shadow: 3px 3px 0 rgb(212, 173, 81);
  font-size: 250%;
  padding: 6px 3px;
  margin-right: 6px;
  float: left;
}
```

{% codepen https://codepen.io/pin0s/pen/BapXWOg %}

### First-line

`::first-line` - CSS pseudo-element applies styles to the first line of a block-level element.

In plain English the above means, this pseudo-element lets you style the the first line of the element you select. Again like with first letter this only happens to block level elements.

Let's add the below code to the `first-letter` example.

```CSS
p::first-line {
  color: red;
}
```

**Result**

![first-letter and first-line pseudo-elements effects on p element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvj64lldpoe8kmz176d1.png)

As you can see, the `p` now has drop caps and red text for the first line. Play around with width in the pen above to see what happens as you increase and decrease the width.

Did you notice how if the text moves lines the color changes? You have to be careful taking into consideration things like the width of the element and how it will respond on different screens when styling the first line.

### Marker

The `::marker` CSS pseudo-element selects the marker box of a list item, which typically contains a bullet or number.

The marker pseudo-element will allow you to replace the counter content value. For an example on how a counter works I encourage you to check out this [post](https://www.freecodecamp.org/news/css-before-and-after-how-to-use-the-content-property/). That said, a counter is just the bullet point of number in front of a list item (`<li>`) and the `::marker `pseudo-element lets you style them.

Let's look at an example.

```HTML
<h3>Nintendo Hero's</h3>
<ul>
  <li>Mario</li>
  <li>Link</li>
  <li>Samus</li>
</ul>
```

```CSS
ul li::marker {
  color: #e4000f;
}
```

{% codepen https://codepen.io/pin0s/pen/ExZqWBo %}

The above example is pretty simple, we have just changed the bullet point color to red. But, you can do lot's of things like change the style or even use emoji's.

Finally, it is important to note that the ::marker pseudo-element is not fully supported at the time of writing this.

![browser support for marker pseudo element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qx48djtc2wfdd3ml9dsw.png)

### Summary

Now you should have a good understanding of pseudo-elements. Let’s recap on a few important notes.

Firstly, pseudo elements let you style specific parts of the element you selected. Pseudo-elements are denoted by double colons.

Next, remember that pseudo-elements do not appear in the DOM as they are fake elements. The way you make them visible to the user is to utilize the `content` property.

Lastly, if you learnt something from this post then checkout the rest of my posts [here](https://bit.ly/2Re6Vdf) or [sign up to my newsletter](https://mailchi.mp/4fb2a2723574/peter-lunch-link) to get ridiculously good and super exclusive newbie content.