# Front End Best Practices

> Applies framework-agnostic web UI guidelines for layout, spacing, modals, accessibility, loading states, and motion. Use when writing or reviewing HTML/CSS/JS front ends, design systems, component libraries, or UI in any framework (React, Vue, Svelte, Angular, Lit, etc.).

- Skill: `ckulwik/front-end-best-practices` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ckulwik/front-end-best-practices`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ckulwik/front-end-best-practices/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: ckulwik (https://skillmd.com/u/ckulwik)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ckulwik/front-end-best-practices

---


# Front end best practices (framework-agnostic)

Apply these when implementing or reviewing user interfaces. Map concepts to the project's stack (utility CSS, design tokens, component primitives).

## Layout and spacing

- Prefer **design-system spacing** (scale/tokens) or **utility classes** over arbitrary pixel values when equivalents exist.
- **Flexbox** for alignment and distribution: wrap, center on both axes, consistent gaps (`gap` in CSS; many stacks expose `gap-*` utilities).
- **Consistent rhythm**: outer containers slightly looser padding than nested sections; dense regions (toolbars, tags) tighter.
- **Grouped actions**: horizontal button groups use uniform spacing (e.g. one gap token) instead of mixed margins.

## Actions and buttons

- **Primary action on the right** in left-to-right locales (Save, Submit, Continue); secondary actions (Cancel, Back) to the left.
- **Destructive actions** (Delete, Remove): use a **secondary / outline / ghost** treatment, not the same prominence as primary. Place them left of the primary when both appear in one row.
- **Loading / disabled**: disable or show in-button progress while the primary action runs; avoid double submission.

## Modal vs persistent panel

- **Modal (dialog)**: short, blocking flow — confirm/cancel, errors, small single-purpose forms. User must resolve or dismiss; focus is trapped while open.
- **Panel / sheet / drawer**: longer or multi-step work on a **selected item** while list or parent context stays visible. Often slides from an edge; dismissible with close control and Escape where appropriate.

Choose modal for "must decide now"; choose panel when **context preservation** matters.

## Accessibility

- **Contrast**: target WCAG AA — roughly **4.5:1** for normal text, **3:1** for large text (about 18pt+ or 14pt+ bold). Verify with a contrast checker.
- **Keyboard**: every control reachable with Tab / Shift+Tab; visible focus styles; logical tab order (avoid positive `tabindex` except rare cases).
- **Semantics**: use native interactive elements (`button`, `a` with `href`, `input`, `select`) or components that expose the same roles and keyboard behavior. Avoid clickable `div`/`span` unless they have explicit role, `tabindex`, and key handlers.
- **Icon-only controls**: provide an accessible name (`aria-label` or visually hidden text); pair with tooltips only as enhancement, not as the sole label.
- **Live regions**: use `aria-live` (polite/assertive) for async status ("Saving…", "Saved", errors) when content updates without moving focus.

## Loading, empty, and error states

1. **Reserve space** — skeletons, min-height containers, or stable layout so content swap does not shift the page jarringly.
2. **Minimum loader visibility** — very fast responses can flash spinners; optional short minimum display (e.g. ~300–400ms) if the product cares about perceived stability (use sparingly; do not delay real feedback).
3. **Motion** — prefer short opacity/transform transitions for enter/leave; respect **`prefers-reduced-motion`**: reduce or disable non-essential animation.

## Forms and validation

- Associate **labels** with controls (`for`/`id` or wrapping label); surface errors **inline** near fields and summarize at the top for long forms.
- Do not rely on **color alone** for errors; use text and icons.
- **Autofocus** sparingly (e.g. single-field search or modal primary field); avoid trapping users unexpectedly.

## Performance and resilience

- **Images**: appropriate formats, dimensions, and `loading="lazy"` for below-the-fold content where supported.
- **Lists**: virtualize or paginate large collections; avoid rendering thousands of DOM nodes at once.
- **Network**: optimistic UI only when rollback is clear; show failure states and retries for critical actions.

## Quick checklist

- [ ] Primary action right; cancel/secondary left; destructive de-emphasized.
- [ ] Spacing and layout use tokens/utilities; gaps consistent in toolbars and button rows.
- [ ] Modal vs panel choice matches task length and need for surrounding context.
- [ ] Focus order, labels, contrast, and icon-only names covered.
- [ ] Loading and empty states avoid layout jump; motion respects reduced-motion.
- [ ] Forms: labels, errors, no color-only status.

## References

- [WCAG 2.2 Understanding](https://www.w3.org/WAI/WCAG22/Understanding/)
- [Colour Contrast Analyzer (macOS)](https://github.com/ThePacielloGroup/CCA-OSX/releases/tag/2.4) | [Windows](https://github.com/ThePacielloGroup/CCA-Win/releases/tag/2.5.0)

