---
title: Pseudo-classes and pseudo-elements
slug: Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements
tags:
  - Beginner
  - CSS
  - Learn
  - Pseudo
  - Pseudo-class
  - Pseudo-element
  - Selectors
---
{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}

The next set of selectors we will look at are referred to as **pseudo-classes** and **pseudo-elements**. There are a large number of these, and they often serve quite specific purposes. Once you know how to use them, you can look at the list to see if there is something which works for the task you are trying to achieve. Once again the relevant MDN page for each selector is helpful in explaining browser support.

<table>
  <tbody>
    <tr>
      <th scope="row">Prerequisites:</th>
      <td>
        Basic computer literacy,
        <a
          href="/en-US/docs/Learn/Getting_started_with_the_web/Installing_basic_software"
          >basic software installed</a
        >, basic knowledge of
        <a
          href="/en-US/docs/Learn/Getting_started_with_the_web/Dealing_with_files"
          >working with files</a
        >, HTML basics (study
        <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML"
          >Introduction to HTML</a
        >), and an idea of how CSS works (study
        <a href="/en-US/docs/Learn/CSS/First_steps">CSS first steps</a>.)
      </td>
    </tr>
    <tr>
      <th scope="row">Objective:</th>
      <td>To learn about the pseudo-class and pseudo-element selectors.</td>
    </tr>
  </tbody>
</table>

## What is a pseudo-class?

A pseudo-class is a selector that selects elements that are in a specific state, e.g. they are the first element of their type, or they are being hovered over by the mouse pointer. They tend to act as if you had applied a class to some part of your document, often helping you cut down on excess classes in your markup, and giving you more flexible, maintainable code.

Pseudo-classes are keywords that start with a colon:

```css
:pseudo-class-name
```

### Simple pseudo-class example

Let's look at a simple example. If we wanted to make the first paragraph in an article larger and bold, we could add a class to that paragraph and then add CSS to that class, as shown in the first example below:

{{EmbedGHLiveSample("css-examples/learn/selectors/first-child.html", '100%', 800)}}

However, this could be annoying to maintain — what if a new paragraph got added to the top of the document? We'd need to move the class over to the new paragraph. Instead of adding the class, we could use the {{cssxref(":first-child")}} pseudo-class selector — this will _always_ target the first child element in the article, and we will no longer need to edit the HTML (this may not always be possible anyway, maybe due to it being generated by a CMS.)

{{EmbedGHLiveSample("css-examples/learn/selectors/first-child2.html", '100%', 700)}}

All pseudo-classes behave in this same kind of way. They target some bit of your document that is in a certain state, behaving as if you had added a class into your HTML. Take a look at some other examples on MDN:

- [`:last-child`](/en-US/docs/Web/CSS/:last-child)
- [`:only-child`](/en-US/docs/Web/CSS/:only-child)
- [`:invalid`](/en-US/docs/Web/CSS/:invalid)

> **Note:** It is valid to write pseudo-classes and elements without any element selector preceding them. In the example above, you could write `:first-child` and the rule would apply to _any_ element that is the first child of an `<article>` element, not just a paragraph first child — `:first-child` is equivalent to `*:first-child`. However, usually you want more control than that, so you need to be more specific.

### User-action pseudo classes

Some pseudo-classes only apply when the user interacts with the document in some way. These **user-action** pseudo-classes, sometimes referred to as **dynamic pseudo-classes**, act as if a class had been added to the element when the user interacts with it. Examples include:

- [`:hover`](/en-US/docs/Web/CSS/:hover) — mentioned above; this only applies if the user moves their pointer over an element, typically a link.
- [`:focus`](/en-US/docs/Web/CSS/:focus) — only applies if the user focuses the element by clicking or using keyboard controls.

{{EmbedGHLiveSample("css-examples/learn/selectors/hover.html", '100%', 500)}}

## What is a pseudo-element?

Pseudo-elements behave in a similar way. However, they act as if you had added a whole new HTML element into the markup, rather than applying a class to existing elements. Pseudo-elements start with a double colon `::`.

```css
::pseudo-element-name
```

> **Note:** Some early pseudo-elements used the single colon syntax, so you may sometimes see this in code or examples. Modern browsers support the early pseudo-elements with single- or double-colon syntax for backwards compatibility.

For example, if you wanted to select the first line of a paragraph you could wrap it in a `<span>` element and use an element selector; however, that would fail if the number of words you had wrapped were longer or shorter than the parent element's width. As we tend not to know how many words will fit on a line — as that will change if the screen width or font-size changes — it is impossible to robustly do this by adding HTML.

The `::first-line` pseudo-element selector will do this for you reliably — if the number of words increases or decreases it will still only select the first line.

{{EmbedGHLiveSample("css-examples/learn/selectors/first-line.html", '100%', 800)}}

It acts as if a `<span>` was magically wrapped around that first formatted line, and updated each time the line length changed.

You can see that this selects the first line of both paragraphs.

## Combining pseudo-classes and pseudo-elements

If you wanted to make the first line of the first paragraph bold you could chain the `:first-child` and `::first-line` selectors together. Try editing the previous live example so it uses the following CSS. We are saying that we want to select the first line, of the first `<p>` element, which is inside an `<article>` element.

```css
article p:first-child::first-line {
  font-size: 120%;
  font-weight: bold;
}
```

## Generating content with ::before and ::after

There are a couple of special pseudo-elements, which are used along with the [`content`](/en-US/docs/Web/CSS/content) property to insert content into your document using CSS.

You could use these to insert a string of text, such as in the live example below. Try changing the text value of the {{cssxref("content")}} property and see it change in the output. You could also change the `::before` pseudo-element to `::after` and see the text inserted at the end of the element instead of the beginning.

{{EmbedGHLiveSample("css-examples/learn/selectors/before.html", '100%', 400)}}

Inserting strings of text from CSS isn't really something we do very often on the web however, as that text is inaccessible to some screen readers and might be hard for someone to find and edit in the future.

A more valid use of these pseudo-elements is to insert an icon, for example the little arrow added in the example below, which is a visual indicator that we wouldn't want read out by a screenreader:

{{EmbedGHLiveSample("css-examples/learn/selectors/after-icon.html", '100%', 400)}}

These pseudo-elements are also frequently used to insert an empty string, which can then be styled just like any element on the page.

In this next example, we have added an empty string using the `::before` pseudo-element. We have set this to `display: block` in order that we can style it with a width and height. We then use CSS to style it just like any element. You can play around with the CSS and change how it looks and behaves.

{{EmbedGHLiveSample("css-examples/learn/selectors/before-styled.html", '100%', 500)}}

The use of the `::before` and `::after` pseudo-elements along with the `content` property is referred to as "Generated Content" in CSS, and you will often see this technique being used for various tasks. A great example is the site [CSS Arrow Please](https://www.cssarrowplease.com/), which helps you to generate an arrow with CSS. Look at the CSS as you create your arrow and you will see the {{cssxref("::before")}} and {{cssxref("::after")}} pseudo-elements in use. Whenever you see these selectors, look at the {{cssxref("content")}} property to see what is being added to the document.

## Reference section

There are a large number of pseudo-classes and pseudo-elements, and it is useful to have a list to refer to. Below are tables listing them, with links to their reference pages on MDN. Use this as a reference to see the kinds of things that are available for you to target.

### Pseudo-classes

<table class="standard-table no-markdown">
  <thead>
    <tr>
      <th scope="col">Selector</th>
      <th scope="col">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>{{ Cssxref(":active") }}</td>
      <td>
        Matches when the user activates (for example clicks on) an element.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":any-link") }}</td>
      <td>
        Matches both the <code>:link</code> and <code>:visited</code> states of
        a link.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":blank") }}</td>
      <td>
        Matches an
        <a href="/en-US/docs/Web/HTML/Element/input"
          ><code>&#x3C;input></code> element</a
        >
        whose input value is empty.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":checked") }}</td>
      <td>Matches a radio button or checkbox in the selected state.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":current") }}</td>
      <td>
        Matches the element, or an ancestor of the element, that is currently
        being displayed.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":default") }}</td>
      <td>
        Matches the one or more UI elements that are the default among a set of
        similar elements.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":dir") }}</td>
      <td>
        Select an element based on its directionality (value of the HTML
        <code
          ><a href="/en-US/docs/Web/HTML/Global_attributes/dir">dir</a></code
        >
        attribute or CSS
        <code><a href="/en-US/docs/Web/CSS/direction">direction</a></code>
        property).
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":disabled") }}</td>
      <td>Matches user interface elements that are in an disabled state.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":empty") }}</td>
      <td>
        Matches an element that has no children except optionally white space.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":enabled") }}</td>
      <td>Matches user interface elements that are in an enabled state.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":first") }}</td>
      <td>
        In <a href="/en-US/docs/Web/CSS/Paged_Media">Paged Media</a>, matches
        the first page.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":first-child") }}</td>
      <td>Matches an element that is first among its siblings.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":first-of-type") }}</td>
      <td>
        Matches an element which is first of a certain type among its siblings.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":focus") }}</td>
      <td>Matches when an element has focus.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":focus-visible")}}</td>
      <td>
        Matches when an element has focus and the focus should be visible to the
        user.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":focus-within") }}</td>
      <td>
        Matches an element with focus plus an element with a descendent that has
        focus.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":future") }}</td>
      <td>Matches the elements after the current element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":hover") }}</td>
      <td>Matches when the user hovers over an element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":indeterminate") }}</td>
      <td>
        Matches UI elements whose value is in an indeterminate state, usually
        <a href="/en-US/docs/Web/HTML/Element/input/checkbox">checkboxes</a>.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":in-range") }}</td>
      <td>Matches an element with a range when its value is in-range.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":invalid") }}</td>
      <td>
        Matches an element, such as an <code>&#x3C;input></code>, in an invalid
        state.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":lang") }}</td>
      <td>
        Matches an element based on language (value of the HTML
        <a href="/en-US/docs/Web/HTML/Global_attributes/lang">lang</a>
        attribute).
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":last-child") }}</td>
      <td>Matches an element which is last among its siblings.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":last-of-type") }}</td>
      <td>
        Matches an element of a certain type that is last among its siblings.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":left") }}</td>
      <td>
        In <a href="/en-US/docs/Web/CSS/CSS_Pages">Paged Media</a>, matches
        left-hand pages.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":link")}}</td>
      <td>Matches unvisited links.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":local-link")}}</td>
      <td>
        Matches links pointing to pages that are in the same site as the current
        document.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":is", ":is()")}}</td>
      <td>
        Matches any of the selectors in the selector list that is passed in.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":not") }}</td>
      <td>
        Matches things not matched by selectors that are passed in as a value to
        this selector.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":nth-child") }}</td>
      <td>
        Matches elements from a list of siblings — the siblings are matched by a
        formula of the form <var>an+b</var> (e.g. 2n + 1 would match elements 1,
        3, 5, 7, etc. All the odd ones.)
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":nth-of-type") }}</td>
      <td>
        Matches elements from a list of siblings that are of a certain type
        (e.g. <code>&#x3C;p></code> elements) — the siblings are matched by a
        formula of the form <var>an+b</var> (e.g. 2n + 1 would match that type
        of element, numbers 1, 3, 5, 7, etc. All the odd ones.)
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":nth-last-child") }}</td>
      <td>
        Matches elements from a list of siblings, counting backwards from the
        end. The siblings are matched by a formula of the form
        <var>an+b</var> (e.g. 2n + 1 would match the last element in the
        sequence, then two elements before that, then two elements before that,
        etc. All the odd ones, counting from the end.)
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":nth-last-of-type") }}</td>
      <td>
        Matches elements from a list of siblings that are of a certain type
        (e.g. <code>&#x3C;p></code> elements), counting backwards from the end.
        The siblings are matched by a formula of the form <var>an+b</var> (e.g.
        2n + 1 would match the last element of that type in the sequence, then
        two elements before that, then two elements before that, etc. All the
        odd ones, counting from the end.)
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":only-child") }}</td>
      <td>Matches an element that has no siblings.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":only-of-type") }}</td>
      <td>
        Matches an element that is the only one of its type among its siblings.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":optional") }}</td>
      <td>Matches form elements that are not required.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":out-of-range") }}</td>
      <td>Matches an element with a range when its value is out of range.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":past") }}</td>
      <td>Matches the elements before the current element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":placeholder-shown") }}</td>
      <td>Matches an input element that is showing placeholder text.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":playing") }}</td>
      <td>
        Matches an element representing an audio, video, or similar resource
        that is capable of being "played" or "paused", when that element is
        "playing".
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":paused") }}</td>
      <td>
        Matches an element representing an audio, video, or similar resource
        that is capable of being "played" or "paused", when that element is
        "paused".
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":read-only") }}</td>
      <td>Matches an element if it is not user-alterable.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":read-write") }}</td>
      <td>Matches an element if it is user-alterable.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":required") }}</td>
      <td>Matches form elements that are required.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":right") }}</td>
      <td>
        In <a href="/en-US/docs/Web/CSS/CSS_Pages">Paged Media</a>, matches
        right-hand pages.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":root") }}</td>
      <td>Matches an element that is the root of the document.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":scope") }}</td>
      <td>Matches any element that is a scope element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref(":valid") }}</td>
      <td>
        Matches an element such as an <code>&#x3C;input></code> element, in a
        valid state.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":target") }}</td>
      <td>
        Matches an element if it is the target of the current URL (i.e. if it
        has an ID matching the current
        <a href="https://en.wikipedia.org/wiki/Fragment_identifier"
          >URL fragment</a
        >).
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref(":visited") }}</td>
      <td>Matches visited links.</td>
    </tr>
  </tbody>
</table>

### Pseudo-elements

<table class="standard-table no-markdown">
  <thead>
    <tr>
      <th scope="col">Selector</th>
      <th scope="col">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>{{ Cssxref("::after") }}</td>
      <td>
        Inserts a stylable element appearing after the originating element's
        actual content, if used with the {{cssxref("content")}} property
        with a value other than <code>none</code>.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref("::before") }}</td>
      <td>
        Inserts a stylable element appearing before the originating element's
        actual content, if used with the {{cssxref("content")}} property
        with a value other than <code>none</code>.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref("::first-letter") }}</td>
      <td>Matches the first letter of the element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref("::first-line") }}</td>
      <td>Matches the first line of the containing element.</td>
    </tr>
    <tr>
      <td>{{ Cssxref("::grammar-error") }}</td>
      <td>
        Matches a portion of the document containing a grammar error as flagged
        by the browser.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref("::marker") }}</td>
      <td>
        Matches the marker box of a list item, which typically contains a bullet
        or number.
      </td>
    </tr>
    <tr>
      <td>{{ Cssxref("::selection") }}</td>
      <td>Matches the portion of the document that has been selected.</td>
    </tr>
    <tr>
      <td>{{ Cssxref("::spelling-error") }}</td>
      <td>
        Matches a portion of the document containing a spelling error as flagged
        by the browser.
      </td>
    </tr>
  </tbody>
</table>

{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}

## In this module

1. [Cascade and inheritance](/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance)
2. [CSS selectors](/en-US/docs/Learn/CSS/Building_blocks/Selectors)

    - [Type, class, and ID selectors](/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors)
    - [Attribute selectors](/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors)
    - [Pseudo-classes and pseudo-elements](/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements)
    - [Combinators](/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators)

3. [The box model](/en-US/docs/Learn/CSS/Building_blocks/The_box_model)
4. [Backgrounds and borders](/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders)
5. [Handling different text directions](/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions)
6. [Overflowing content](/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content)
7. [Values and units](/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)
8. [Sizing items in CSS](/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS)
9. [Images, media, and form elements](/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements)
10. [Styling tables](/en-US/docs/Learn/CSS/Building_blocks/Styling_tables)
11. [Debugging CSS](/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS)
12. [Organizing your CSS](/en-US/docs/Learn/CSS/Building_blocks/Organizing)
