Skip to main content
← 🎨 CSS as a design systemΒ·Module B7 Β· Lesson 10
TaskBuild a polished button with all four states. .button base + .button:hover (translate -1px + shadow) + .button:active (translate 0 + smaller shadow) + .button:focus-visible (outline 2px solid + 2px offset).

Hover and focus polish

60 XP5 min
Theory

Small details that signal "polished"

.button {
  background: #3B82F6;
  color: white;
  border-radius: 8px;
  padding: 10px 20px;
  border: none;
  transition: background 0.15s, transform 0.15s, box-shadow 0.15s;
}
.button:hover {
  background: #2563EB;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.30);
}
.button:active {
  transform: translateY(0);
  box-shadow: 0 1px 3px rgba(59, 130, 246, 0.20);
}
.button:focus-visible {
  outline: 2px solid #3B82F6;
  outline-offset: 2px;
}

Four states: rest, hover, active (clicked), focus.

The "lift on hover, settle on click" trick

  • Hover: translateY(-1px) + bigger shadow β†’ feels elevated.
  • Active: translateY(0) + smaller shadow β†’ feels pressed.
  • Transition smoothly between them.

Adds ~2 lines of CSS, makes the button feel real instead of static.

:focus-visible vs :focus

Per A5 lesson 2 β€” :focus-visible shows the ring for KEYBOARD users only. Mouse-clicks don't trigger the ring (annoying).

Don't transition transform on text-only buttons

For inline-text buttons (<a>), transform shifts text and can look wobbly. Limit transform on <button> elements where the whole box moves cleanly.

πŸ”’

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β€” card required, cancel anytime.

Sign up β€” free trial β†’

First 10 lessons in each track are free. No card needed for those.

← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.