When do the :hover, :focus, and :active pseudo-classes apply?

When we select an element by its .class or #id, we’re using predefined and unchanging attributes that are baked into the DOM. With pseudo-classes, we can select elements using information that isn’t already in the DOM and can change based on how a user interacts with the page.

:hover, :focus, and :active are pseudo-classes that are determined by a user’s actions. They each correspond to a very specific point in how a user will interact with an element on a page such as a link or a button or an input field.

With the range in input devices we have today, these pseudo-classes also behave slightly differently depending on if the user is interacting with the element with a mouse 🐭, keyboard ⌨️, or touchscreen 📱, which can make it difficult to know how and when to style these situations.

When :hover is applied

The :hover pseudo-class, also called the “pointer hover pseudo-class”, applies when a pointing device interacts with an element without necessarily activating it.

A typical example of this is when a mouse 🐭 hovers over an element. If you hover your mouse over the button below, you’ll see that it turns yellow.

button:hover { background-color: #ffdb3a; }

 

When on a mobile device 📱, there’s basically only one interaction you can take with any interactive element, which is tapping/clicking it. You may notice that if you tap on the button above, it also changes the colour despite the fact that you aren’t “just” hovering over it. This is because, on mobile devices, the events that trigger these pseudo-classes can become conflated. We’ll see with :focus and :active pseudo-classes as well.

Finally, for users of keyboard devices ⌨️, the :hover pseudo-class is never triggered. The keyboard is not considered a “pointer” device and so can’t apply to this pointer hover pseudo-class.

When :focus is applied

The :focus pseudo-class applies when an element is in a state that is ready to be interacted with, i.e. it has the focus of the input device. When this applies differs quite greatly between the different input devices.

When using a mouse 🐭 or similar pointing device, the :focus pseudo-class will apply once the user has begun activating the element and, importantly, it will continue to stay in focus until the user activates another element. For example, if you click the button below with a mouse, you’ll notice that it turns yellow once you begin the click interaction. The button will only return to its default state if you click somewhere else on the page.

button:focus { background-color: #ffdb3a; }

 

For keyboard users ⌨️, focusing on an element is very similar to hovering over it for mouse users. I like to think of the :focus pseudo-class as a hover state for keyboard devices, because it signals a similar intention for interaction.

For touchscreen users 📱, the :focus pseudo-class applies, again, when the user taps on the element. However, it should be noted that this doesn’t apply for the mobile Safari browser.

When :active is applied

Finally, the :active pseudo-class applies during the period in which the element is being activated. For example, if using a mouse 🐭, it would be the time between when the mouse button is clicked and when it is released.

If you click the button below quickly, you may not notice the brief change in colour, but if you press and maintain, you’ll see when the pseudo-class is applied.

button:active { background-color: #ffdb3a; }

 

The :active pseudo-class works in the same way for mouse and keyboard ⌨️ interactions.

On mobile devices 📱, like the :focus pseudo-class, the :active pseudo-class applies on the tap of the element. And again, it doesn’t apply at all in the mobile Safari browser.

Combining :hover, :focus, and :active

One thing you may have noticed is that the conditions in which each of these pseudo-classes can be applied are not mutually exclusive. In fact, most times when an element is being clicked with a mouse, all three conditions are valid - the mouse if over the element, the element is in focus, and the element is being activated.

We can test this by only changing the background of the button if all three conditions apply.

button:hover:focus:active {
  background-color: #ffdb3a;
}

If you click and hold the button below, you’ll see that it turns yellow. But if you click and hold while dragging your mouse away from hovering over it, you’ll see that it loses the colour.

 

This ability to combine the pseudo-classes can be really helpful for fine-tuning how we want to style the different states.

Order of styles - :hover then :focus then :active

Due to the fact that these conditions can and frequently are applied at the same time, the order in which we add these styles is important.

Let’s say we have the following styles:

button:active {
  background-color: green;
}

button:focus {
  background-color: blue;
}

button:hover {
  background-color: red;
}
Only the :hover styles will be visible

 

When you hover and interact with the element above, only the styles applied to :hover will prevail as long as you are still hovering over it. As we’ve seen, since all three events are applied during a typical click event, the cascade takes over and the last-defined style wins.

This is why it’s important to define these styles in the order in which they typically happen, so it becomes clear to the user when a new interaction is recognised. Typically, a user will first hover over an element, then bring it to focus, then activate it. So, the best way to order your pseudo-class styles are :hover then :focus then :active .

button:hover {
  background-color: green;
}

button:focus {
  background-color: blue;
}

button:active {
  background-color: red;
}
All styles will be visible

 

Recap

The :hover, :focus, and :active pseudo-classes allow us to style elements in response to how a user interacts with it. Depending on the device being used, these pseudo-classes become active at different points (or not at all).

  :hover :focus :active
Mouse 🐭 Yes Yes Yes
Keyboard ⌨️ No Yes Yes
Touchscreen 📱 Yes (on click) Yes* (on click) Yes* (on click)

* Will not apply on mobile (iOS) Safari

blog comments powered by Disqus