Three States, Three Purposes
:hover— applies while the cursor sits over the button, before any click. It signals "this is interactive, and your cursor is on it right now.":active— applies during the actual click, between mouse-down and mouse-up. It gives the visual confirmation that the click registered.:focus— applies when the button has keyboard focus, typically from tabbing to it. This matters for keyboard users independent of mouse hover entirely.
A Typical Combination
.button {
background: #7c3aed;
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
transition: all 0.15s ease;
}
.button:hover {
background: #6d28d9;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.25);
}
.button:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
Hover lifts the button slightly with a bigger shadow, suggesting it's rising toward the cursor. Active flattens it back down with a smaller shadow, mimicking the button being physically pressed. Together, these two small changes go a long way toward making a flat CSS element feel tactile.
Why the Transition Property Matters
Without a transition, every state change happens instantly — the button snaps rather than smoothly moving. A short transition (150–250ms is a commonly recommended range) gives the state change a sense of motion without feeling sluggish or overly showy.
Don't Forget Focus
It's common to style :hover carefully and completely forget :focus — but keyboard users never trigger :hover at all, since they never move a cursor over the button. A button with no distinct focus style is effectively invisible to someone tabbing through the page with a keyboard, even if it looks polished to a mouse user.
Ready to design interactive states visually?
Open CSS Button Generator