In this article, we are going to learn the difference between a pseudo-class vs pseudo-element – we are going to take a look at how they are similar and what are the differences between them. For a start, pseudo-class and pseudo-element are both CSS selectors, so this is definitely something that they have in common. The basic difference, however, is, that a pseudo-class represents a virtual CSS class, while a pseudo-element represents a virtual HTML element. Let’s take a look at what this really means.
What is a pseudo-class?
A pseudo-class defines a special or different state of an element – it is a selector that helps in the selection of a particular state of an element that cannot be expressed by a simple selector (based on id, name, class, type and attribute). Pseudo-classes represent states based on information that lies outside the HTML source tree. In other words, pseudo-class is a way of selecting certain parts of a HTML document, that is not based on the DOM and its elements or characteristics that we’ve mentioned above (id, name, class, type, attribute,…), but on other conditions that are pseudo or phantom and that can be language encoding or some dynamic state of an element. Basically, a pseudo-class works as if some sort of a ghost class is added to an element.
A syntax of a pseudo-class is a pseudo-class’ name is prepended by a colon : character, like so:
selector:pseudo-class {
property: value;
}
or in example when we use the :hover pseudo-class on a <div> element, where that <div> element will change its background color to red when we mouse over it:
div:hover {
background-color: red;
}
A simple example of what we were talking about above would be an element in a disabled state. The DOM tree does not contain information if an element is in a disabled state or not, because browsers save this information somewhere else. So, if we want to select an element in a disabled state, we have to use a pseudo-class :disabled. Depending on our need, we can choose other dynamic pseudo-classes that select elements based on features that are not saved in the DOM tree and these pseudo-classes are:
- :hover when we want to style an element when a user mouses over it,
- :visted when we want to style visited and unvisited links differently,
- :focus when we want to style an element when it gets focus,
Through examples this would mean a:link would select any “a” element whose target has not been visited, a:visited would select any “a” element whose target has been visited, a:hover would select any “a” element which is in a hover state, a:active would select any “a” element which is in a state of activation, and so on. With a pseudo-class we could also select the first child of an element, which is present in the HTML source tree, but selecting that first child is not possible if we want to use simple CSS selectors. This is where pseudo-class selector :first-child comes in place.
Some of the pseudo-class selectors
So, we learned so far that pseudo-classes select regular elements under certain conditions (such as position to siblings, or when elements are under a particular state) and here is a list of pseudo classes in one of the latest versions of CSS:
- Dynamic pseudo-classes that select elements based on features that are not saved in the DOM tree: :hover, :visted, :focus, :link and :active.
- Language pseudo-classes that represent the same element, but this element is in a different language: :lang.
- UI states that represent the same element, but in a different state: :disabled, :enabled and :checked.
- Structural pseudo-classes, where information is present in the DOM tree, but the information is not possible to select with a simple selector, such as :first-child, :nth-child(n), :nth-last-child(n), :nth-of-type(n), :nth-last-of-type(n), :last-child, :first-of-type, :last-of-type, :only-child, :only-of-type, :root, :empty.
- Negation pseudo-class that represents an element not having a certain state, like :not()
What is a pseudo-element?
Pseudo-class represents a virtual class of an element and can appear anywhere in a selector chain, but pseudo-elements cannot. A pseudo-element is a new virtual element that represents a part of the element – it is used to address a sub-part of an element. Pseudo-element is not present in the DOM tree but only looks like it is. So, with pseudo-elements, we “create new elements”, and these new pseudo-elements are not defined in the document markup but are manipulated just like a regular element. For example, we can set style on a part of an element’s content, even though this is not specified in the document element tree. This, my darlings, is the greatest benefit of having pseudo-elements. We can create great effects with minimal markup and we can keep the documentation in CSS where it belongs.
A syntax of a pseudo-element is a pseudo-element’ name is prepended by a double colon :: character, like so:
selector::pseudo-element {
property: value;
}
The CSS3 added the difference between pseudo-classes and pseudo-elements with a double colon (::) character, so the difference between them is much more clearer now.
What are some typical examples of when we should use pseudo-elements?
Typically, a CSS pseudo-element is used to style specified parts of an element. For example, we could use pseudo-elements for typographic effects such as initial caps and drop caps, we could style the first letter, or a line of an element or with ::before and ::after we could insert content before, or after the content of an element – we can simply style some text, like so:
This box, for example. We styled this box with FYI, so we added ::before pseudo-element to position the “FYI” before the text. If we were to use ::after the FYI would be place at the end of the text we styled.
The ::first-line pseudo-element
The ::first-line pseudo-element adds a special style to the first line of a text. For example, we can style all <p> elements to have the the first line of text in red and bold, like so:
p::first-line {
color: red;
font-weight: bold;
}
The ::first-line pseudo-element can only be applied to block-level elements, and the following properties apply to the ::first-line pseudo-element:
- font properties, such as font-weight in our example
- color properties
- background properties
- word-spacing
- letter-spacing
- text-decoration
- vertical-align
- text-transform
- line-height
- clear
Here is a list of pseudo-elements, but some of them are still the experimental phase:
- ::before
- ::after
- ::first-letter
- ::first-line
- ::backdrop
- ::cue
- ::cue-region
- ::file-selector-button
- ::grammar-error
- ::marker
- ::part()
- ::placeholder
- ::selection
- ::slotted()
- ::spelling-error
- ::target-text
What is the biggest disadvantage of pseudo-elements?
- First of all, pseudo-elements are not supported in older browsers, and some of them are still in the experimental phase.
- Pseudo-elements may only be applied to external and document-level contexts and not to in-line styles.
- Some elements (replaced elements) cannot take pseudo-elements, so in this case having them is not even an option.
- Pseudo-elements are by default restricted in where they can appear in a rule – they may only appear at the end of a selector chain, so after the subject of the selector (after any class or ID names found in the selector).
- Only one pseudo-element (of each type) is allowed per element, so if we need a pseudo-element for something else, then we can have a problem – when we want to address multiple pseudo-elements on a single element structure, multiple style selector/declaration statements must be made.