| name | html-purist |
| description | Enforce strict separation of HTML (structure/data) and CSS (visual design) when writing or reviewing web markup. Use this skill when generating HTML, CSS, or JavaScript for any web page, component, or template — even if not explicitly asked for semantic markup. Covers zero inline styles, semantic-only elements, CSS custom properties, CSS-first animations, minimal JavaScript, Datastar/htmx hypermedia over SPAs, SSR + SSE, and JSON-LD for SEO/AI agents.
|
| metadata | {"author":"chrisabruce","version":"1.0.0","category":"web-development"} |
| license | MIT |
HTML Purist
You are an expert in building fast, semantic, server-rendered web applications with strict separation of concerns. Follow these rules absolutely when generating or reviewing HTML, CSS, and JavaScript.
Core Philosophy
HTML is a data document. CSS is visual design. JavaScript is a last resort.
Every page you produce should be fully readable, navigable, and meaningful with CSS and JS completely disabled. The HTML alone must communicate the content hierarchy, relationships, and meaning.
HTML Rules
Absolute Prohibitions
- NEVER use
style attributes (inline styles) — zero exceptions
- NEVER use presentational elements:
<b>, <i>, <u>, <center>, <font>, <br> for spacing, <hr> for decoration
- NEVER use
<div> or <span> when a semantic element exists (<nav>, <article>, <section>, <aside>, <header>, <footer>, <main>, <figure>, <figcaption>, <details>, <summary>, <time>, <address>, <mark>, <dl>, <dt>, <dd>)
- NEVER use tables for layout — only for actual tabular data
- NEVER add JavaScript event handlers inline (
onclick, onsubmit, etc.)
- NEVER use
<img> without meaningful alt text (or alt="" for purely decorative images handled via CSS)
Required Practices
- Use semantic HTML5 landmarks:
<header>, <nav>, <main>, <article>, <section>, <aside>, <footer>
- Heading hierarchy must be logical (
h1 > h2 > h3) — never skip levels, never choose heading level for visual size
- Classes and IDs must represent data meaning and content hierarchy, not visual appearance
- GOOD:
class="job-listing", class="profile-skills", class="production-credits"
- BAD:
class="big-text", class="red-box", class="left-column", class="mt-4 px-2"
- Use
<strong> for importance, <em> for emphasis (semantic meaning, not visual styling)
- Forms must have proper
<label> elements associated via for/id, grouped with <fieldset> and <legend>
- Use
<ol>, <ul>, <dl> for actual lists and definitions
- Use
<time datetime=""> for dates and times
- Use
<address> for contact information
- Include structured data (JSON-LD schema.org) for SEO and AI agent discoverability
- Include proper
<meta> tags: description, Open Graph, canonical URLs
- Use
lang attribute on <html>
SEO and AI Agent Friendliness
- Every page must have exactly one
<h1> representing the primary topic
- Use descriptive, hierarchical heading structure that an AI could parse to understand page content
- Include JSON-LD structured data (
@type from schema.org) embedded in <script type="application/ld+json">
- Semantic markup should make content extractable without rendering — an AI agent or scraper reading raw HTML should understand the data relationships
- Use
<link rel="canonical">, proper <title>, and <meta name="description">
- Prefer descriptive URLs that mirror content hierarchy
CSS Rules
Architecture
Animations and Transitions
- ALL animations and transitions must be in CSS, not JavaScript
- Use
@keyframes, transition, and animation properties
- Use CSS
transform and opacity for performant animations (GPU-composited)
- Respect
prefers-reduced-motion media query — always provide reduced/no-motion alternatives
- Use
transition for state changes (hover, focus, active, open/closed)
- Use
@keyframes for complex multi-step animations
- Loading states, skeleton screens, and micro-interactions should all be CSS
Layout and Responsiveness
- Use CSS Grid and Flexbox for all layout — never floats, never tables
- Mobile-first responsive design using
min-width media queries
- Use
clamp(), min(), max() for fluid typography and spacing
- Use container queries (
@container) where supported for component-level responsiveness
- Prefer relative units (
rem, em, %, vw, vh, dvh) over fixed px
Prohibited CSS Patterns
- No utility-class frameworks (Tailwind, etc.) — write semantic CSS
- No CSS-in-JS — styles belong in
.css files
- Minimize
!important — if you need it, the selector architecture is wrong
- No vendor prefixes manually — use build tools if needed
JavaScript Rules
Minimize JavaScript
- JavaScript is the last resort, not the first tool
- If it can be done with HTML + CSS, do it with HTML + CSS:
- Dropdowns/accordions: use
<details>/<summary>
- Modals: use
<dialog> with ::backdrop
- Tooltips: use CSS
:hover/:focus-within + [data-tooltip]
- Tab panels: use CSS
:target or radio-button hack where viable
- Form validation: use HTML5 constraint validation (
required, pattern, min, max, type)
- Scroll animations: use
@keyframes with animation-timeline: scroll()
- Smooth scroll: use
scroll-behavior: smooth in CSS
- Carousels: use CSS scroll-snap
When JavaScript IS Needed — Use Hypermedia
- Prefer Datastar (or htmx-like declarative hypermedia) over custom JavaScript
- Use
data-* attributes for declarative behavior, not imperative JS
- Server-Sent Events (SSE) for real-time updates — not WebSockets unless bidirectional is truly required
- Server-side rendering (SSR) is the default — the server sends HTML fragments, not JSON
- Pattern: user action -> HTTP request -> server renders HTML fragment -> swap into DOM
- No client-side routing — let the server own the URL and render the page
- No SPA frameworks (React, Vue, Angular, Svelte) unless there is an extraordinary reason
Interactivity Architecture (Datastar/Hypermedia Style)
<div data-on-click="$$get('/api/profile/123')" data-target="#profile-detail">
View Profile
</div>
<div id="profile-detail" data-on-load="$$get('/api/profile/recent')">
</div>
- All interactivity is server-driven: the server decides what HTML to return
- Use SSE (
EventSource) for live updates (notifications, feeds, real-time data)
- Progressive enhancement: the page works without JS, Datastar/htmx enhances it
Performance Requirements
- First Contentful Paint must be fast — no JS-blocking render
- Critical CSS inlined in
<head> if needed, rest loaded async
- Images: use
<picture> with srcset, loading="lazy", proper width/height to prevent layout shift
- Fonts:
font-display: swap, preload critical fonts
- Minimal DOM depth — semantic elements naturally flatten the tree vs. div soup
Code Review Checklist
When reviewing HTML/CSS/JS, flag these violations: