facebook twitter
Webucator's Free Introduction to CSS Tutorial

Lesson: Pseudo-classes and Pseudo-elements

Welcome to our free Introduction to CSS tutorial. This tutorial is based on Webucator's Introduction to CSS Training course.

In this lesson, you will work with pseudo-classes and pseudo-elements.

Lesson Goals

  • Understand and use pseudo-classes.
  • Understand and use pseudo-elements.

Pseudo-classes

Pseudo-classes are keywords that can be added to a selector to target a specific state of the selected element(s). For example, :hover can be used to target the style of an element when the mouse is hovering over it.

Below is a table of pseudo-classes:

Pseudo-classes
Pseudo-class How it works
:active Selects an element being activated by a user (e.g., clicked).
:empty Selects an element that has no content (including whitespace).
:first-child Selects the first element in a group of siblings.
:first-of-type Selects the first element of its type in a group of siblings.
:hover Selects an element that is being hovered over with the mouse.
:lang() Selects elements that have content in the language specified in the parentheses, meaning that they have a lang attribute specifying the language. See a list of ISO 639-1 language codes on Wikipedia (https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes.)
:last-child Selects the last element in a group of siblings.
:last-of-type Selects the last element of its type in a group of siblings.
:link Selects a link element whose link has not been visited.
:not() Selects elements that are not specified in the parentheses.
:nth-child() Selects elements based on their position among their siblings.
:nth-last-child() Works exactly like :nth-child(), but starts from the last child and goes backwards.
:nth-last-of-type() Selects elements of certain type by position starting from the last element and going backwards.
:nth-of-type() Selects elements of certain type by position.
:only-child Selects elements that do not have any siblings.
:only-of-type Selects elements that do not have any siblings of the same type.
:root Selects the root element of the document. In HTML, this is always the html element.
:target Selects the element that is the current target, meaning that the URL is targeting that element's id (e.g.,index.html#article1).
:visited Selects a link element whose link has been visited. The only allowable properties are: color, background-color, border-color, and outline-color.

Many of these pseudo-classes are rarely used. We will look at the most useful ones below.

Styling Links with Pseudo-classes

The most commonly used pseudo-classes when styling links are:

  1. :visited
  2. :hover
  3. :active

We will also look at the :target pseudo-class. Although it is not used to style links, links determine what :target selects.

:link

Note that our demo does not include the :link pseudo-class. This is because you can use a simple a rule instead of a:link. If you do include both an a rule and an a:link rule the a:link rule will take precedence because it has a higher specificity.

First, let's look at how most browsers style links by default:

  1. Links are underlined.
  2. Links that have not been visited are blue.
  3. Links that have been visited are purple.
  4. Hovering over/clicking on a link makes the mouse a pointer.
  5. Active links (links being clicked on) are red.

Changing Link Styles

Be careful not to change link styles in a way that disguises the fact that they are links.

The demo below includes examples for how to style links.

Code Sample:

PseudoClassesAndElements/Demos/links-styles.css
body {
  background: aliceblue;
}

header {
  background: gray;
  border: black solid 1px;
  border-radius: 1rem;
  height: 160px;
  margin: 0 auto 0.5rem;
  padding: 0.5rem;
  width: 410px;
}

header h2 {
  padding-left: 0.5rem;
  text-decoration: underline;
}

#outside-links {
  background: white;
  border: black solid 1px;
  float: left;
  margin-right: 0.2rem;
  width: 200px;
}

#article-links {
  background: white;
  border: black solid 1px;
  float: left;
  width: 200px;
}

main {
  background: white;
  border: gray solid;
  border-radius: 0.5rem;
  height: 370px;
  margin: auto;
  width: 500px;
}

article {
  background: #ccc;
  border: solid black 1px;
  float: left;
  margin: 0.5rem;
  padding: 1rem;
  width: 200px;
}

article h2 {
  font-variant: small-caps;
  margin: 0;
}

a, 
a:visited {
  text-decoration: none;
  color: blue;
}

a:hover {
  text-decoration: underline;
}

a:active {
  color: gray;
}

:target h2 {
  font-style: italic;
  text-decoration: underline;
}

Code Sample:

PseudoClassesAndElements/Demos/links.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Links and Pseudo-classes</h1>
<header>
  <aside id="outside-links">
    <h2>Links</h2>
    <ol>
      <li>
        <a href="https://www.webucator.com/">
        Webucator</a>
      </li>
      <li>
        <a href="https://www.google.com/">
        Google</a>
      </li>
      <li>
        <a href="https://www.washingtonpost.com/">
          Washington Post</a>
      </li>
      <li><a href="https://www.wikipedia.org/">Wikipedia</a></li>
    </ol>
  </aside>
  <nav id="article-links">
    <h2>Articles</h2>
    <ol>
      <li><a href="#article1">Article 1</a></li>
      <li><a href="#article2">Article 2</a></li>
      <li><a href="#article3">Article 3</a></li>
      <li><a href="#article4">Article 4</a></li>
    </ol>
  </nav>
</header>
<main>
  <article id="article1">
    <h2>Article 1</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
      Nulla non gravida massa, sit amet commodo nisi...</p>
  </article>
  <article id="article2">
    <h2>Article 2</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Nulla non gravida massa, sit amet commodo nisi...</p>
  </article>
  <article id="article3">
    <h2>Article 3</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Nulla non gravida massa, sit amet commodo nisi...</p>
  </article>
  <article id="article4">
    <h2>Article 4</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Nulla non gravida massa, sit amet commodo nisi...</p>
  </article>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Styling Links with Pseudo-classes

Some things to note:

  1. We removed the underline from the links.
  2. We kept the signature blue color of the links.
  3. We made visited links appear exactly like links that haven't been visited.
  4. We added the underline back when the links are hovered over.
  5. We made the links turn gray when they are clicked.
  6. We underlined and italicized the h2 elements within the target. Note that article4 is the current target.
  7. In order to really see what's going on with the links, you will need to open links-demo.html in the browser and interact with them.

Styling Tables and Articles with Pseudo-classes

The following demos show how to use these pseudo-classes:

  1. :first-child
  2. :nth-child()
  3. :first-of-type
  4. :last-of-type

:nth-child()

The :nth-child() pseudo-class is a powerful selector that selects an element or elements based on their position. :nth-child() accepts several values:

  1. A positive integer (e.g., 1, 2, 3, etc.) to select one element in a specific position.
  2. The keywords even and odd to select either all the even elements in a selection or all the odd elements in a selection.
  3. A function in the form of An+B where A and B are integers and n is a variable. For example, #my-list li:nth-child(-n+3) would select the first three li elements in my-list (-0+3=3, -1+3=2, -2+3=1). Negative values are not valid.

The demo below shows how pseudo-classes can be used to style tables:

Code Sample:

PseudoClassesAndElements/Demos/table-pseudo-classes-styles.css
body {
  background: aliceblue;
}

table,
th,
td {
  border: solid black 1px;
  border-collapse: collapse; /* collapses 
                      the separate borders into single borders
                      between the table elements */
  padding: 0.2rem;
}

table {
  margin: auto;
  background: white;
}

caption {
  font-size: 1.5rem;
  font-weight: bold;
  text-decoration: underline;
}

thead {
  background: rgb(75, 75, 75);
  color: white;
  text-decoration: underline;
}

span.title {
  font-style: italic;
}

tfoot {
  background: rgb(75, 75, 75);
  color: white;
}

tbody td:first-child {
  font-style: italic;
}

tbody tr:nth-child(odd) {
  background-color: #ccc;
}

Code Sample:

PseudoClassesAndElements/Demos/table-pseudo-classes.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Using Pseudo-classes on a Table</h1>
<table>
  <caption>Great Books You Should Read</caption>
  <thead>
    <tr>
      <th>Title</th>
      <th>Author</th>
      <th>Genre</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Harry Potter and the Sorcerer's Stone*</td>
      <td>J. K. Rowling</td>
      <td>Fantasy</td>
    </tr>
    <tr>
      <td>To Kill a Mockingbird</td>
      <td>Harper Lee</td>
      <td>Novel</td>
    </tr>
    <tr>
      <td>Pride and Prejudice</td>
      <td>Jane Austen</td>
      <td>Romance</td>
    </tr>
    <tr>
      <td>The Diary of Anne Frank</td>
      <td>Anne Frank</td>
      <td>Non-fiction</td>
    </tr>
    <tr>
      <td>1984</td>
      <td>George Orwell</td>
      <td>Dystopia</td>
    </tr>
    <tr>
      <td>The Hunger Games</td>
      <td>Suzanne Collins</td>
      <td>Dystopia</td>
    </tr>
    <tr>
      <td>The Book Thief</td>
      <td>Mark Zusak</td>
      <td>Novel</td>
    </tr>
    <tr>
      <td>The Call of the Wild</td>
      <td>Jack London</td>
      <td>Novel</td>
    </tr>
    <tr>
      <td>Hamlet</td>
      <td>William Shakespeare</td>
      <td>Play - Tragedy</td>
    </tr>
    <tr>
      <td>The Lord of the Rings</td>
      <td>J. R. R. Tolkien</td>
      <td>Fantasy</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3" class="info">*The original title of 
        <span class="title">Harry Potter and 
          the Sorcerer's Stone</span> was 
        <span class="title">Harry Potter and 
          the Philosopher's Stone</span>.
      </td>
    </tr>
  </tfoot>
</table>
</body>
</html>

Code Explanation

The code above will render the following:Styling Links with Pseudo-classes 2

Some things to note:

  1. There are a lot of rules that don't use pseudo-classes. These rules are used to create the display of the demo.
  2. :first-child is used to select the book titles and make them italic.
  3. :nth-child() is used to make the odd tr elements in the table gray.

Below is a demo showing how pseudo-classes can be used to help style articles.

Code Sample:

PseudoClassesAndElements/Demos/articles-pseudo-classes-styles.css
body {
  background: aliceblue;
}

header {
  background: gray;
  border: black solid 1px;
  border-radius: 1rem;
  margin: auto;
  width: 50%;
}

a,
a:visited {
  color: blue;
}

main {
  background: white;
  margin: auto;
  width: 75%;
}

article {
  border: black solid 1px;
  border-radius: 0.5rem;
  padding: 0.2rem 1rem 0.5rem;
  margin: 0.5rem auto;
}

article p:first-of-type {
  font-size: larger;
}

article p:last-of-type {
  font-size: smaller;
  font-style: italic;
}

Code Sample:

PseudoClassesAndElements/Demos/articles-pseudo-classes.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Using Pseudo-classes to Style Some Articles</h1>
<header>
  <nav>
    <ol>
      <li><a href="#article1">Article 1</a></li>
      <li><a href="#article2">Article 2</a></li>
      <li><a href="#article3">Article 3</a></li>
    </ol>
  </nav>
</header>
<main>
  <article id="article1">
    <h2>Article 1</h2>
    <p>
      This is the beginning of article 1. Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>
      Proin dolor turpis, tincidunt ac 
      consequat nec, luctus in justo. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>Written by So-and-so.</p>
  </article>
  <article id="article2">
    <h2>Article 2</h2>
    <p>
      This is the beginning of article 1. Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>
      Proin dolor turpis, tincidunt ac 
      consequat nec, luctus in justo. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>Written by What's-his-face.</p>
  </article>
  <article id="article3">
    <h2>Article 3</h2>
    <p>
      This is the beginning of article 1. Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>
      Proin dolor turpis, tincidunt ac 
      consequat nec, luctus in justo. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>Written by You-know-who.</p>
  </article>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Styling Links with Pseudo-classes 2

Some things to note:

  1. There are a lot of rules that don't use pseudo-classes. These rules are used to create the display of the demo.
  2. :first-of-type is used to select the first p elements in each article and make them larger.
  3. :last-of-type is used to select the last p elements in each article to make them smaller and italic.

Pseudo-elements

Pseudo-elements are keywords that can be added to a selector to target a specific part of the selected element(s). For example, ::first-letter can be used to target the first letter of the text within an element.

Below is a table of pseudo-elements:

Pseudo-elements
Pseudo-class How it works
::after Creates a pseudo-element that is the last child of the selected element. This pseudo-element can be given content with the content property (https://developer.mozilla.org/en-US/docs/Web/CSS/content).
::before Creates a pseudo-element that is the first child of the selected element. This pseudo-element can be given content with the content property.
::first-letter Selects the first letter of the first line of text in the selected element(s).
::first-line Selects the first line of text in the selected element(s).
::selection Selects the content that has been highlighted by the user with the mouse. The properties that can be used with ::selection are very limited (https://developer.mozilla.org/en-US/docs/Web/CSS/::selection).

Two colons vs. one colon

You may see pseudo-elements written with just one colon (e.g., :first-letter), which is the old syntax. The new syntax is to use two colons to distinguish pseudo-elements from pseudo-classes. While browsers support both, you should use the new syntax.

content

The content property is used with ::before and ::after. It can be used to add:

  1. A string (i.e., text).
  2. An image as a URL value. Note that the image is displayed in its original size and cannot be manipulated in any way.
  3. A counter, generally a number, using the CSS counter() or counters() function (https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters).
  4. A string value of an element's attribute using attr(x) where x is the element's attribute (e.g., attr(id)).

Using Pseudo-elements

Like pseudo-classes, pseudo-elements are infrequently used, but there are cases where they can be useful, like in the demo below:

Code Sample:

PseudoClassesAndElements/Demos/pseudo-elements-styles.css
body {
  background: aliceblue;
}

header {
  background: gray;
  border: black solid 1px;
  border-radius: 1rem;
  margin: auto;
  width: 200px;
}

main {
  background: white;
  border: black solid 1px;
  margin: 0.5rem auto;
  width: 400px;
}

section {
  margin: auto;
  width: 75%;
}

a, 
a:visited {
  color: blue;
}

aside {
  margin: 0.5rem auto;
  width: 75%;
}

.bio {
  font-style: italic;
}

:target h2::before {
  content: "\2192";
}

section p:first-of-type::first-line {
  font-style: italic;
}

section p:first-of-type::first-letter {
  font-size: xx-large;
}

.note::after {
  content:"*"
}

.bio::before {
  content:"*";
}
            

Code Sample:

PseudoClassesAndElements/Demos/pseudo-elements.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Using Pseudo-elements</h1>
<header>
  <nav>
    <ol>
      <li><a href="#chapter1">Chapter 1</a></li>
      <li><a href="#chapter2">Chapter 2</a></li>
      <li><a href="#acknowledgements">Acknowledgements</a></li>
    </ol>
  </nav>
</header>
<main>
  <section id="chapter1">
    <h2>Chapter 1</h2>
    <p>
      This is the beginning of chapter 1. Lorem ipsum 
      dolor sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>
      Proin dolor turpis, tincidunt ac 
      consequat nec, luctus in justo. 
      
---- C O D E   O M I T T E D ----

    </p>
  </section>
  <section id="chapter2">
    <h2>Chapter 2</h2>
    <p>
      This is the beginning of chapter 2. Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus. 
      
---- C O D E   O M I T T E D ----

    </p>
    <p>
      Proin dolor turpis, tincidunt ac 
      consequat nec, luctus in justo. 
      
---- C O D E   O M I T T E D ----

    </p>
  </section>
  <aside id="acknowledgements">
    <h2>Acknowledgements</h2>
    <p>This story was written thanks 
      to So-and-so, What's-his-face, and 
      <span class="note">You-know-who</span>.</p>
    <p class="bio">You-know-who is a long-time friend and editor, 
      winner of numerous writing awards...</p>
  </aside>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Styling Links with Pseudo-classes 2

Some things to note:

  1. There are a lot of rules that don't use pseudo-elements. These rules are used to create the display of the demo.
  2. ::before is used to give the h2 elements within the target an arrow before the targeted section. Note that chapter1 is the target in the image.
  3. ::after and ::before are also used to give an asterisk (*) to the note and bio classes.
  4. ::first-letter is used to make the first letter in each chapter bigger.
  5. ::first-line is used to make the first line in each chapter italic.

Pseudo-classes and Pseudo-elements

Duration: 25 to 40 minutes.

In this exercise, you will continue to work on the Runners Home page.

  1. Open PseudoClassesAndElements/Exercises/index.html in your editor. You will see the homepage for a website called Runners Home.
  2. Open PseudoClassesAndElements/Exercises/styles.css. This is the stylesheet from the solution to the Backgrounds exercise. Feel free to continue working from your own stylesheet.
  3. Using your new knowledge of pseudo-classes and pseudo-elements add some styles to this page. The object of this exercise is to practice using the properties covered in this lesson. Also, feel free to add or change any other properties that you know.
  4. When you are done, open index.html in your browser to see the results. You are welcome to go back to the code and continue to work.

You can design it however you like, or you can try to:

  • Make all links blue when they are normal or have been visited.
  • Make the nav links purple when they are hovered over and red when they are clicked on.
  • Give articles a blur box-shadow effect when they are hovered over.
  • Make the first letter in each article larger and bold, and make the first line italic.
  • Make the .read-more links underlined when they are hovered over and purple when they are clicked.

Solution:

PseudoClassesAndElements/Solutions/styles.css
html {
  font-size: 16px;
}

body {
  background-image: url(images/runners.png);
  background-size: cover;
  font: 1rem/1.3 Verdana, Geneva, Tahoma, sans-serif;
}

nav {
  background: url(images/runner.png) no-repeat bottom right;
  background-color: white;
  border: solid rgb(110, 78, 226) 0.1rem;
  border-radius: 1rem;
  box-shadow: 0.5rem 0.5rem 1rem rgb(110, 78, 226, .5);
  margin: 1rem;
  width: 40%;
}

nav a {
  text-decoration: none;
}

nav a:hover {
  color: purple;
}

nav a:active {
  color: red;
}

main {
  background: rgba(232, 232, 232, 0.8);
  padding: 2%;
  max-width: 1000px;
  min-width: 750px;
}

#welcome {
  font-size: larger;
}

#welcome h1 {
  color: rgb(8, 5, 211);
  text-shadow: 0.2rem 0.2rem 0.1rem rgb(211, 200, 238);
}

article {
  background: white;
  border: 1px ridge rgb(226, 77, 40);
  box-sizing: border-box;
  margin: 1em auto;
  padding: 1rem;
  max-width: 75%;
  text-align: center;
}

article h2 {
  font-variant: small-caps;
  letter-spacing: 0.1em;
  word-spacing: 0.2em;
}

article p {
  line-height: 2;
  text-align: left;
  text-indent: 3rem;
}

article:hover {
  box-shadow: 0 0 1rem 0.5rem rgba(189, 101, 189, 0.5);
}

article p:first-of-type::first-line {
  font-style: italic;
}

article p:first-of-type::first-letter {
  font-size: larger;
  font-weight: bold;
}

a, a:visited {
  color: blue;
}

.read-more {
  text-decoration: none;
}

a.read-more:hover {
  text-decoration: underline;
}

a.read-more:active {
  color: purple;
}

aside label {
  font-weight: bold;
}

#newsletter {
  background: white;
  border: 1px dashed rgb(110, 78, 226);
  border-radius: 1em;
  margin: 0 1rem;
  padding: .5rem 1rem;
  text-align: right;
}

footer {
  font-size: smaller;
  font-style: italic;
  margin: 1rem;
}

Code Explanation

You will need to open PseudoClassesAndElements/Solutions/index.html in the browser and interact with the page to see the :hover and :active effects we added.