CSSUser-Action Pseudo-Classes (:hover, :focus, :active)

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."

CSS
.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.

CSS
.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.

CSS
.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).

CSS
.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);
}
Declaration order matters
Because :hover, :focus, and :active can all match the same element at the same time, the order you write these rules in your stylesheet affects which declarations "win" when specificity is otherwise equal (later rules override earlier ones for the same specificity). For anchor elements specifically, this is codified as the classic LVHA mnemonic — Link, Visited, Hover, Active — a required order that avoids common bugs like a hover style being silently overridden by the visited style. We cover that in detail on the link pseudo-classes page.
Practical guidance
  • Always pair :hover with a :focus (or :focus-visible) equivalent — keyboard users can never trigger :hover.

  • Keep :active styles subtle; it is only visible for a fraction of a second.

  • Use transition on the base rule (not on the pseudo-class rule) so both entering and leaving the state animate smoothly.

  • Never rely on :hover alone to reveal essential content — touchscreen and keyboard users may never trigger it.