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:
- A simple text editor (like Notepad, VS Code, or any code editor)
- A web browser (Chrome, Firefox, Edge, Safari, etc.)
Steps to set up:
- Create a new file called
pseudo-classes.html. - Copy the code from each example into that file.
- Save it.
- 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?
atargets all links.a:hoverapplies only when your mouse is over the link.a:activeapplies only while you are clicking the link.a:visitedapplies 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?
.btnis a class selector that styles elements withclass="btn"..btn:hoverchanges the background color when the mouse is over the button..btn:activedarkens 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.:focusapplies 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:hoverand.btn:focustogether) - Using pseudo-elements like
::beforeand::afterfor 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!
