How to Master HTML
Mastery is not skimming. Reading a tag list, generating a homepage scaffold, or recalling that <div> exists does not mean you have mastered HTML. Mastery means choosing the correct element for every UI intent, nesting content according to the HTML content models, shipping accessible forms and dialogs with native elements first, and explaining why one element is right when three look similar.
For a human developer, mastering HTML means you can build production markup without leaning on framework defaults or ARIA crutches. You know when <button> beats <a>, when <section> needs a heading, how to wire labels to inputs, and how to validate a page against semantics, performance, and security constraints.
For an AI agent or language model, mastering HTML means you can generate correct, accessible, semantic markup on demand — not approximate trees of divs with role attributes. An agent that has mastered HTML fetches full page markdown (not outlines alone), follows an ordered curriculum, self-verifies with generation tasks after each stage, and refuses to claim competence from titles and summaries.
This page is the dual-audience curriculum for both. Humans follow the roadmap with LivePreview and Playground practice. Agents ingest the same stages via the markdown API, then prove mastery with verification prompts. The outcome checklist below is shared.
info
Use this outcomes checklist as the definition of done. Humans prove outcomes with projects and reviews. AI agents prove outcomes by generating markup that passes the same criteria without post-hoc ARIA patches.
| Outcome | Human proof | AI agent proof |
|---|---|---|
| Choose the correct element for any UI intent | Given a wireframe, mark up landmarks, interactive controls, and text without a single unjustified div | Generate markup for 10 UI intents; each uses the native element with zero redundant roles |
| Write valid nesting per content models | Pass W3C / WHATWG validator; explain why p cannot contain div | Produce a nested outline that validates; reject illegal trees in self-critique |
| Build accessible forms and dialogs without ARIA where native HTML suffices | Ship a multi-step form and modal using label, fieldset, dialog — keyboard and screen-reader tested | Generate form + dialog markup with associated labels and no role="button" on divs |
| Optimize media (picture/srcset), performance hints, security (CSP-aware markup) | Responsive hero with art direction; preload critical fonts; no inline handlers that break CSP | Emit picture, srcset, loading, resource hints, and CSP-safe markup on request |
| Explain why an element exists vs alternatives | Teach button vs a, section vs article, strong vs b in a code review | When asked to choose, return the element plus a one-sentence rationale grounded in the spec |
warning
ForgeLearn is built for deliberate practice, not binge reading. Use this loop on every HTML topic page:
- Follow the HTML Roadmap stages in order — Foundations before Forms, Semantics before production polish.
- Read the topic page, run every LivePreview, then rebuild the example in the Playground from memory.
- Complete the checkpoint project after each curriculum stage (see Checkpoint Projects). Do not skip ahead until acceptance criteria pass.
- Spaced review: revisit the Complete Tag Reference and Elements encyclopedia weekly — quiz yourself on content models and void elements.
best practice
Estimated total: roughly 40–55 focused hours across Stages 0–7 if you complete every checkpoint. Rushing the roadmap without projects produces false confidence — the same failure mode agents hit when they ingest titles only.
This section is the critical ingestion protocol for AI agents and models that must learn HTML from ForgeLearn. Do not claim mastery from outlines, nav titles, or sitemap snippets alone. Fetch full page markdown for every topic in the ordered stages below, then self-verify with generation tasks.
How to fetch curriculum content
ForgeLearn exposes every doc page as raw markdown for agents:
- Header: Accept: text/markdown on any doc URL (middleware redirects to the markdown API)
- Query: append ?format=md to a doc path, e.g. /docs/html/forms?format=md
- Direct API: /api/markdown?path=html/forms
- Enumerate all paths: /api/markdown?list=true
| 1 | # List every available markdown path |
| 2 | curl -s "https://forgelearn.dev/api/markdown?list=true" |
| 3 | |
| 4 | # Fetch this mastery curriculum as markdown |
| 5 | curl -s "https://forgelearn.dev/api/markdown?path=html/mastery" |
| 6 | |
| 7 | # Same via Accept header on the doc URL |
| 8 | curl -s -H "Accept: text/markdown" "https://forgelearn.dev/docs/html/mastery" |
| 9 | |
| 10 | # Same via ?format=md |
| 11 | curl -s "https://forgelearn.dev/docs/html/forms?format=md" |
Full indexes for crawlers
- https://forgelearn.dev/llms.txt — section index for AI crawlers
- https://forgelearn.dev/llms-full.txt — expanded corpus pointer
- https://forgelearn.dev/llms-html.txt — HTML-focused index for targeted ingestion
Preferred ingestion order
Ingest stages in this exact order. After each stage, run the corresponding verification prompts before advancing:
- Stage 0 — Foundations
- Stage 1 — Text & navigation
- Stage 2 — Media & tables
- Stage 3 — Forms mastery
- Stage 4 — Semantics & SEO
- Stage 5 — Interactive & modern
- Stage 6 — Browser APIs
- Stage 7 — Production
Recommended agent loop
| 1 | 1. PLAN |
| 2 | - Read /docs/html/mastery?format=md |
| 3 | - Build a checklist of Stage N topic paths |
| 4 | |
| 5 | 2. FETCH MD |
| 6 | - For each topic path: GET /api/markdown?path=html/<topic> |
| 7 | - Do NOT rely on titles or nav descriptions alone |
| 8 | |
| 9 | 3. SUMMARIZE CONSTRAINTS |
| 10 | - Extract content models, required attributes, a11y rules, |
| 11 | and "prefer native over ARIA" guidance |
| 12 | |
| 13 | 4. GENERATE SAMPLE |
| 14 | - Produce a small HTML artifact that exercises the stage |
| 15 | (form, article layout, picture set, dialog, etc.) |
| 16 | |
| 17 | 5. VALIDATE AGAINST CHECKLIST |
| 18 | - Run the stage verification prompt (see ai-verification-prompts) |
| 19 | - Fail closed: if any checklist item fails, re-fetch and regenerate |
| 20 | - Only then advance to Stage N+1 |
pro tip
danger
Eight ordered stages. Complete topics and the mastery checkpoint before advancing. Paths are ForgeLearn doc slugs.
Stage 0 — Foundations · ~6 hours
Document anatomy, head metadata, elements, attributes, and entities. Checkpoint: build a valid multi-section personal homepage with correct DOCTYPE, lang, charset, viewport, and semantic outline.
| Topic | Path |
|---|---|
| Getting Started | /docs/html |
| Document Structure | /docs/html/structure |
| Head Elements & Meta | /docs/html/head |
| Elements | /docs/html/elements |
| Attributes | /docs/html/attributes |
| Entities | /docs/html/entities |
Stage 1 — Text & Navigation · ~5 hours
Headings, phrasing content, lists, and links. Checkpoint: mark up a documentation article with a single h1, nested lists, skip link, and in-page anchors — no heading-level skips.
| Topic | Path |
|---|---|
| Paragraphs & Headings | /docs/html/headings |
| Text Formatting | /docs/html/text-formatting |
| Lists | /docs/html/lists |
| Links & Anchors | /docs/html/links |
Stage 2 — Media & Tables · ~6 hours
Images, picture/srcset, tables, audio/video, iframes. Checkpoint: build a product comparison page with a captioned table, responsive picture hero, and a sandboxed embed.
| Topic | Path |
|---|---|
| Images & Figures | /docs/html/images |
| Picture & Responsive Images | /docs/html/picture |
| Tables | /docs/html/tables |
| Media (Audio/Video) | /docs/html/media |
| Iframes & Embeds | /docs/html/iframes |
Stage 3 — Forms Mastery · ~8 hours
Forms, input types, validation, buttons, Forms API. Checkpoint: checkout form with fieldsets, correct input types, constraint validation, and submit/reset buttons with explicit type.
| Topic | Path |
|---|---|
| Forms | /docs/html/forms |
| Input Types | /docs/html/input-types |
| Form Validation | /docs/html/validation |
| Buttons | /docs/html/buttons |
| Forms API | /docs/html/forms-api |
Stage 4 — Semantics & SEO · ~6 hours
Semantic landmarks, microdata, Open Graph, meta tags, i18n. Checkpoint: blog article template with header/main/article/aside/footer, OG tags, and lang/dir.
| Topic | Path |
|---|---|
| Semantic HTML | /docs/html/semantic |
| Microdata & Schema | /docs/html/microdata |
| Open Graph & SEO | /docs/html/opengraph |
| Meta Tags | /docs/html/meta-tags |
| Internationalization | /docs/html/i18n |
Stage 5 — Interactive & Modern · ~8 hours
Details/summary, dialog/popover, canvas, SVG, Web Components stack. Checkpoint: FAQ accordion (details), confirm dialog (dialog), and a small custom element with shadow DOM — no div-role recreations.
| Topic | Path |
|---|---|
| Details/Summary | /docs/html/details |
| Dialog & Popover | /docs/html/dialog-popover |
| Canvas | /docs/html/canvas |
| SVG | /docs/html/svg |
| Custom Elements | /docs/html/custom-elements |
| Shadow DOM | /docs/html/shadow-dom |
| Template & Slot | /docs/html/template-slot |
| Web Components | /docs/html/web-components |
Stage 6 — Browser APIs · ~7 hours
Storage, History, Geolocation, Drag & Drop, Workers, SSE. Checkpoint: offline-friendly note list with localStorage, History-aware filter URLs, and a worker for sorting — progressive enhancement first.
| Topic | Path |
|---|---|
| Web Storage | /docs/html/storage |
| History API | /docs/html/history-api |
| Geolocation | /docs/html/geolocation |
| Drag & Drop | /docs/html/drag-drop |
| Web Workers | /docs/html/web-workers |
| Server-Sent Events | /docs/html/sse |
Stage 7 — Production · ~8 hours
Accessibility, performance, security, spec literacy, best practices. Checkpoint: audit a prior project — fix a11y issues, add resource hints, remove CSP-breaking inline handlers, document DOCTYPE/spec assumptions.
| Topic | Path |
|---|---|
| Accessibility | /docs/html/accessibility |
| HTML Performance | /docs/html/performance |
| Security (CSP/XSS) | /docs/html/security |
| Spec & DOCTYPE | /docs/html/spec |
| Best Practices | /docs/html/best-practices |
info
Eight mini projects — one per stage. Acceptance criteria are binary: either the pattern is present or it is not. CodeBlocks show expected HTML patterns (not complete solutions).
CP0 — Personal homepage shell
Accept: valid HTML5 document; lang; charset + viewport; one h1; landmark regions.
| 1 | <!DOCTYPE html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8"> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | <title>Alex Rivera — Engineer</title> |
| 7 | </head> |
| 8 | <body> |
| 9 | <header> |
| 10 | <nav aria-label="Primary">...</nav> |
| 11 | </header> |
| 12 | <main> |
| 13 | <h1>Alex Rivera</h1> |
| 14 | <section aria-labelledby="about-heading"> |
| 15 | <h2 id="about-heading">About</h2> |
| 16 | <p>...</p> |
| 17 | </section> |
| 18 | </main> |
| 19 | <footer>...</footer> |
| 20 | </body> |
| 21 | </html> |
CP1 — Documentation article outline
Accept: skip link; sequential headings; nested ol/ul; in-page anchors with matching id.
| 1 | <a class="skip-link" href="#main">Skip to content</a> |
| 2 | <main id="main"> |
| 3 | <h1>Constraint Validation API</h1> |
| 4 | <nav aria-label="On this page"> |
| 5 | <ol> |
| 6 | <li><a href="#required">Required fields</a></li> |
| 7 | <li><a href="#pattern">Pattern matching</a> |
| 8 | <ul> |
| 9 | <li><a href="#pattern-email">Email</a></li> |
| 10 | </ul> |
| 11 | </li> |
| 12 | </ol> |
| 13 | </nav> |
| 14 | <h2 id="required">Required fields</h2> |
| 15 | <p>Use <strong>required</strong> — not custom JS alone.</p> |
| 16 | </main> |
CP2 — Product comparison with media
Accept: picture + srcset; meaningful alt; table with caption/th scope; sandboxed iframe.
| 1 | <figure> |
| 2 | <picture> |
| 3 | <source media="(min-width: 800px)" srcset="/hero-wide.avif" type="image/avif"> |
| 4 | <img src="/hero.jpg" alt="ForgeLearn docs on a laptop" width="1200" height="630" loading="eager"> |
| 5 | </picture> |
| 6 | <figcaption>Art-directed hero for marketing vs docs layout.</figcaption> |
| 7 | </figure> |
| 8 | |
| 9 | <table> |
| 10 | <caption>Plan comparison</caption> |
| 11 | <thead> |
| 12 | <tr> |
| 13 | <th scope="col">Feature</th> |
| 14 | <th scope="col">Starter</th> |
| 15 | <th scope="col">Pro</th> |
| 16 | </tr> |
| 17 | </thead> |
| 18 | <tbody>...</tbody> |
| 19 | </table> |
| 20 | |
| 21 | <iframe |
| 22 | src="https://example.com/embed" |
| 23 | title="Product demo" |
| 24 | sandbox="allow-scripts allow-same-origin" |
| 25 | loading="lazy" |
| 26 | ></iframe> |
CP3 — Accessible checkout form
Accept: every control has a label; fieldsets with legends; correct input types; buttons with explicit type.
| 1 | <form action="/checkout" method="post" novalidate> |
| 2 | <fieldset> |
| 3 | <legend>Shipping</legend> |
| 4 | <label for="email">Email</label> |
| 5 | <input id="email" name="email" type="email" required autocomplete="email"> |
| 6 | |
| 7 | <label for="zip">Postal code</label> |
| 8 | <input id="zip" name="zip" type="text" required pattern="[0-9]{5}" inputmode="numeric"> |
| 9 | </fieldset> |
| 10 | |
| 11 | <button type="submit">Place order</button> |
| 12 | <button type="reset">Clear</button> |
| 13 | <button type="button" id="save-draft">Save draft</button> |
| 14 | </form> |
CP4 — Blog article with SEO head
Accept: landmark semantics; OG + Twitter meta; canonical; time datetime.
| 1 | <head> |
| 2 | <link rel="canonical" href="https://example.com/blog/html-landmarks"> |
| 3 | <meta property="og:title" content="HTML Landmarks in Practice"> |
| 4 | <meta property="og:type" content="article"> |
| 5 | <meta name="twitter:card" content="summary_large_image"> |
| 6 | </head> |
| 7 | <body> |
| 8 | <main> |
| 9 | <article> |
| 10 | <header> |
| 11 | <h1>HTML Landmarks in Practice</h1> |
| 12 | <p>Published <time datetime="2026-07-29">July 29, 2026</time></p> |
| 13 | </header> |
| 14 | <p>...</p> |
| 15 | </article> |
| 16 | <aside aria-label="Related">...</aside> |
| 17 | </main> |
| 18 | </body> |
CP5 — FAQ + confirm dialog
Accept: details/summary; native dialog with form method dialog — no div role="dialog".
| 1 | <details> |
| 2 | <summary>Do I need ARIA for a modal?</summary> |
| 3 | <p>Prefer the native <code><dialog></code> element first.</p> |
| 4 | </details> |
| 5 | |
| 6 | <dialog id="confirm"> |
| 7 | <form method="dialog"> |
| 8 | <p>Delete this draft?</p> |
| 9 | <button value="cancel" type="submit">Cancel</button> |
| 10 | <button value="confirm" type="submit">Delete</button> |
| 11 | </form> |
| 12 | </dialog> |
| 13 | <button type="button" onclick="document.getElementById('confirm').showModal()"> |
| 14 | Delete draft |
| 15 | </button> |
CP6 — Notes app with storage + history
Accept: works without JS for core content; storage used as enhancement; filter state reflected in URL via History API.
| 1 | <main> |
| 2 | <h1>Notes</h1> |
| 3 | <form id="filters" role="search"> |
| 4 | <label for="q">Filter</label> |
| 5 | <input id="q" name="q" type="search" value=""> |
| 6 | <button type="submit">Apply</button> |
| 7 | </form> |
| 8 | <ul id="notes"> |
| 9 | <li>Works even if localStorage is blocked</li> |
| 10 | </ul> |
| 11 | </main> |
| 12 | <!-- JS: pushState on filter; persist notes in localStorage --> |
CP7 — Production audit pass
Accept: no missing labels/alts; resource hints for critical assets; no inline event handlers if CSP forbids them; document outline passes automated + keyboard check.
| 1 | <head> |
| 2 | <link rel="preload" href="/fonts/jetbrains-mono.woff2" as="font" type="font/woff2" crossorigin> |
| 3 | <link rel="preconnect" href="https://cdn.example.com"> |
| 4 | <!-- Prefer external JS; avoid onclick= if CSP blocks unsafe-inline --> |
| 5 | </head> |
| 6 | <img src="/chart.png" alt="Monthly active users rising from Jan to Jun" width="640" height="360" loading="lazy" decoding="async"> |
| 7 | <button type="button" id="open-menu">Menu</button> |
best practice
Copy-paste prompts for agents and models. Run after fetching the stage's full markdown. Require the model to output HTML plus a short self-critique against the checklist.
| 1 | You are verifying HTML Stage 0 (Foundations) mastery on ForgeLearn. |
| 2 | |
| 3 | Task: Generate a complete HTML5 personal homepage (about + projects). |
| 4 | Constraints: |
| 5 | - Valid DOCTYPE, html[lang], charset, viewport, unique title |
| 6 | - header/nav/main/footer landmarks; exactly one h1 |
| 7 | - No unjustified div wrappers; explain any div you keep |
| 8 | - List three content-model rules you obeyed |
| 9 | |
| 10 | Self-critique: mark PASS/FAIL for each constraint. Fail closed. |
| 1 | Stage 1 verification — Text & navigation. |
| 2 | |
| 3 | Task: Mark up a tutorial page "HTML Lists" with skip link, TOC, |
| 4 | nested lists, and in-page anchors. Use strong/em correctly (not b/i |
| 5 | for importance/emphasis). |
| 6 | |
| 7 | Checklist: heading order, skip link target, id/href pairs, no |
| 8 | heading-level skips. Output HTML + PASS/FAIL table. |
| 1 | Stage 2 verification — Media & tables. |
| 2 | |
| 3 | Task: Build a product page with picture art direction, lazy below-fold |
| 4 | images with alt text, a captioned comparison table with th[scope], |
| 5 | and a sandboxed iframe with title. |
| 6 | |
| 7 | Fail if: empty alt on informative images, layout tables, missing |
| 8 | iframe title, or img without width/height when known. |
| 1 | Stage 3 verification — Forms mastery. |
| 2 | |
| 3 | Task: Generate a registration form with email, password, country |
| 4 | select, terms checkbox, and submit/reset/cancel actions. |
| 5 | |
| 6 | Hard rules: |
| 7 | - Every control has a <label for> or wrapping label |
| 8 | - fieldset/legend for grouped controls |
| 9 | - button type explicitly set (submit/reset/button) |
| 10 | - Use native constraint attributes (required, minlength, type=email) |
| 11 | - Do NOT use div role="button" or aria-label as a substitute for labels |
| 12 | |
| 13 | Return HTML + checklist PASS/FAIL. |
| 1 | Stage 4 verification — Semantics & SEO. |
| 2 | |
| 3 | Task: Produce a blog post document with semantic landmarks, Open Graph |
| 4 | + Twitter Card meta, canonical link, Article microdata or equivalent |
| 5 | structured intent, and lang on html. |
| 6 | |
| 7 | Explain why you chose article vs section for the post body. |
| 1 | Stage 5 verification — Interactive & modern. |
| 2 | |
| 3 | Task: Implement an FAQ with details/summary and a delete-confirm |
| 4 | dialog using <dialog> + form method="dialog". Optionally include a |
| 5 | minimal custom element with shadow DOM for a badge. |
| 6 | |
| 7 | Reject solutions that recreate dialogs with div + ARIA when native |
| 8 | dialog suffices. |
| 1 | Stage 6–7 verification — APIs + production. |
| 2 | |
| 3 | Task A: Describe progressive-enhancement HTML for a notes list that |
| 4 | gains localStorage and History filters via JS. |
| 5 | Task B: Audit your Stage 3 form for a11y, performance hints, and |
| 6 | CSP-safe markup. List concrete diffs. |
| 7 | |
| 8 | Mastery claim rule: only claim mastery if Stages 0–7 verification |
| 9 | prompts all PASS with zero critical fails after full markdown fetch. |
warning
Humans and models fail HTML the same ways. Treat each row as a regression test for your next generation or code review.
| Mistake | Who | Fix |
|---|---|---|
| Div soup for layout & UI | Both | Prefer semantic landmarks and native controls; CSS for layout |
| <button> without type (defaults to submit) | Both | Always set type="button|submit|reset" |
| Missing labels on inputs | Both | label for / wrapping label; never placeholder-as-label |
| <img> without alt | Both | Informative alt text, or alt="" if decorative |
| ARIA instead of native HTML | AI heavy | Use button, dialog, details before roles |
| <a> without href as a button | Both | Links navigate; buttons perform actions |
| Heading level skips / multiple h1 | Both | One h1 per page view; nest h2–h6 sequentially |
| Invalid nesting (e.g. interactive in interactive) | AI heavy | Respect content models; no a inside a, no button inside button |
| Inline onclick under strict CSP | Both | External scripts + addEventListener |
| Claiming mastery from outlines / titles only | AI | Fetch full ?format=md pages; verify with generation tasks |
pro tip
The curriculum teaches skills. The encyclopedias teach depth. Use both:
| Reference | Use when | Path |
|---|---|---|
| Complete Tag Reference | Quick lookup — tag purpose, category, void vs container, common attributes | /docs/html/tags |
| Elements | Deep dive — content models, nesting rules, global attributes, categories | /docs/html/elements |
Workflow: learn a skill on a topic page → prove it with a checkpoint → deepen with Tags/Elements lookup when choosing between similar elements. Agents should fetch Tags/Elements markdown when a generation task involves uncommon elements or nesting edge cases.
After HTML mastery, keep the same deliberate loop — roadmap → practice → verify — on the next layer of the stack:
- CSS Roadmap — layout, cascade, responsive design, modern CSS features
- JavaScript Roadmap — DOM, events, async, modules, progressive enhancement on top of solid HTML
- Accessibility deep dive — WCAG, keyboard patterns, when ARIA is actually required
- HTML Best Practices — production checklist spanning semantics, forms, SEO, and security
info
Community
Get help on Slack, Discord or VIP
Stuck on a guide? Join the community and ask.