CSS: Pseudo-class and Pseudo-element

Basics - Backgrounds - Text - Box Model - Selectors and Combinators - Pseudo-class and Pseudo-element - Gradients - Animations and Transitions - CSS in AoPS - List of Elements

A pseudo-class and a pseudo-element are extensions to an element in a CSS document that configure how the document looks in specific situations.


A pseudo-class is used to manipulate an element in a such way that cannot be done with simple selectors and/or access to the document source.


A pseudo-class is normally between a selector and the first curly bracket, always starts with a colon ( : ), and this colon is always immediately followed by the name of the pseudo-class.

Some pseudo-classes have the option of placing a value between parentheses.

Dynamic pseudo-classes

A dynamic pseudo-class is a pseudo-class that configures an element based on a user action.

:link and :visited

The :link and :visited pseudo-classes are reserved exclusively for links ( <a>; anchor tags).

  • The :link pseudo-class configures a link when it is unvisited; that is, the page to which a link redirects to has not been visited.
  • The :visited pseudo-class applies to links that have been visited; that is, the page to which a link redirects to has been visited.

:hover, :active, and :focus

The :hover pseudo-class can apply to all elements, the :active pseudo-class normally applies to links (but can be applied to any element), and the :focus pseudo-class is used for text areas almost exclusively.

  • The :hover pseudo-class is activated when a user "hovers" over an element with a mouse, trackpad, or any pointing device. To hover over an element, the cursor is normally placed on the element, but the user does not click on the element.
  • The :active pseudo-class describes the look of an element between the time a user presses the mouse button and releases it. :active normally applies only to the primary button on a pointing device ("left-click" for most users).
  • The :focus pseudo-class applies when an element that accepts keyboard, mouse, or any other form of input has focus. This concept may be hard to understand, so think of a text-area element as having focus when what you type on your keyboard appears in the element.


If the child of an element is hovered upon, and that parent element is configured to act in a certain way when hovered upon, the parent element will be affected, as a child element is still considered part of a parent element.

:target pseudo-class

Some URLs have a little number sign (#) near the end followed by some characters. What does this do?

Well, those little characters after the # sign refer to the id of some element, known as the target element. When you click on that link, the element with that id is selected by the :target pseudo-class.

The :target pseudo-class exploits this situation to create all sorts of interesting stuff. For example,


#red{ background-color: white; }
#red:target{ background-color: red; }

says that when the element with id "red" becomes the target element (i.e. the URL in the address bar of your browser ends in "#red"), its background will turn from white to red.

Familiarizing yourself with this pseudo-class may require some practice, which can be found here.

Structural pseudo-classes

A structural pseudo-class configures an element based on its position in the structure of the HTML document, or document tree.

:nth-child() pseudo-class

The :nth-child(an+b) pseudo-class notation is used to describe the element that is the $an+b$th child of its parent, where $a$ and $b$ are integers and $a > b$.

For positive values of $a$ and $b$, the elements affected are determined by taking the modulo $a$ residue of $b$, and then adding this residue onto consecutive multiples of $a$ (0 included). The resulting numbers specify which elements are to be affected in the document tree.


tr:nth-child(2n+1){ background-color: yellow; }

states that every odd row of a table is to have a yellow background.

The :nth-child() pseudo-class can also take on "odd" and "even" as values between the brackets. "odd" is equal to $2n+1$, while "even" is equal to $2n+0$.

There are several rules to using the :nth-child() pseudo-class:

  1. If $a=0$, then the $an$ part may be removed, leaving just $b$.
  2. If $b=0$, then it may be removed, leaving just $an$.
  3. If $|a|=1$, then $a$ may be removed, leaving just $n+b$.
  4. If $b<0$, then a minus sign (-) must be placed before the $b$ and the plus sign (+) must be omitted.
  5. If $a<0$, then $an+b > 0$, or else no element will be affected.

Note that for :nth-child(1), :first-child is a universally accepted replacement.

:nth-last-child() pseudo-class

The :nth-last-child(an+b) notation is used to describe the element that has an+b-1 siblings after it in a document tree.

See :nth-child() pseudo-class for syntax. :nth-last-child() also accepts "odd" and "even" as arguments.

Note that for :nth-last-child(1), :last-child is a universally accepted replacement.

:nth-of-type() pseudo-class

The :nth-of-type(an+b) notation is used to describe the element that has an+b-1 siblings of the same type before it in the document tree.

Example: In this document

<li class="a">A</li>
<li class="b">o</li>
<li class="b">P</li>
<li class="c">S</li>

the following says that the "P" in "AoPS" is to be colored red.

li.b:nth-of-type(2){ color: red; }

See :nth-child() pseudo-class for syntax. :nth-of-type() also accepts "odd" and "even" as arguments.

Note that for nth-of-type(1), :first-of-type is a universally accepted replacement.


The :nth-last-of-type(an+b) notation is used to describe the element that has an+b-1 siblings of the same type after it in a document tree.

See :nth-child() pseudo-class for syntax. :nth-last-of-type() also accepts "odd" and "even" as arguments.

Note that for :nth-last-of-type(1), :last-of-type is a universally accepted replacement.

:not() pseudo-class

The :not(foo) pseudo-class represents an element that is not represented by the value within the brackets.

Basically, it excludes all elements that are represented in any way (class, id, etc.) by the argument.


div:not(#abc){ text-transform: uppercase; }

states that every <div> division that does not have ID abc is to have exclusively uppercase letters.

a:not(:hover){ color: lawngreen; }

states that when a link is not hovered upon, it will have a light green color.


span:not(:not(.hi)){ font-variant: small-caps; }

is not correct; you cannot nest a :not() pseudo-class inside a :not() pseudo-class.


The :matches(foo,bar) pseudo-class selects all elements that are selected by the selectors






The following

:matches(main, aside) :matches(section, article) :matches(section, article) :matches(ul, ol, dl){
    color: black;

is equivalent to

main section section ul, main section article ul,
main article section ul, main article article ul,
main section section ol, main section article ol,
main article section ol, main article article ol,
main section section dl, main section article dl,
main article section dl, main article article dl,
aside section section ul, aside section article ul,
aside article section ul, aside article article ul,
aside section section ol, aside section article ol,
aside article section ol, aside article article ol,
aside section section dl, aside section article dl,
aside article section dl, aside article article dl{
    color: black;


This is a non-standard pseudo-class, introduced only in Selectors Level 4; it used to be
but the syntax was changed by the W3C. None of the major browsers have followed suit however, and all of them continue to use prefixed versions of
. The following browsers support it:
Browser Prefix/Version first supported
Google Chrome
Mozilla Firefox
Internet Explorer Not supported
Opera Not supported


Pseudo-elements are used to manipulate elements in a such way that cannot be done with pseudo-classes and/or other simple selectors.

Pseudo-elements can also add information to a document without access to the source code itself.


A pseudo-element consists of a colon (:) followed by the name of the pseudo-element.


The latest standard for CSS selectors, Selectors Level 3, states that two colons (::) should be used in place of the single colon for pseudo-elements. However, doing so will remove compatibility with most browsers released before September 29, 2011.

Also note that multiple pseudo-elements are allowed per selector, given that their functions do not interfere with each other and that each pseudo-element is placed on a separate rule by itself. For example,

span:first-letter{ background-color: orange; }
span:first-line{ background-color: orange; }

is not allowed as the functions of the :first-letter and :first-line pseudo-elements interfere with each other.

:before and :after pseudo-elements

The :before and :after pseudo-elements add content before or after an element's content respectively.


When using a dynamic pseudo-class or the :target pseudo-class on an element to which a :before or :after pseudo-element applies to, and you want the psuedo-element(s) to react to the dynamic pseudo-class/:target pseudo-class being activated, you must place the pseudo-class before the pseudo-element. So while this is perfectly valid:

    content: ""; 
    border-width: 0 0 0 4px; 
    border-color: transparent blue; 

this will not work at all:

    content: ""; 
    border-width: 0 0 0 4px; 
    border-color: transparent blue; 

Adding content

To add content, we use the content property. There are several values for this property; the most useful are described here.

Value Description
"bool " Sets content to be text you specify in place of bool
attr(foo) Sets content to be an attribute foo of the element. More attributes here.

For more information on possible values that this property can take, see here.

:first-line pseudo-element

The first-line pseudo-element formats the first line of text in an element.


.message:first-line{ font-weight: bold; }

states that the first line of all blog entries is to be in bold.


When :first-line is applied to a selector to which a :before and/or :after pseudo-element also applies to, the generated content is affected by the :first-line pseudo-element.

:first-letter pseudo-element

The :first-letter pseudo-element formats the first letter of text in an element.


#header h1:first-letter{ text-shadow: 0 0 15px #000 }

states that the first letter in your blog title will have a black text shadow with blur distance 15 pixels.


As with the :first-line pseudo-element, generated content is also affected by the :first-letter pseudo-element.

See Also