Universal web design implementation methodology — BEM, responsive, accessibility, CSS architecture, spacing systems, dark mode. The HOW of building production-grade HTML/CSS.
Universal patterns for building production-grade HTML/CSS. This skill covers implementation methodology — pair with web-design-patterns for specific component designs.
Production-ready HTML/CSS prototypes with:
prototype/
├── index.html
├── about.html
├── services.html
├── contact.html
├── favicon.svg
├── css/
│ ├── variables.css # Tokens: colours, typography, spacing
│ ├── styles.css # All component styles (BEM)
│ └── mobile-nav.css # Mobile menu styles
├── js/
│ ├── theme.js # Dark mode toggle (only if requested)
│ └── mobile-menu.js # Hamburger menu
└── media/
└── images/
Build order:
variables.css — tokens firstfavicon.svg — simple SVG from brand colourstyles.css — all BEM componentsmobile-nav.css — responsive navigationassets/ templatesindex.html — homepage firstUse Block-Element-Modifier naming. No exceptions.
/* Block */
.hero {
}
.card {
}
.nav {
}
/* Element (child of block) */
.hero__title {
}
.hero__subtitle {
}
.hero__cta {
}
.card__image {
}
.card__content {
}
/* Modifier (variation) */
.hero--split {
}
.hero--minimal {
}
.card--featured {
}
.btn--primary {
}
.btn--lg {
}
Rules:
__--.hero__content__title is wrong.card__image only inside .cardUse semantic tokens. Never hardcode colours, spacing, or typography values.
See references/css-variables-template.md for the complete token template.
/* Always this */
.card {
background: var(--card);
color: var(--card-foreground);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow-sm);
padding: var(--space-6);
}
/* Never this */
.card {
background: #ffffff;
color: #333333;
border: 1px solid #e5e5e5;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
padding: 24px;
}
Dark mode is optional — only add if the brief requests it. Most business sites ship faster as light-only.
When to include:
When to skip:
Use class-based toggle, never CSS media queries.
/* Light mode (default) */
:root {
--background: #f9fafb;
--foreground: #0f172a;
--card: #ffffff;
--card-foreground: #1e293b;
}
/* Dark mode (via .dark class on html) */
.dark {
--background: #0f172a;
--foreground: #f1f5f9;
--card: #1e293b;
--card-foreground: #f1f5f9;
}
Rules:
.dark class on <html>, toggled via JavaScript@media (prefers-color-scheme: dark) — JS handles system preference#0F172A to #1E293B range (not pure black)Use assets/theme-toggle.js for the three-state toggle implementation.
Mobile-first. Design for 375px, enhance upward.
/* Base: 375px (mobile) — no media query needed */
@media (min-width: 640px) {
/* sm — large phone */
}
@media (min-width: 768px) {
/* md — tablet */
}
@media (min-width: 1024px) {
/* lg — small desktop */
}
@media (min-width: 1440px) {
/* xl — standard desktop */
}
.prose {
max-width: 65ch;
}
.hero__content {
max-width: min(640px, 45vw);
}
.container {
max-width: 1280px;
margin-inline: auto;
padding-inline: var(--space-4);
}
.section {
padding: clamp(3rem, 6vw, 6rem) 0;
}
Use assets/mobile-nav.js for the hamburger menu implementation.
clamp(2.5rem, 6vw, 5rem) for hero titles.letter-spacing: 0.05em minimum.The 80/20 rule:
If primary is on every heading, border, icon — nothing stands out.
Not uniform padding. Sections breathe differently:
/* Tight section (service list, FAQ) */
.section--compact {
padding: clamp(2rem, 4vw, 4rem) 0;
}
/* Standard section */
.section {
padding: clamp(3rem, 6vw, 6rem) 0;
}
/* Breathing room (editorial break, testimonial) */
.section--spacious {
padding: clamp(4rem, 8vw, 10rem) 0;
}
| Element | Shadow |
|---|---|
| Cards at rest | --shadow-sm |
| Cards on hover | --shadow-md |
| Dropdowns | --shadow-lg |
| Modals | --shadow-xl |
Not everything needs shadow. Use sparingly.
Use Lucide icons via inline SVG:
currentColor (inherits text colour)Non-negotiable:
<header>, <nav>, <main>, <section>, <footer>aria-expanded on toggles, aria-label where neededloading="lazy" on images below the foldloading="eager" on hero image<link rel="preconnect" href="https://fonts.googleapis.com"> in headThese patterns signal "AI generated this" — avoid:
Before marking complete: