Hello, my name is: Amy

The CSS Pseudos

Pseudonyms, pseudoscience, pseudo-activity, pseudo-[anything]. All the prefix 'pseudo' really means is that the word that follows it is not what it seems. (Fake, if you will.) Smoke and mirrors, something that kind of appears to be like one thing, but doesn't quite make the cut.

There are actually two different types of pseudos out there in CSS Land: pseudo-classes and pseudo-elements. Even if you're a beginner with CSS, chances are you have been using a 'pseudo'. And if you've been writing CSS for a while, there's most likely a 'pseudo' that you didn't even know about.

You can detect these fake CSS impostors by looking for colons. If a CSS selector has a colon in it, you at least know it is a pseudo-something. Technically, it's considered best practice to use one ':' for pseudo-classes (.link:hover) and two :'s for pseudo-elements (.fancy::after) in order to distinguish them. With that said, when pseudo-elements first rolled old some browsers didn't support using two :'s, so only one was used. Old habits die hard, so it's likely that you will still see pseudo-elements referenced with only one ':'.

Pseudo-classes

Taking what we know about the word 'pseudo', we can say that a pseudo-class is just something that's trying to act like a class but doesn't quite make the cut. Pseudo-classes give you a way to target and style a specific specific state of an element, without having to specifically add a class name to the element.

Say I want to style a link on hover. Without a pseudo-classes, I would have to use javascript to listen for a mouseover event, then add a class called link-hover, then remove that class when the mouse leaves. Pseudo-classes save me from all that, and allow me the same functionality by just referencing the 'fake class' of link:hover.

<a href="/my-page.html" class="link">My Link</a>
.link {
  color: blue;
}
.link:hover {
  text-decoration: underline;
}

Pseudo-classes, together with pseudo-elements, let you apply a style to an element not only in relation to the content of the document tree, but also in relation to external factors like the history of the navigator (:visited, for example), the status of its content (like :checked on some form elements), or the position of the mouse (like :hover which lets you know if the mouse is over an element or not). -MDN

MDN also has a great explanation of each of these pseudo-classes. Post your favorite, or one you just found out about in the comments! I just learned about the pseudo-classes for printing, :left and :right, which allow you to tell if the content is considered to be on the 'left' or 'right' when printing, so you could adjust margins or such accordingly.

pseudo-elements

Pseudo-elements are very similar to pseudo-classes, but instead of styling a 'state', pseudo-elements` allow you to style a specific part of an element. There aren't near as many pseudo-elements, though these things can be a bit trickier to put in your brain than a pseudo-class.

Back to our link example, let's say we want to jazz up our link a bit by adding a special character in front (** My Link). We cold actually type that in the HTML of course, but of course that becomes a mess to manage when I decide the character should be different.

Using ::before could help with just this case. By adding the content property, like you see below, I am actually creating another (fake) element that appears before my link, and contains the content I tell it.

.link::before {
  content: '** ';
}

If you use the inspector on this element, you won't see the two asterisks in the DOM at all, but you will see a reference to the pseudo element ::before. If you were to click on that, you could interact with that ::before just like it was an actual element.

Element view in inspector, anchor tag with ::before inside, but not astericks

You can style these imposter elements just as if they were the real deal. Things that might trip you up though are that in order for ::before or ::after to display, they must have a content property, even if it's blank. If content is blank, then you'll most likely want to set it as display: block and give it a width/height/position/etc.

When first learning, I like to get something on the page, and then work from there. Here's a good place to start:

.element::before {
  content: '';                //creates the pseudo element
  display: block;             // default is 'inline'
  width: 20px;                // give it some space 
  height: 20px;
  background-color: deeppink; //so I can find it
}

Fun fact about the content property: You can reference attributes of CSS, kind of like variables. So, if I wanted to add the href of my link after, I could do so by:

.link::after {
  content: ' - ' attr(href);
}

Before you get too excited about pseudo elements, remember:

  • Not all screen readers read the content, but some do. Don't put important content inside, but also don't put garbage inside thinking a screen reader won't read it.
  • Because your content doesn't show up in the DOM, anything you put in content property won't be selectable.

Take a look at these other cool use cases at these links:

If you're into this kind of thing, I'd definitely encourage you to check out this insanely in-depth dive into what each of the many pseudo classes and pseudo-elements are able to do. You won't regret it!

Keep it fake!

Comments