Skip to content

Button states that convert

A practical guide to designing button states that communicate clearly and drive action.

Published
Reading time
2 min read

Why button states matter

Most buttons have five states: default, hover, focus, active and disabled. Most implementations only style two of them.

That leaves keyboard users without a visible focus state, and it leaves out the small details that make an interface feel finished.

The five states

Default

This is the button at rest. It should be clean and readable, with enough visual weight to show it can be clicked.

Hover

This is the button responding to the cursor. Use one subtle change: a colour change, a slight lift with translateY(-2px), or a shadow. Don't use all three at once.

Focus

This state matters most for keyboard navigation and accessibility. Use a visible outline or ring that passes WCAG 4.5:1 contrast against the background. Never set outline: none without a replacement.

Active

This is the button being pressed. A slight compress with scale(0.98) tells the user the press registered.

Disabled

This is the button that can't be clicked. Reduce opacity to 40 to 50%, change the cursor to not-allowed, and remove all hover effects.

Implementation

Here are all five states on one button, written with this site's colour tokens.

<button
  className="px-6 py-3 bg-vermilion text-ink
    hover:bg-ink hover:text-ivory
    focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink
    active:scale-[0.98]
    disabled:opacity-40 disabled:cursor-not-allowed
    transition-colors duration-200"
>
  Click me
</button>

Each state tells the user something specific, so design all five together as one system.

Where to go next