Mudzinga

Discover how CSS pseudo-classes let you style links, buttons, and forms based on their state. Learn with simple examples and start making your pages feel interactive—read now!

5 Minute Read

Pseudo-Classes: Styling Element States

Pseudo-Classes: Styling Element States

When you move your mouse over a button and it changes color, or you click a link and it looks different afterward, you’re seeing pseudo-classes in action.

In this article, you’ll learn what pseudo-classes are, why they matter, and how to use them to make your web pages feel more interactive and user-friendly. We’ll walk through simple, hands-on examples you can try right away—even if you’re brand new to coding.


What is a pseudo-class?

A pseudo-class is a special keyword in CSS that lets you style an element based on its state.

Think of a button:

  • Normal state (just sitting there)
  • Hover state (when your mouse is over it)
  • Active state (when you’re clicking it)

Each of these is the same element, but in a different state. Pseudo-classes let you say: “When this element is hovered, look like this. When it’s clicked, look like that.”

You write a pseudo-class like this:

selector:pseudo-class {
  /* styles go here */
}

Example:

a:hover {
  color: red;  /* When the user hovers over a link, make it red */
}

Getting set up (so you can follow along)

To practice, you only need:

  1. A simple text editor (like Notepad, VS Code, or any code editor)
  2. A web browser (Chrome, Firefox, Edge, Safari, etc.)

Steps to set up:

  1. Create a new file called pseudo-classes.html.
  2. Copy the code from each example into that file.
  3. Save it.
  4. Double-click the file to open it in your browser.

You can then adjust the CSS and refresh the browser to see changes.


Example 1: Styling link states with pseudo-classes

Let’s start with something very common: links (<a> elements).

Create this simple page:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Link Pseudo-Classes</title>
  <style>
    /* Basic style for all links */
    a {
      text-decoration: none;     /* Remove underline */
      color: blue;               /* Default link color */
      font-size: 18px;
    }

    /* :hover — when the mouse is over the link */
    a:hover {
      color: orange;             /* Link turns orange on hover */
    }

    /* :active — when the link is being clicked */
    a:active {
      color: red;                /* Link turns red while you click */
    }

    /* :visited — links you've already clicked */
    a:visited {
      color: purple;             /* Visited links appear purple */
    }
  </style>
</head>
<body>
  <h1>Link States</h1>
  <p>
    Visit <a href="https://example.com" target="_blank">Example.com</a>
  </p>
</body>
</html>

What’s happening here?

  • a targets all links.
  • a:hover applies only when your mouse is over the link.
  • a:active applies only while you are clicking the link.
  • a:visited applies to links you’ve already opened before.

Expected result:

  • Default: blue link.
  • Hover: orange.
  • While clicking: red.
  • After visiting: purple.

Try it yourself

Change the colors to your favorites. For example, make the hover state green and the visited state gray. Refresh the page and test how it feels.


Example 2: Button hover and active states

Now let’s style a button so it feels clickable and responsive.

Add this code to your HTML (or make a new file):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Button States</title>
  <style>
    /* Base button style */
    .btn {
      background-color: #3498db;   /* Blue background */
      color: white;                /* White text */
      padding: 10px 20px;          /* Space around the text */
      border: none;                /* No border */
      border-radius: 4px;          /* Slightly rounded corners */
      cursor: pointer;             /* Show pointer on hover */
      font-size: 16px;
      transition: background-color 0.2s ease, transform 0.1s ease;
    }

    /* :hover — mouse is over the button */
    .btn:hover {
      background-color: #2980b9;   /* Darker blue when hovered */
    }

    /* :active — button is being pressed */
    .btn:active {
      background-color: #1c5980;   /* Even darker blue when clicked */
      transform: translateY(1px);  /* Move slightly down for a "press" effect */
    }
  </style>
</head>
<body>
  <h1>Button States</h1>
  <button class="btn">Click Me</button>
</body>
</html>

What’s happening here?

  • .btn is a class selector that styles elements with class="btn".
  • .btn:hover changes the background color when the mouse is over the button.
  • .btn:active darkens the color and moves the button down just a little when pressed, making it feel more “real.”

Expected result:

  • The button looks like a modern blue button.
  • When you hover: it becomes a darker blue.
  • When you click and hold: it becomes even darker and moves down slightly.

Try it yourself

Change the transform: translateY(1px); to translateY(3px); and see how the effect changes. Does it feel too dramatic? Adjust until it feels right to you.


Example 3: Highlighting focused form fields

Forms become much easier to use when the active field stands out. The :focus pseudo-class is perfect for this.

Use this code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Form Focus State</title>
  <style>
    input[type="text"] {
      padding: 8px;
      border: 2px solid #ccc;   /* Light gray border */
      border-radius: 4px;
      font-size: 16px;
      outline: none;            /* Remove default focus outline */
      transition: border-color 0.2s ease, box-shadow 0.2s ease;
    }

    /* :focus — when the field is active (clicked into) */
    input[type="text"]:focus {
      border-color: #3498db;    /* Blue border when focused */
      box-shadow: 0 0 3px #3498db;  /* Soft blue glow */
    }
  </style>
</head>
<body>
  <h1>Form Focus</h1>
  <label for="name">Your Name:</label>
  <br />
  <input type="text" id="name" placeholder="Type your name here" />
</body>
</html>

What’s happening here?

  • input[type="text"] selects all text input fields.
  • :focus applies when the user clicks inside the field or tabs into it from the keyboard.
  • We change the border color and add a soft shadow to highlight the field.

Expected result:

  • The text box looks normal at first.
  • When you click inside it, the border turns blue and a soft glow appears.

Try it yourself

Add another input field, such as an email field:

<input type="email" placeholder="Your email" />

Then create a similar focus style for it (e.g., input[type="email"]:focus). Try using a different color for email fields to distinguish them.


Example 4: Using :nth-child to style every other list item

Pseudo-classes are not just for interactive states. They can also help you style elements based on their position.

One useful one is :nth-child(), which lets you target items like “every second item” or “the third item.”

Try this example:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>List Styling with :nth-child</title>
  <style>
    ul {
      list-style: none;      /* Remove default bullets */
      padding: 0;
    }

    li {
      padding: 8px 12px;
    }

    /* Style every odd item (1st, 3rd, 5th, ...) */
    li:nth-child(odd) {
      background-color: #f2f2f2;   /* Light gray */
    }

    /* Style every even item (2nd, 4th, 6th, ...) */
    li:nth-child(even) {
      background-color: #ffffff;   /* White */
    }
  </style>
</head>
<body>
  <h1>Striped List</h1>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
</body>
</html>

What’s happening here?

  • li:nth-child(odd) styles list items in positions 1, 3, 5, etc.
  • li:nth-child(even) styles positions 2, 4, 6, etc.
  • Together, they create a “striped” effect that makes lists easier to read.

Expected result:

  • Your list items will alternate background colors.
  • This is often used in tables and lists to make them clearer.

Try it yourself

Change odd to 3n like this:

li:nth-child(3n) {
  background-color: #ffeaa7;  /* Light yellow every 3rd item */
}

Now every 3rd item is highlighted. Experiment with different patterns.


Quick recap of key pseudo-classes

Here are some common pseudo-classes you’ve just used:

  • :hover — when the mouse is over an element
  • :active — when the element is being clicked
  • :visited — links the user has already visited
  • :focus — when an element (like an input) is active and ready for typing
  • :nth-child() — style elements based on their position in a list

Each one helps you respond to what the user is doing or how the page is structured, without changing your HTML.


What’s next?

You’ve just taken a big step toward making your web pages feel alive and interactive. Pseudo-classes are a powerful tool, and you’ve already used several of the most important ones.

From here, you might explore:

  • More pseudo-classes like :first-child, :last-child, and :checked
  • Combining pseudo-classes with classes (for example, .btn:hover and .btn:focus together)
  • Using pseudo-elements like ::before and ::after for extra decorations

Most importantly, keep experimenting. Change colors, sizes, and effects. Celebrate each small improvement—every time you tweak a style and refresh the browser, you’re learning real, practical web development skills.

You’re doing great. Keep going!

About Percy Mudzinga

This article was automatically generated by an AI-powered blog system built by Percy.
Percy Mudzinga is a Senior Full-Stack Software Engineer based in Harare, Zimbabwe, with nearly a decade of experience building enterprise web and mobile applications. He specializes in React, Vue.js, Flutter, and Node.js.

Never Miss an Update

Subscribe to our newsletter and get the latest articles delivered directly to your inbox every week.

No spam, unsubscribe anytime. We respect your privacy.

© 2025 Mudzinga. All rights reserved.