|$ curl https://forge-ai.dev/api/markdown?path=docs/html
$cat docs/html-—-getting-started.md
updated Recently·45 min read·published

HTML — Getting Started

HTMLBeginner to Advanced
Introduction

HTML (HyperText Markup Language) is the standard markup language for creating web pages. It describes the structure of a web page semantically, providing the foundation upon which CSS and JavaScript are applied.

Every web page you visit is built on HTML. This guide covers everything from document anatomy to modern HTML features, parsing internals, and best practices.

Document Anatomy

Every HTML document follows a standard structure. This is the minimal skeleton of a valid HTML5 page:

index.html
HTML
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>My Page</title>
7</head>
8<body>
9 <h1>Hello, World!</h1>
10 <p>Welcome to HTML.</p>
11</body>
12</html>
preview

info

Always include the <!DOCTYPE html> declaration. It tells the browser to render the page in standards mode, preventing quirks mode behavior that varies across browsers.
DOCTYPE Declaration

The <!DOCTYPE html> is not an HTML element — it is a document type declaration that instructs the browser to parse the page in standards mode. It must be the very first line of every HTML document, before the <html> element.

DOCTYPEModeUsage
<!DOCTYPE html>Standards ModeHTML5 — Recommended
<!DOCTYPE HTML PUBLIC ...>Almost StandardsLegacy HTML 4.01
(none)Quirks ModeAvoid — inconsistent rendering
doctype-comparison.html
HTML
1<!-- HTML5 (always use this) -->
2<!DOCTYPE html>
3<html lang="en">
4...
5
6<!-- Legacy HTML 4.01 (avoid) -->
7<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
8 "http://www.w3.org/TR/html4/strict.dtd">
9
10<!-- XHTML 1.0 (avoid) -->
11<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
12 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

best practice

Only use <!DOCTYPE html> (HTML5). It is the shortest, easiest to remember, and triggers full standards mode in all modern browsers. Older DOCTYPEs are legacy and unnecessary.
The HTML Element

The <html> element is the root element of every HTML document. It wraps all content on the page. The lang attribute is critical for accessibility, search engines, and browser features like translation.

index.html
HTML
1<!DOCTYPE html>
2<html lang="en">
3 <!-- All page content here -->
4</html>

Common lang values:

ValueLanguageBCP 47
enEnglish
en-USEnglish (US)
zh-CNChinese (Simplified)
esSpanish
arArabic

warning

Never omit the lang attribute on the <html> element. It is required for WCAG 2.1 compliance (Success Criterion 3.1.1), and screen readers depend on it for correct pronunciation.
Head Metadata

The <head> element contains metadata about the document: title, character encoding, viewport settings, stylesheets, scripts, and SEO information. Content inside the head is not displayed in the browser.

head-section.html
HTML
1<head>
2 <!-- Character encoding — must be UTF-8 -->
3 <meta charset="UTF-8" />
4
5 <!-- Viewport for responsive design -->
6 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
8 <!-- Title — required, shown in tab and search results -->
9 <title>My Page | Site Name</title>
10
11 <!-- SEO meta tags -->
12 <meta name="description" content="A description of the page for search engines." />
13 <meta name="keywords" content="html, tutorial, web development" />
14 <meta name="author" content="Your Name" />
15
16 <!-- Open Graph (social sharing) -->
17 <meta property="og:title" content="My Page" />
18 <meta property="og:description" content="What shows up when shared on social media." />
19 <meta property="og:image" content="https://example.com/thumbnail.jpg" />
20 <meta property="og:url" content="https://example.com/page" />
21 <meta property="og:type" content="website" />
22
23 <!-- Twitter Card -->
24 <meta name="twitter:card" content="summary_large_image" />
25 <meta name="twitter:title" content="My Page" />
26 <meta name="twitter:description" content="Twitter-specific description." />
27 <meta name="twitter:image" content="https://example.com/thumbnail.jpg" />
28
29 <!-- Favicon -->
30 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
31 <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
32
33 <!-- Canonical URL (prevents duplicate content issues) -->
34 <link rel="canonical" href="https://example.com/page" />
35
36 <!-- RSS feed -->
37 <link rel="alternate" type="application/rss+xml" title="RSS" href="/feed.xml" />
38
39 <!-- Preconnect to external origins for performance -->
40 <link rel="preconnect" href="https://fonts.googleapis.com" />
41 <link rel="preconnect" href="https://cdn.example.com" crossorigin />
42
43 <!-- External stylesheets -->
44 <link rel="stylesheet" href="/styles.css" />
45
46 <!-- Deferred JavaScript -->
47 <script src="/app.js" defer></script>
48</head>
🔥

pro tip

Always put <meta charset="UTF-8" /> as the first child of <head>. It must be within the first 1024 bytes of the document for the browser to apply it before parsing the rest of the page, preventing encoding-related parsing errors.

Here is an interactive example showing how meta tags affect how your page appears:

preview
Content Categories

HTML elements belong to content categories that define where they can be placed and what they can contain. Understanding these categories is essential for writing valid, semantic HTML.

Flow Content

Most elements that go inside the body. This is the broadest category, including text, images, forms, tables, sections, and interactive elements.

flow-content.txt
HTML
1<p>, <div>, <span>, <ul>, <ol>, <table>, <form>,
2<section>, <article>, <header>, <footer>, <main>,
3<img>, <video>, <audio>, <canvas>, <figure>, <blockquote>

Phrasing Content

Inline-level elements that mark up text. These can only contain other phrasing content.

phrasing-content.txt
HTML
1<span>, <strong>, <em>, <a>, <code>, <b>, <i>, <u>,
2<small>, <sub>, <sup>, <mark>, <q>, <cite>, <time>,
3<button>, <input>, <label>, <textarea>, <select>,
4<br>, <img>, <svg>, <abbr>, <dfn>, <var>, <samp>, <kbd>

Interactive Content

Elements specifically designed for user interaction. They are content that the user can click, tap, or otherwise interact with.

interactive-content.txt
HTML
1<a> (with href), <button>, <input>, <select>, <textarea>,
2<details>, <summary>, <label>, <audio> (with controls),
3<video> (with controls), <dialog>

Sectioning Content

Elements that create sections in the document outline. They define the scope of headings and the document structure.

sectioning-content.txt
HTML
1<article>, <section>, <nav>, <aside>, <h1>-<h6>,
2<header>, <footer>, <main>, <address>

Embedded Content

Elements that import external resources into the document.

embedded-content.txt
HTML
1<img>, <video>, <audio>, <iframe>, <embed>, <object>,
2<picture>, <source>, <track>, <canvas>, <svg>

Metadata Content

Elements that set up the presentation or behavior of the document, or provide information about the document.

metadata-content.txt
HTML
1<base>, <link>, <meta>, <noscript>, <script>, <style>,
2<title>, <template>

best practice

Understanding content categories helps you write valid HTML. For example, <div> cannot be placed inside <p> because <p> only accepts phrasing content. Use the HTML spec or validator to check your structure.
Semantic HTML

Semantic HTML means using elements that convey meaning about their content, not just how it looks. This improves accessibility, SEO, and code maintainability.

semantic-html.html
HTML
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>Semantic HTML Structure</title>
7</head>
8<body>
9 <header>
10 <nav>
11 <ul>
12 <li><a href="/">Home</a></li>
13 <li><a href="/about">About</a></li>
14 <li><a href="/blog">Blog</a></li>
15 <li><a href="/contact">Contact</a></li>
16 </ul>
17 </nav>
18 </header>
19
20 <main>
21 <article>
22 <header>
23 <h1>Article Title</h1>
24 <p>Published on <time datetime="2026-01-15">January 15, 2026</time></p>
25 </header>
26
27 <section id="introduction">
28 <h2>Introduction</h2>
29 <p>Content introduction here.</p>
30 </section>
31
32 <section id="body">
33 <h2>Main Content</h2>
34 <p>Article body content goes here.</p>
35
36 <figure>
37 <img src="diagram.png" alt="Diagram explaining the concept" />
38 <figcaption>Figure 1: Concept explanation diagram</figcaption>
39 </figure>
40 </section>
41 </article>
42
43 <aside>
44 <h2>Related Articles</h2>
45 <ul>
46 <li><a href="/related-1">Related Post 1</a></li>
47 <li><a href="/related-2">Related Post 2</a></li>
48 </ul>
49 </aside>
50 </main>
51
52 <footer>
53 <p>&copy; 2026 Your Site. All rights reserved.</p>
54 <address>
55 Contact: <a href="mailto:info@example.com">info@example.com</a>
56 </address>
57 </footer>
58</body>
59</html>
preview

Semantic elements and their purposes:

ElementPurposeUsage
<header>Introductory content or navigationTop of page or section
<nav>Navigation linksPrimary site navigation
<main>Primary content (unique per page)One per page
<article>Self-contained compositionBlog posts, news, comments
<section>Thematic grouping of contentChapters, tab panels
<aside>Tangentially related contentSidebars, pull quotes
<footer>Footer for page or sectionCopyright, links, meta
<figure>Self-contained media with captionImages, diagrams, code
<figcaption>Caption for figureMust be inside figure
<time>Machine-readable date/timeDates, event times
<address>Contact informationAuthor or company contact
<mark>Highlighted/referenced textSearch results, quotes

warning

Use <div>only as a last resort. Every div you write should make you ask: "Is there a semantic element I could use instead?" Accessibility tools and search engines rely on meaningful structure, not generic containers.
Embedded Content

HTML provides powerful elements for embedding external resources like images, video, audio, and other web pages.

Images — <img> & <picture>

The <img> element embeds images. Always provide alt text for accessibility. Use <picture> for responsive images.

images.html
HTML
1<!-- Basic image with required alt text -->
2<img src="photo.jpg" alt="A sunset over the ocean" width="800" height="600" />
3
4<!-- Responsive image with srcset -->
5<img
6 src="photo-800.jpg"
7 srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
8 sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
9 alt="A sunset over the ocean"
10 loading="lazy"
11 decoding="async"
12/>
13
14<!-- Picture element for art direction -->
15<picture>
16 <source media="(min-width: 1200px)" srcset="hero-wide.jpg" />
17 <source media="(min-width: 768px)" srcset="hero-tablet.jpg" />
18 <source media="(min-width: 480px)" srcset="hero-mobile.jpg" />
19 <img src="hero-fallback.jpg" alt="Hero banner image" />
20</picture>
21
22<!-- Figure with caption -->
23<figure>
24 <img src="diagram.svg" alt="Architecture diagram" />
25 <figcaption>System architecture overview</figcaption>
26</figure>
preview

Video — <video>

The <video> element embeds video content. Provide multiple source formats for cross-browser compatibility and include captions.

video.html
HTML
1<video
2 controls
3 width="640"
4 height="360"
5 poster="thumbnail.jpg"
6 preload="metadata"
7>
8 <source src="video.mp4" type="video/mp4" />
9 <source src="video.webm" type="video/webm" />
10 <source src="video.ogv" type="video/ogg" />
11 <track
12 kind="captions"
13 src="captions-en.vtt"
14 srclang="en"
15 label="English"
16 />
17 <p>Your browser does not support video.
18 <a href="video.mp4">Download the video</a>.</p>
19</video>

Audio — <audio>

The <audio> element embeds audio content. Like video, provide multiple source formats.

audio.html
HTML
1<audio controls preload="none">
2 <source src="podcast.mp3" type="audio/mpeg" />
3 <source src="podcast.ogg" type="audio/ogg" />
4 <source src="podcast.wav" type="audio/wav" />
5 <p>Your browser does not support audio.
6 <a href="podcast.mp3">Download the podcast</a>.</p>
7</audio>
preview

Iframe — <iframe>

The <iframe> element embeds another HTML page. Always sandbox for security.

iframe.html
HTML
1<!-- Secure iframe with sandbox -->
2<iframe
3 src="https://example.com/widget"
4 width="400"
5 height="300"
6 sandbox="allow-scripts allow-same-origin"
7 loading="lazy"
8 title="Example widget"
9 allow="clipboard-write; payment"
10>
11 <p>Your browser does not support iframes.</p>
12</iframe>
13
14<!-- Lazy-loaded map embed -->
15<iframe
16 src="https://maps.google.com/?q=location"
17 width="100%"
18 height="350"
19 loading="lazy"
20 referrerpolicy="no-referrer-when-downgrade"
21 title="Map location"
22 style="border:0;border-radius:8px"
23></iframe>

warning

Always use the sandbox attribute on iframes that load untrusted content. It restricts what the embedded document can do, protecting your users from malicious content. Never omit it for third-party embeds.

best practice

Always include alt text on images, loading="lazy" for below-the-fold content, and width/height attributes to prevent layout shifts (CLS — Cumulative Layout Shift).
Modern HTML Features

HTML has evolved significantly. These modern features provide native browser functionality that previously required JavaScript.

<dialog> — Native Modal

The <dialog> element provides a native modal dialog. It supports open/close, backdrop dismissal, and focus trapping automatically.

dialog.html
HTML
1<!-- Modal dialog -->
2<dialog id="myModal">
3 <form method="dialog">
4 <h2>Confirm Action</h2>
5 <p>Are you sure you want to proceed?</p>
6 <menu>
7 <button value="cancel">Cancel</button>
8 <button value="confirm">Confirm</button>
9 </menu>
10 </form>
11</dialog>
12
13<!-- Open with JavaScript -->
14<script>
15 const modal = document.getElementById("myModal");
16 modal.showModal(); // Opens as modal
17 modal.close("confirmed"); // Closes with return value
18</script>
preview
🔥

pro tip

Use showModal() instead of show() for dialogs. showModal() creates a backdrop and traps focus, making it truly accessible. The <form method="dialog"> pattern automatically closes the dialog on submit.

<details> & <summary> — Disclosure Widget

Native accordion-style expand/collapse without JavaScript. Perfect for FAQs, collapsible sections, and progressive disclosure.

details.html
HTML
1<details>
2 <summary>What is HTML?</summary>
3 <p>HTML (HyperText Markup Language) is the standard
4 markup language for creating web pages.</p>
5</details>
6
7<details open>
8 <summary>Already expanded section</summary>
9 <p>Add the open attribute to start expanded.</p>
10</details>
11
12<!-- Nested details for tree navigation -->
13<details>
14 <summary>Chapter 1: Introduction</summary>
15 <details>
16 <summary>1.1 What is the Web?</summary>
17 <p>The web is a system of interlinked hypertext documents.</p>
18 </details>
19 <details>
20 <summary>1.2 History of HTML</summary>
21 <p>HTML was created by Tim Berners-Lee in 1991.</p>
22 </details>
23</details>
preview

<datalist> — Autocomplete Suggestions

Provides a list of predefined options for an input field, enabling autocomplete behavior natively.

datalist.html
HTML
1<label for="browser">Choose a browser:</label>
2<input
3 list="browsers"
4 id="browser"
5 name="browser"
6 placeholder="Start typing..."
7/>
8
9<datalist id="browsers">
10 <option value="Chrome" />
11 <option value="Firefox" />
12 <option value="Safari" />
13 <option value="Edge" />
14 <option value="Opera" />
15 <option value="Brave" />
16 <option value="Arc" />
17</datalist>
preview

info

Use <datalist> when you want to provide suggestions but still allow free-form input. For strictly limited choices, use <select> instead.

<template> — Declarative Templates

The <template> element holds HTML that is not rendered immediately but can be instantiated by JavaScript. Its contents are parsed but inert.

template.html
HTML
1<!-- Define template -->
2<template id="card-template">
3 <div class="card">
4 <img class="card-image" src="" alt="" />
5 <div class="card-body">
6 <h3 class="card-title"></h3>
7 <p class="card-description"></p>
8 </div>
9 </div>
10</template>
11
12<!-- Clone and populate with JavaScript -->
13<script>
14 const template = document.getElementById("card-template");
15
16 function createCard(image, alt, title, description) {
17 const clone = template.content.cloneNode(true);
18
19 clone.querySelector(".card-image").src = image;
20 clone.querySelector(".card-image").alt = alt;
21 clone.querySelector(".card-title").textContent = title;
22 clone.querySelector(".card-description").textContent = description;
23
24 document.body.appendChild(clone);
25 }
26
27 createCard("photo.jpg", "A photo", "My Card", "Description");
28</script>

<slot> — Web Component Composition

The <slot> element is part of the Web Components specification. It defines insertion points within a shadow DOM where content can be projected.

slot.html
HTML
1<!-- Custom element with slots -->
2<template id="page-layout">
3 <style>
4 header { background: #1a1a2e; padding: 1rem; }
5 main { padding: 1rem; }
6 footer { background: #1a1a2e; padding: 0.5rem; text-align: center; }
7 </style>
8 <header>
9 <slot name="header">Default header</slot>
10 </header>
11 <main>
12 <slot>Default content</slot>
13 </main>
14 <footer>
15 <slot name="footer">&copy; 2026</slot>
16 </footer>
17</template>
18
19<!-- Usage -->
20<page-layout>
21 <h1 slot="header">My Page</h1>
22 <p>Main content goes here.</p>
23 <p slot="footer">Custom footer content</p>
24</page-layout>
25
26<script>
27 class PageLayout extends HTMLElement {
28 constructor() {
29 super();
30 const template = document.getElementById("page-layout");
31 const shadow = this.attachShadow({ mode: "open" });
32 shadow.appendChild(template.content.cloneNode(true));
33 }
34 }
35 customElements.define("page-layout", PageLayout);
36</script>

<progress> & <meter>

Native elements for displaying progress and measurements.

progress-meter.html
HTML
1<!-- Progress bar (indeterminate or determinate) -->
2<label for="upload">Upload progress:</label>
3<progress id="upload" max="100" value="65">65%</progress>
4
5<!-- Meter for scalar measurements -->
6<label for="disk">Disk usage:</label>
7<meter id="disk" min="0" max="100" low="25" high="75" optimum="50" value="80">
8 80% used
9</meter>
10
11<!-- Styling with CSS -->
12<style>
13 progress[value] {
14 appearance: none;
15 height: 8px;
16 border-radius: 4px;
17 overflow: hidden;
18 }
19 progress[value]::-webkit-progress-value {
20 background: #00FF41;
21 }
22 progress[value]::-webkit-progress-bar {
23 background: #222222;
24 }
25</style>
preview

best practice

Modern HTML features like <dialog>, <details>, and <datalist> reduce JavaScript dependencies significantly. Always check if the browser provides a native solution before reaching for JS.
Microdata & ARIA

Microdata adds machine-readable semantics to HTML, while ARIA (Accessible Rich Internet Applications) provides accessibility semantics for assistive technologies.

Microdata & Schema.org

Microdata allows you to annotate HTML elements with machine-readable labels from Schema.org, enabling rich search results (rich snippets).

microdata.html
HTML
1<article itemscope itemtype="https://schema.org/Article">
2 <h1 itemprop="headline">How HTML Works</h1>
3 <p itemprop="description">A comprehensive guide to HTML.</p>
4 <meta itemprop="datePublished" content="2026-01-15" />
5 <span itemprop="author" itemscope itemtype="https://schema.org/Person">
6 <span itemprop="name">Jane Doe</span>
7 </span>
8</article>
9
10<!-- Product schema for e-commerce -->
11<div itemscope itemtype="https://schema.org/Product">
12 <img itemprop="image" src="product.jpg" alt="Product photo" />
13 <h2 itemprop="name">Wireless Headphones</h2>
14 <p itemprop="description">Noise-cancelling Bluetooth headphones.</p>
15 <div itemprop="offers" itemscope itemtype="https://schema.org/Offer">
16 <span itemprop="priceCurrency" content="USD">$</span>
17 <span itemprop="price">79.99</span>
18 <link itemprop="availability" href="https://schema.org/InStock" />
19 </div>
20 <div itemprop="aggregateRating" itemscope
21 itemtype="https://schema.org/AggregateRating">
22 <span itemprop="ratingValue">4.5</span> stars
23 (<span itemprop="reviewCount">128</span> reviews)
24 </div>
25</div>
26
27<!-- Breadcrumb schema -->
28<nav aria-label="Breadcrumb" itemscope
29 itemtype="https://schema.org/BreadcrumbList">
30 <ol>
31 <li itemprop="itemListElement" itemscope
32 itemtype="https://schema.org/ListItem">
33 <a itemprop="item" href="/">
34 <span itemprop="name">Home</span>
35 </a>
36 <meta itemprop="position" content="1" />
37 </li>
38 <li itemprop="itemListElement" itemscope
39 itemtype="https://schema.org/ListItem">
40 <a itemprop="item" href="/docs">
41 <span itemprop="name">Docs</span>
42 </a>
43 <meta itemprop="position" content="2" />
44 </li>
45 </ol>
46</nav>

ARIA — Accessible Rich Internet Applications

ARIA attributes bridge gaps where native HTML semantics are insufficient. The golden rule: only use ARIA when native HTML is not enough.

aria.html
HTML
1<!-- ARIA Landmarks (use semantic HTML first!) -->
2<header role="banner">
3 <nav role="navigation" aria-label="Main navigation">
4 ...
5 </nav>
6</header>
7
8<main role="main">
9 <article role="article">
10 ...
11 </article>
12</main>
13
14<footer role="contentinfo">
15 ...
16</footer>
17
18<!-- ARIA for dynamic content -->
19<div
20 role="alert"
21 aria-live="polite"
22 aria-atomic="true"
23>
24 Form submitted successfully!
25</div>
26
27<!-- ARIA for custom interactive widgets -->
28<button
29 aria-expanded="false"
30 aria-controls="menu-list"
31 aria-haspopup="true"
32>
33 Menu
34</button>
35<ul id="menu-list" role="menu" aria-hidden="true">
36 <li role="menuitem" tabindex="0">Item 1</li>
37 <li role="menuitem" tabindex="-1">Item 2</li>
38</ul>
39
40<!-- ARIA for status messages -->
41<div
42 role="status"
43 aria-live="polite"
44 aria-relevant="additions"
45>
46 <p>3 new messages</p>
47</div>
48
49<!-- ARIA for progress (when not using native progress) -->
50<div
51 role="progressbar"
52 aria-valuenow="65"
53 aria-valuemin="0"
54 aria-valuemax="100"
55 aria-label="Upload progress"
56>
57 65%
58</div>

warning

ARIA is not magic. Adding role="button" to a <div> does not make it a real button. Assistive technology will announce it as a button, but you still need to add keyboard event handling, focus management, and proper semantics. First rule of ARIA: do not use ARIA if you can use a native HTML element.
🔥

pro tip

Use the aria-label attribute on elements that have no visible text but need an accessible name — typically icon-only buttons, interactive icons, and close buttons. Example: <button aria-label="Close dialog">✕</button>
Performance Optimizations

HTML attributes play a crucial role in web performance. Correct use of async, defer, preload, and prefetch can dramatically improve loading times.

AttributeResourceBehavior
asyncScriptDownload in parallel, execute as soon as downloaded
deferScriptDownload in parallel, execute after document parsed (in order)
preloadCritical assetsFetch early, high priority (current page)
prefetchFuture navigationFetch opportunistically, low priority (next page)
preconnectOriginPre-emptively open connection (DNS + TLS)
dns-prefetchOriginPre-resolve DNS only
modulepreloadModule scriptsPreload ES module and its dependencies
prerenderFull pageRender entire page in background (deprecated in some browsers)
performance.html
HTML
1<!-- Script loading strategies -->
2
3<!-- Blocking (default) — pauses HTML parsing -->
4<script src="app.js"></script>
5
6<!-- Async — download in parallel, execute ASAP (out of order) -->
7<script src="analytics.js" async></script>
8
9<!-- Defer — download in parallel, execute after parse (in order) -->
10<script src="app.js" defer></script>
11<script src="utils.js" defer></script>
12
13<!-- Resource hints for performance -->
14
15<!-- Preload critical resources (fonts, hero images, CSS) -->
16<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin />
17<link rel="preload" href="/hero.jpg" as="image" />
18<link rel="preload" href="/critical.css" as="style" />
19
20<!-- Prefetch resources for the next page -->
21<link rel="prefetch" href="/about" as="document" />
22<link rel="prefetch" href="/about/style.css" as="style" />
23<link rel="prefetch" href="/about/hero.jpg" as="image" />
24
25<!-- Preconnect to third-party origins -->
26<link rel="preconnect" href="https://fonts.googleapis.com" />
27<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin />
28
29<!-- DNS prefetch (fallback for older browsers) -->
30<link rel="dns-prefetch" href="https://cdn.example.com" />
31
32<!-- Module preload for ES modules -->
33<link rel="modulepreload" href="/app.mjs" />
34
35<!-- Lazy loading for images and iframes -->
36<img src="photo.jpg" loading="lazy" decoding="async" />
37<iframe src="widget.html" loading="lazy"></iframe>

info

Use defer for scripts that depend on the DOM being ready. Use async for independent scripts like analytics. Never use blocking scripts in the <head> unless absolutely necessary — they delay rendering.

best practice

Avoid using both preload and prefetch for the same resource. Preloading is for current-page critical assets that the browser would discover late (like hero images referenced in CSS or fonts loaded from CSS). Overuse of preload competes with other critical resources.
Parsing Internals

Understanding how browsers parse HTML helps you write more efficient code and debug rendering issues. The HTML parser follows a deterministic algorithm defined in the HTML specification.

Tokenization Phase

The tokenizer reads raw HTML byte by byte and produces tokens: start tags, end tags, attributes, comments, and text. It uses a state machine with over 80 states.

tokenization.txt
HTML
1<!-- Raw HTML input -->
2<p class="greeting">Hello, <strong>World</strong>!</p>
3
4<!-- Tokenization output (conceptual) -->
5StartTag: <p>
6 Attribute: class="greeting"
7Text: "Hello, "
8StartTag: <strong>
9Text: "World"
10EndTag: </strong>
11Text: "!"
12EndTag: </p>

Tree Construction Phase

Tokens are fed to the tree construction algorithm, which builds the DOM tree. The parser maintains a stack of open elements and an insertion mode that determines how each token is processed.

tree-construction.txt
HTML
1<!-- Parsing algorithm steps (simplified) -->
2
31. Initial state
4 - DOCTYPE: <!DOCTYPE html>
5 - Insert document node, set mode to standards
6
72. Before HTML
8 - Any token before <html> creates implicit <html>
9
103. Before Head
11 - After <html>, next token creates implicit <head>
12
134. In Head
14 - <title>, <meta>, <link>, <script> processed
15 - </head> pops head element
16
175. After Head / In Body
18 - Most content parsed here
19 - Implicit <body> created before first body content
20
216. In Table
22 - Special parsing rules for table elements
23 - Foster parenting: misnested table content moved before table
24
257. After Body / After After Body
26 - </body> and </html> tokens processed
27
288. Text / Foreign Content
29 - CDATA sections (SVG, MathML) use different rules
30 - Raw text elements (<script>, <style>) use different tokenizer

warning

HTML parsers are fault-tolerant by design. Unlike XML, HTML does not throw errors on malformed markup — it applies specific error recovery rules. This is why <br></br> and <br /> both work, and why missing end tags are silently corrected. Do not rely on this behavior; write valid HTML.

Key Parsing Concepts

Foster Parenting

When content that should be inside a table element is incorrectly placed, the parser moves ("fosters") it before the table. This is why misnested HTML rarely breaks pages entirely.

foster-parenting.html
HTML
1<!-- Misnested (foster parenting applies) -->
2<table>
3 <tr>
4 <td>Cell</td>
5 </tr>
6 <p>This text gets fostered before the table</p>
7</table>
8
9<!-- Parse result: -->
10<p>This text gets fostered before the table</p>
11<table>
12 <tr>
13 <td>Cell</td>
14 </tr>
15</table>

Script Execution Model

When the parser encounters a blocking <script>, it pauses HTML parsing, downloads and executes the script, then resumes. defer and async change this behavior.

script-execution.html
HTML
1<!-- Parser blocking — delays rendering -->
2<script src="large.js"></script>
3
4<!-- Parser pauses, waits for download, executes, resumes -->
5
6<!-- Async — download in parallel, execute when ready -->
7<script src="analytics.js" async></script>
8
9<!-- Defer — download in parallel, execute after parse -->
10<script src="app.js" defer></script>
🔥

pro tip

The browser's preload scanner is a secondary parser that runs ahead of the main parser to discover subresources (images, scripts, stylesheets) before the main parser reaches them. This is why preload hints like <link rel="preload"> can boost performance — they give the preload scanner an extra signal for late-discovered resources.
Best Practices Checklist

A comprehensive checklist to ensure your HTML is valid, accessible, performant, and maintainable.

Structure & Validity

Always include <!DOCTYPE html> declaration
Use <html lang="..."> with correct language code
Set <meta charset="UTF-8"> as first child of <head>
Include <meta name="viewport" content="width=device-width, initial-scale=1.0"> for responsive design
Always provide a descriptive <title> in <head>
Validate your HTML with the W3C Validator
Close all optional tags (</li>, </td>, </tr>) for consistency — some teams prefer omitting them, but explicit closing is clearer

Accessibility

Use semantic HTML elements — don't use <div> for everything
Include alt text on every <img> element
Use <button> for actions, <a> for navigation
Ensure proper heading hierarchy (h1 → h2 → h3, never skip levels)
Add labels to all form controls via <label> or aria-label
Use aria-expanded, aria-controls, and aria-label on interactive widgets
Test with screen readers (VoiceOver, NVDA, JAWS)
Support keyboard navigation (Tab, Enter, Escape, Arrow keys)
Use <figure> and <figcaption> for self-contained media
Provide captions and transcripts for audio/video content

Performance

Defer non-critical JavaScript with defer or async
Lazy-load below-the-fold images with loading="lazy"
Preload critical assets (fonts, hero images) with <link rel="preload">
Preconnect to third-party origins used early in page load
Specify width and height on images to prevent CLS
Use modern image formats (WebP, AVIF) with <picture> fallback
Minimize the use of blocking scripts in <head>
Use <link rel="prefetch"> for likely next-page resources

SEO & Semantics

Use descriptive <title> (unique per page, 50-60 characters)
Write compelling meta descriptions (150-160 characters)
Use Open Graph meta tags for social sharing
Implement Schema.org microdata for rich snippets
Use canonical URLs to prevent duplicate content
Maintain a clear heading hierarchy (h1 → h6)
Use <nav> for primary navigation landmarks
Add <link rel="canonical"> to specify preferred URL

Security

Always sandbox iframes that load untrusted content
Use rel="noopener noreferrer" on external links
Never render user-generated content without escaping
Set Content-Security-Policy via <meta> tag or HTTP header
Use referrerpolicy="no-referrer-when-downgrade" on links
Validate and sanitize all form input server-side
Use Subresource Integrity (SRI) for external scripts and stylesheets

Maintainability

Use consistent indentation (2 or 4 spaces)
Write lowercase element and attribute names
Quote attribute values (single or double quotes, be consistent)
Use self-closing tags for void elements (<br />, <img />, <input />)
Organize CSS with class-based selectors, avoid inline styles
Use data-* attributes for custom data, never invent non-standard attributes
Keep template logic separate — avoid heavy logic in HTML
Comment complex sections where purpose is not obvious
Use prettier or other formatters for consistent formatting

best practice

Run your HTML through the W3C Validator before every deployment. Catch issues like unclosed tags, duplicate IDs, improperly nested elements, and missing required attributes. Validation is the first step toward quality.
Common Mistakes

✗ Incorrect

<div onclick="submit()">Submit</div>

Non-semantic: use <button> or <a> instead.

✗ Incorrect

<img src="photo.jpg" />

Missing alt attribute — accessibility failure.

✗ Incorrect

<h1>Title</h1><h3>Subtitle</h3>

Skipping heading levels — use <h2> after <h1>.

✗ Incorrect

<form><button>Submit</button></form>

Button defaults to type="submit" in forms — specify type="button" if not submitting.

✗ Incorrect

<a href="#" onclick="navigate()">Link</a>

Use real URLs instead of href="#" for progressive enhancement.

✗ Incorrect

<div class="nav">...</div>

Use <nav> instead of a generic div for navigation.

🔥

pro tip

Write HTML with the mindset that your code will be read by screen readers, parsed by search engines, and maintained by other developers. Semantic, valid HTML is the foundation of the web — it degrades gracefully, works everywhere, and lasts forever.
$Blueprint — Engineering Documentation·Section ID: HTML-01·Revision: 1.0