The difference between pseudo-classes and pseudo-elements

Pseudo-classes and pseudo-elements are highly useful features of CSS. But what’s the difference? Are the terms interchangeable? And should you use one colon or two? Let’s dig into this.

Pseudo-classes

Pseudo-classes represent states in which an element can be. Links are a good example; here are a few available to them:

:active
Applies when a user activates a link (e.g. by clicking).
:hover
Applies when a user hovers over a link with their cursor.
:link
Applies to links that the user has not yet visited.
:visited
Applies to links that the user has already visited.

These all represent different states in which a link can be. They don’t target entire elements of their own; they target existing elements that happen to be in a specific state.

Pseudo-elements

Pseudo-elements, on the other hand, let you style specific parts of an element. Here’s a short list:

::after
Inserts content as the last child of a selected element.
::before
Inserts content as the first child of a selected element.
::first-letter
Selects the first letter in the first line of a block of text.
::first-line
Selects the first line in a block of text.

These aren’t states. They’re specific parts of an element that don’t have actual elements of their own. You might use the ::first-letter pseudo-element to create drop caps, for example. This would save you from having to manually wrap every single first letter in a <span> element.

One colon or two?

As you can see, I’ve prepended each of the pseudo-classes with a single colon, and the pseudo-elements with two colons. This is because CSS3 specifically added the two-colon syntax to help distinguish pseudo-elements from pseudo-classes.

Browsers still accept the single-colon syntax for pseudo-elements. But I feel it’s always best to be as explicit as possible. If adding one extra colon helps with that, it’s a no-brainer for me. 🙅‍♂️ 🧠


If you have questions, feedback, or any other suggestions, please do email me. I'd love to hear from you!