Module 27 : Button Sizes, Colors & States — Bootstrap (Deep Dive)
design, implement, customize, and test buttons in Bootstrap-based interfaces. built-in Bootstrap button system (sizes, color variants, outline vs solid, link buttons), button states (hover, focus, active, disabled, loading), accessibility considerations, customizing with CSS/SASS variables, and techniques for production-ready components.
Basic HTML/CSS and familiarity with Bootstrap 4/5 (this uses Bootstrap 5 conventions).
Basic JavaScript knowledge (for interactive states).
An editor and local dev server or CodePen/JSFiddle for quick.
1 — Button anatomy & Bootstrap basics
Bootstrap's base button markup:
<button type="button" class="btn btn-primary">Primary</button>
Core parts:
.btn — base reset and shared styles (padding, border, font).
Color variant classes: .btn-primary, .btn-secondary, .btn-success, .btn-danger, .btn-warning, .btn-info, .btn-light, .btn-dark, .btn-link.
Outline variants: .btn-outline-primary (border + transparent background).
Size modifiers: .btn-lg (large), .btn-sm (small). For full-width: .w-100 or d-grid with gap-2 for Bootstrap 5.
Additional helpers: .disabled (anchor/button appearance), disabled attribute for <button>.
Example: different types and sizes
<button class="btn btn-primary btn-lg">Large Primary</button>
<button class="btn btn-secondary">Default</button>
<button class="btn btn-success btn-sm">Small Success</button>
<button class="btn btn-outline-danger">Outline Danger</button>
<a class="btn btn-link" href="#">Link-style</a>
2 — Button states (visual + semantic)
Common states:
Normal (default)
Hover — CSS :hover (user agent / Bootstrap provides hover styles)
Focus — CSS :focus and :focus-visible; Bootstrap draws focus rings for keyboard users.
Active — pressed state (:active) and also .active class for toggling.
Disabled — disabled attribute for <button>; .disabled class for anchors or other elements.
Loading — transient state while background work occurs (not built into Bootstrap; implemented via JS + spinner).
Example: disabled
<button class="btn btn-primary" disabled>Disabled</button>
<a class="btn btn-secondary disabled" href="#" tabindex="-1" aria-disabled="true">Disabled Link</a>
Accessibility notes (semantic states)
Use disabled on <button> elements (automatically ignored by assistive tech; keyboard focus removed).
For anchors used as buttons, add aria-disabled="true" and tabindex="-1" + .disabled styling to prevent focus/interaction.
For toggle buttons (on/off), use aria-pressed="true|false" to expose state.
For spinners/loading states, add aria-live="polite" and update text so screen readers announce progress (or set aria-busy="true" on a container).
3 — Building a loading button pattern
A small, reusable pattern: swap label with spinner, disable the button while loading, restore after finishing.
HTML:
<button id="saveBtn" class="btn btn-primary">
<span class="btn-label">Save</span>
<span class="btn-spinner visually-hidden" role="status" aria-hidden="true">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</span>
</button>
CSS (optional helpers):
.btn-spinner { display: inline-flex; gap: .5rem; align-items: center; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.hidden { display: none !important; }
JavaScript:
const btn = document.getElementById('saveBtn');
function setLoading(button, isLoading) {
const label = button.querySelector('.btn-label');
const spinner = button.querySelector('.btn-spinner');
if (isLoading) {
label.classList.add('visually-hidden');
spinner.classList.remove('visually-hidden');
button.setAttribute('disabled', 'true');
button.setAttribute('aria-busy', 'true');
} else {
label.classList.remove('visually-hidden');
spinner.classList.add('visually-hidden');
button.removeAttribute('disabled');
button.removeAttribute('aria-busy');
}
}
// Example usage:
btn.addEventListener('click', async () => {
setLoading(btn, true);
try {
await fakeApiCall(); // replace with real async action
} finally {
setLoading(btn, false);
}
});
4 — Custom sizes, spacing & responsive buttons
Bootstrap Sass variables that affect buttons (examples — names vary by Bootstrap version):
$btn-padding-y, $btn-padding-x — adjust inner padding.
$btn-font-weight, $btn-border-radius, $btn-font-size.
$btn-lg-padding-y, $btn-sm-padding-y, etc.
Override example using Sass (custom _custom.scss loaded after Bootstrap variables but before Bootstrap components):
$btn-padding-y: 0.55rem;
$btn-padding-x: 1.1rem;
$btn-border-radius: .5rem;
@import "bootstrap"; // or ensure variables override before compilation
Custom CSS for a new size variant:
.btn-xl {
padding: 0.9rem 1.6rem;
font-size: 1.125rem;
border-radius: .6rem;
}
Responsive sizing example
<!-- large on desktop, small on mobile -->
<button class="btn btn-primary btn-lg d-none d-md-inline-block">Desktop Large</button>
<button class="btn btn-primary btn-sm d-inline-block d-md-none">Mobile Small</button>
5 — Visual design: colors, contrast, outlines
Use .btn-outline-* when a lighter, less dominant action is needed. Outline buttons rely on border + text color; ensure contrast on all backgrounds.
For brand colors, create a custom variant using Sass maps in Bootstrap or add a class:
$btn-variant-colors: (
"brand": #1e88e5
);
Or simple CSS:
.btn-brand {
background-color: #1e88e5;
color: #fff;
border-color: #1e88e5;
}
.btn-brand:hover { background-color: #166bb0; border-color: #166bb0; }
Ensure hover and focus states maintain contrast.
6 — Toggle buttons & button groups
Bootstrap supports toggleable buttons and button groups:
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-outline-primary">Left</button>
<button type="button" class="btn btn-outline-primary">Middle</button>
<button type="button" class="btn btn-outline-primary">Right</button>
</div>
For toggleable single buttons:
<button class="btn btn-primary" data-bs-toggle="button" aria-pressed="false" autocomplete="off">Toggle</button>
When using custom JS toggles, update aria-pressed.
7 — Micro-interactions & animation
Keep micro-interactions subtle and fast (50–200ms) for hover/focus transitions.
Use CSS transitions for background-color, transform (scale), box-shadow.
Example:
.btn {
transition: background-color .12s ease, transform .08s ease;
}
.btn:active { transform: translateY(1px) scale(.995); }
Avoid layout-affecting transitions (like width) without care.
8 — Testing & checklist
Visual tests:
Buttons across variants, sizes, outlines, disabled states, and responsive breakpoints.
Contrast: text vs background meet WCAG (4.5:1 for normal text; 3.0:1 for large text).
Hover/focus styles visible (keyboard-only users must see focus ring).
Functional tests:
Disabled buttons cannot be activated by keyboard or mouse.
Loading state prevents multiple submissions.
Toggle buttons correctly update aria-pressed.
Accessibility tests:
Use screen reader to verify announcements for loading and state changes.
Keyboard-only navigation works: Tab focuses buttons; Enter/Space activated.
9 — Performance & bundling tips
Keep button components small; avoid embedding large assets inside buttons.
Use SVG icons (inline or symbol sprite) for crisp icons without extra network requests.
Defer heavy JS that’s not needed for initial interaction.
Summary
A set of button components (HTML/CSS/JS) covering variants, sizes, disabled/loading states, accessible patterns, and a small style for teams.
A test checklist and responsive
No comments:
Post a Comment