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