CSS — Buttons
The reset every button needs
Browser defaults fight your design. Start clean:
.btn {
display: inline-flex; /* centers icon + label */
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 20px;
border: none;
border-radius: 6px;
background: #0d9488;
color: white;
font: inherit; /* buttons don't inherit by default! */
font-weight: 600;
cursor: pointer;
transition: background 0.2s ease, transform 0.1s ease;
}
.btn:hover { background: #0f766e; }
.btn:active { transform: scale(0.97); } /* tactile press */
.btn:focus-visible {
outline: 3px solid rgba(13,148,136,.4);
outline-offset: 2px;
}
display: inline-flex + gap handles icon alignment forever.
Variants via modifier classes
.btn-secondary { background: white; color: #0f766e;
border: 1px solid currentColor; }
.btn-danger { background: #dc2626; }
.btn-ghost { background: transparent; color: inherit; }
.btn-ghost:hover { background: rgba(0,0,0,.06); }
<button class="btn">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-danger">Delete</button>
One base, unlimited personalities — the composition pattern from the classes lesson.
Sizes
.btn-sm { padding: 6px 12px; font-size: .875rem; }
.btn-lg { padding: 14px 28px; font-size: 1.125rem; }
Padding drives size — no fixed heights, so text changes never break layout.
Disabled state
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
submitBtn.disabled = true; // during form submission
// …await save()
submitBtn.disabled = false;
Disabled buttons stay focusable-by-screen-reader debate aside — also announce why when possible (aria-disabled + helper text).
Loading button pattern
.btn.loading {
pointer-events: none;
opacity: 0.7;
}
.btn.loading::after {
content: "";
width: 14px; height: 14px;
border: 2px solid currentColor;
border-top-color: transparent;
border-radius: 50%;
animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
btn.classList.add("loading");
await save();
btn.classList.remove("loading");
(Spinner appears inside the button; clicks blocked while pending.)
Icon-only buttons need labels
.icon-btn {
width: 40px; height: 40px;
padding: 0;
border-radius: 50%;
}
<button class="icon-btn" aria-label="Search settings">
<svg …></svg>
</button>
No visible text = mandatory aria-label.
Checklist: real
<button>elements (not divs/links-that-act) ·font: inherit· hover+active+focus-visible states · disabled feedback · min touch target 44×44px on mobile.
Mini Practice
- Base
.btn+ three variants from scratch. - Three sizes driven purely by padding.
- Wire a loading state around a fake async save.
- Icon-only circular button with aria-label.
- Full keyboard pass: tab, space, enter all work.
- Ghost variant that adapts to dark backgrounds.
Next: navigation bars →
Related Topics
Frequently Asked Questions about Buttons
What is Buttons in CSS?
Buttons is a fundamental concept in CSS. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Buttons?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Buttons.
Why is Buttons important in CSS?
Buttons is essential for CSS development. Understanding this concept will help you write better code and solve real-world problems more effectively.