User-Action Pseudo-Classes (:hover, :focus, :active)
User-action pseudo-classes let you style an element differently depending on how a person is currently interacting with it. The three most common ones — :hover, :focus, and :active — cover the pointer, the keyboard/programmatic focus, and the moment of being pressed.
:hover
:hover matches an element while a pointing device (typically a mouse) is positioned over it. It has no meaning on touch-only devices, where there is no persistent "pointer position."
.button {
background: #2563eb;
color: white;
transition: background 0.15s ease;
}
.button:hover {
background: #1d4ed8;
}:focus
:focus matches an element that currently has keyboard or programmatic focus — for example, an input the user has tabbed into, or an element that received .focus() from JavaScript.
.button:focus {
outline: 2px solid #2563eb;
outline-offset: 2px;
}:active
:active matches an element during the (very brief) moment it is being pressed — the mouse button is down, or a touch/tap is in progress, on that specific element.
.button:active {
background: #1e40af;
transform: translateY(1px);
}The order of a real interaction
Clicking a button with a mouse typically triggers these states in this order: the pointer moves over the element (:hover begins), the mouse button goes down (:active begins, and the element usually also gains :focus at this point), the mouse button is released (:active ends, :focus and :hover remain).
.button {
background: #2563eb;
color: white;
border: none;
padding: 0.6em 1.2em;
border-radius: 6px;
transition: background 0.15s ease, transform 0.1s ease;
}
.button:hover {
background: #1d4ed8;
}
.button:focus-visible {
outline: 2px solid #93c5fd;
outline-offset: 2px;
}
.button:active {
background: #1e40af;
transform: translateY(1px);
}Practical guidance
Always pair
:hoverwith a:focus(or:focus-visible) equivalent — keyboard users can never trigger:hover.Keep
:activestyles subtle; it is only visible for a fraction of a second.Use
transitionon the base rule (not on the pseudo-class rule) so both entering and leaving the state animate smoothly.Never rely on
:hoveralone to reveal essential content — touchscreen and keyboard users may never trigger it.