Design systems as HTML contracts: the shared structure, element choices, and attribute conventions that outlive any CSS theme. Tokens and visual polish live in CSS; HTML defines what a ‘card’, ‘alert’, or ‘page shell’ means across products and teams.
Structure before skin
A design system page is not a Figma export – it is agreed markup patterns. Example: every alert is a container with role, variant attribute or class hook, title slot, and body slot. CSS can change colours each year; the HTML contract stays stable so CMS templates, docs, and JavaScript hooks do not break.
Naming and BEM-style hooks
<div class="ds-alert ds-alert--error" role="alert">
<p class="ds-alert__title">Payment failed</p>
<p class="ds-alert__body">Check your card details and try again.</p>
</div>
Prefix classes (ds- for design system) avoid collisions with legacy site CSS. Document required vs optional nodes. If JavaScript targets .ds-alert__dismiss, that class is part of the public contract – treat renames as breaking changes.
Custom elements in systems
Many systems ship <ds-button>, <ds-modal>, or similar. The HTML contract includes attributes (variant, disabled), slots, and events (ds-close). Document them like a small API reference. Autonomous custom elements plus declarative shadow templates give you encapsulation without React.
<ds-button variant="primary" type="submit">Save changes</ds-button>
Page templates as contracts
Define shell templates every product page uses:
<body class="ds-page">
<a class="ds-skip-link" href="#main">Skip to content</a>
<header class="ds-header">...</header>
<main id="main" class="ds-main">
<!-- page-specific content -->
</main>
<footer class="ds-footer">...</footer>
</body>
Landmarks, skip link, and main id are non-negotiable for accessibility. Marketing may add sections; they should not remove the shell. Version the template in your docs when it changes.
Documentation that developers use
- Copy-paste HTML examples that validate
- Do / don’t pairs (correct label association vs div click handlers)
- Accessibility notes per component (keyboard, required ARIA)
- Changelog when markup changes
Tokens vs markup
CSS custom properties hold colour, spacing, and type scales. HTML carries semantic intent: <button type="submit"> not <a class="button-primary"> for form submit. Do not encode design tokens as endless data attributes on every div – use classes or host-level variables on components. Keep HTML readable in ‘view source’ audits.
Governance
Someone owns approvals for new patterns. Ad-hoc one-off markup in a single product becomes debt when it should have been a system component. The HTML contract is the agreement between design, front-end, and CMS authors – enforce it in code review and lint rules where you can.

