Developer Documentation ⏱️ 35 min read Verified Production Ready

HTML Reference & Documentation

Exhaustive HTML5 semantic standard reference with accessibility attributes, meta tags, and structured schema implementation.

0% read
HTML Reference
& Documentation

Every HTML concept, element, attribute, API, and best practice — structured as an interactive living document for developers and educators.

24
Chapters
140+
Elements Covered
60+
Live Examples
100%
Modern HTML
HTML Foundations

HTML (HyperText Markup Language) is the standard markup language for creating web pages. It describes the structure of content — not its appearance. CSS handles styling; JavaScript handles behaviour.

📄

Markup

Elements wrap content in angle-bracket tags to give it meaning and structure.

🌲

DOM Tree

The browser parses HTML into a Document Object Model — a live tree of nodes.

🔗

HyperText

Links connect documents across the web, forming the "hyper" in HyperText.

🧩

Standards

HTML is maintained by WHATWG as a living standard; no version numbers anymore.

Anatomy of an HTML Element

HTML
<!-- Opening tag   Content   Closing tag -->
<p class="intro">Hello, World!</p>

<!-- Void element — self-closing, no content -->
<img src="photo.jpg" alt="A photo" />

<!-- Attributes: name="value" pairs on the opening tag -->
<a href="https://example.com" target="_blank" rel="noopener">
  Visit Example
</a>

Global Attributes

These attributes can be placed on any HTML element:

AttributeDescriptionExample
idUnique identifier on the pageid="header"
classCSS class name(s)class="btn primary"
styleInline CSS stylesstyle="color:red"
data-*Custom data attributesdata-user-id="42"
hiddenHides element visually & from a11y treehidden
tabindexControls keyboard focus ordertabindex="0"
contenteditableMakes element editablecontenteditable="true"
draggableEnables drag-and-dropdraggable="true"
langLanguage of element's contentlang="fr"
dirText direction (ltr / rtl / auto)dir="rtl"
titleTooltip text on hovertitle="More info"
spellcheckBrowser spell-check on/offspellcheck="false"
translateWhether to translate contenttranslate="no"
slotWeb Component slot assignmentslot="icon"
partCSS part for Shadow DOM stylingpart="button"
Document Structure

Every HTML document follows a specific skeleton. Understanding this skeleton is essential before writing a single tag.

HTML — Full Skeleton
<!-- DOCTYPE declaration: tells browser this is HTML5 -->
<!DOCTYPE html>

<!-- Root element with language attribute -->
<html lang="en">

<head>
  <!-- Character encoding — MUST be first in <head> -->
  <meta charset="UTF-8" />

  <!-- Responsive viewport -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <!-- Page title shown in tab and search results -->
  <title>My Page Title</title>

  <!-- Meta description for SEO -->
  <meta name="description" content="Page description here" />

  <!-- External CSS -->
  <link rel="stylesheet" href="styles.css" />

  <!-- Inline CSS -->
  <style> body { margin: 0; } </style>

  <!-- Favicon -->
  <link rel="icon" href="favicon.ico" />

  <!-- Preload critical resource -->
  <link rel="preload" href="font.woff2" as="font" crossorigin />
</head>

<body>
  <!-- All visible content goes here -->
  <h1>Hello World</h1>

  <!-- Scripts at bottom for performance -->
  <script src="app.js" defer></script>
</body>
</html>

The <head> Element

The <head> contains metadata — information about the page, not displayed content.

📌 All valid <head> children
ElementPurpose
<title>Tab title, bookmark name, search result headline
<meta>Metadata (charset, viewport, SEO, social)
<link>External resources (CSS, favicon, preload, canonical)
<style>Embedded CSS
<script>JavaScript (inline or external)
<noscript>Fallback content when JS is disabled
<base>Base URL for relative links
<template>Inert HTML template for Web Components
Text & Semantics

Semantic HTML means using elements that convey the meaning of content, not just its appearance. This benefits SEO, accessibility, and maintainability.

Headings Hierarchy

HTML
<h1>Page Title — only ONE per page</h1>
<h2>Major Section</h2>
<h3>Sub-section</h3>
<h4>Sub-sub-section</h4>
<h5>Rarely needed</h5>
<h6>Very rarely needed</h6>
💡 TipDon't skip heading levels for visual styling. Use CSS classes instead. Screen readers use headings as a navigation map.

Inline Text Elements

ElementMeaningRenders as
<strong>Strong importancebold
<em>Stress emphasisitalic
<b>Stylistically bold (no extra importance)bold
<i>Alternative voice / idiom / termitalic
<mark>Highlighted / search resulthighlighted
<del>Deleted textdeleted
<ins>Inserted textinserted
<sub>SubscriptH2O
<sup>Superscriptx2
<code>Inline codeconsole.log()
<pre>Preformatted (preserves whitespace)code blocks
<kbd>Keyboard inputCtrl+S
<samp>Sample program outputError 404
<var>Variable in math/programmingx
<abbr>Abbreviation with tooltipHTML
<cite>Title of a creative workMDN Web Docs
<q>Inline quotationThe Web is for everyone.
<time>Date/time with machine-readable value
<small>Fine print / side comments© 2025
<s>No longer accurate (strikethrough)$99
<u>Unarticulated annotation (underline)proper noun
<bdi>Bidirectional isolationfor RTL text mixing
<bdo>Bidirectional overridereversed
<ruby>, <rt>, <rp>Ruby annotations (East Asian typography)漢(kan)
<wbr>Optional line-break opportunityVeryLongWord
<span>Generic inline container (no semantics)for CSS/JS hooks
<br>Line break↵ new line
<hr>Thematic break

Block Text Elements

HTML
<p>A paragraph of text.</p>

<!-- Block quotation with citation -->
<blockquote cite="https://source.com">
  <p>The best way to predict the future is to invent it.</p>
  <footer>— <cite>Alan Kay</cite></footer>
</blockquote>

<!-- Address contact info for author/owner -->
<address>
  Written by <a href="mailto:[email protected]">Author Name</a>
</address>

<!-- Thematic break -->
<hr />

<!-- Generic block container -->
<div class="wrapper">...</div>
Lists
HTML — All List Types
<!-- Unordered list -->
<ul>
  <li>Apples</li>
  <li>Bananas</li>
  <li>Nested list:
    <ul><li>Sub-item</li></ul>
  </li>
</ul>

<!-- Ordered list with custom start and type -->
<ol start="3" type="A" reversed>
  <li>Step three</li>
  <li value="10">Jump to item 10</li>
</ol>

<!-- Description list — terms and definitions -->
<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language — structure of the web.</dd>

  <dt>CSS</dt>
  <dd>Cascading Style Sheets — appearance of the web.</dd>
</dl>

<!-- Menu (list of commands — spec usage) -->
<menu>
  <li><button>Cut</button></li>
  <li><button>Copy</button></li>
</menu>
Images & Figures
HTML — Images
<!-- Basic image — alt is MANDATORY for accessibility -->
<img
  src="photo.jpg"
  alt="A golden retriever sitting in a park"
  width="800"
  height="600"
  loading="lazy"
  decoding="async"
/>

<!-- Figure with caption -->
<figure>
  <img src="chart.png" alt="Bar chart showing Q3 revenue growth" />
  <figcaption>Figure 1: Q3 2024 Revenue Growth by Region</figcaption>
</figure>

<!-- Decorative image (empty alt = skip by screen reader) -->
<img src="divider.svg" alt="" role="presentation" />

<!-- Image map with clickable regions -->
<img src="map.jpg" alt="World map" usemap="#worldmap" />
<map name="worldmap">
  <area shape="rect" coords="0,0,200,100" href="/north-america" alt="North America" />
  <area shape="circle" coords="300,150,50" href="/europe" alt="Europe" />
</map>
ℹ️ alt text rulesInformative images: describe what the image shows and why it's there. Decorative images: use alt="". Functional images (buttons/links): describe the action. Complex images (charts): describe the data or link to a text alternative.
Tables

Tables are for tabular data — rows and columns of related information. Never use them for page layout.

HTML — Full Accessible Table
<table>
  <!-- Caption: acts as the table's heading -->
  <caption>Monthly Sales Data — Q1 2025</caption>

  <!-- Column group styling hooks -->
  <colgroup>
    <col span="1" style="background:#f0f"/>
    <col span="3" />
  </colgroup>

  <!-- Table head -->
  <thead>
    <tr>
      <th scope="col">Month</th>
      <th scope="col">Revenue</th>
      <th scope="col">Units</th>
    </tr>
  </thead>

  <!-- Table body -->
  <tbody>
    <tr>
      <th scope="row">January</th>
      <td>$12,400</td>
      <td>248</td>
    </tr>
    <tr>
      <!-- colspan / rowspan for merged cells -->
      <td colspan="2">Merged cell</td>
      <td rowspan="2">Spans 2 rows</td>
    </tr>
  </tbody>

  <!-- Table foot — totals / summaries -->
  <tfoot>
    <tr>
      <th scope="row">Total</th>
      <td>$37,200</td>
      <td>744</td>
    </tr>
  </tfoot>
</table>
Forms

Forms are the primary way users send data to a server. Every form element needs a <label> for accessibility.

HTML — Form Structure
<form
  action="/submit"
  method="post"
  enctype="multipart/form-data"
  novalidate
  autocomplete="on"
>
  <!-- Fieldset groups related controls -->
  <fieldset>
    <legend>Personal Information</legend>

    <!-- Label explicitly linked via for/id -->
    <label for="name">Full Name</label>
    <input type="text" id="name" name="full_name"
           required minlength="2" maxlength="80"
           autocomplete="name"
           placeholder="Jane Smith" />

    <!-- Helper text linked via aria-describedby -->
    <label for="email">Email</label>
    <input type="email" id="email" name="email"
           required aria-describedby="email-hint" />
    <small id="email-hint">We'll never share your email.</small>

    <!-- Select dropdown -->
    <label for="country">Country</label>
    <select id="country" name="country">
      <optgroup label="Americas">
        <option value="us">United States</option>
      </optgroup>
    </select>

    <!-- Textarea -->
    <label for="bio">Bio</label>
    <textarea id="bio" name="bio"
              rows="4" cols="50"
              maxlength="500"></textarea>

    <!-- Datalist for autocomplete suggestions -->
    <input list="browsers" name="browser" />
    <datalist id="browsers">
      <option value="Chrome"/><option value="Firefox"/>
    </datalist>

  </fieldset>

  <!-- Hidden field -->
  <input type="hidden" name="csrf_token" value="abc123" />

  <!-- Buttons -->
  <button type="submit">Submit</button>
  <button type="reset">Clear</button>
  <button type="button" onclick="saveDraft()">Save Draft</button>
</form>

Live Form Demo

Interactive Example
Input Types

HTML5 introduced many semantic input types that trigger appropriate keyboards on mobile and enable built-in validation.

All HTML Input Types — Live
HTML — All Input Types
<input type="text"     />  <!-- default -->
<input type="email"    />  <!-- validates email format -->
<input type="password" />  <!-- masks input -->
<input type="number"   />  <!-- numeric keyboard on mobile -->
<input type="tel"      />  <!-- phone keyboard on mobile -->
<input type="url"      />  <!-- validates URL format -->
<input type="search"   />  <!-- search field with clear button -->
<input type="date"     />  <!-- date picker -->
<input type="time"     />  <!-- time picker -->
<input type="datetime-local" />
<input type="month"    />
<input type="week"     />
<input type="color"    />  <!-- colour picker -->
<input type="range"    min="0" max="100" step="1" />
<input type="checkbox" />
<input type="radio"    name="group" />
<input type="file"     accept="image/*" multiple />
<input type="hidden"   value="token" />
<input type="submit"   value="Send" />
<input type="reset"    />
<input type="button"   value="Click" />
<input type="image"    src="btn.png" alt="Submit" />
Form Validation
HTML — Built-in Validation Attributes
<input type="text"
  required                    <!-- Field must be filled -->
  minlength="3"              <!-- Min char count -->
  maxlength="60"             <!-- Max char count -->
  pattern="[A-Za-z\s]+"      <!-- Regex pattern -->
  title="Letters only please" <!-- Error tooltip hint -->
/>

<input type="number"
  min="1"
  max="100"
  step="5"
/>

<!-- Custom error messages via JavaScript -->
<script>
  const input = document.querySelector('input');
  input.addEventListener('invalid', (e) => {
      e.target.setCustomValidity('Please enter your full name.');
    });
  input.addEventListener('input', (e) => {
      e.target.setCustomValidity('');
    });
</script>

Pseudo-classes for Styled Validation

CSS
input:valid   { border-color: green; }
input:invalid { border-color: red; }
input:required { outline: 2px solid gold; }
input:optional { }
input:in-range { }
input:out-of-range { }
input:placeholder-shown { }
:user-valid    { } /* Only shows after user interaction */
:user-invalid  { } /* Better UX than :invalid */
Audio & Video
HTML — Video
<video
  src="movie.mp4"
  width="800"
  height="450"
  controls               <!-- Show browser controls -->
  autoplay               <!-- Auto-play (muted required) -->
  muted                  <!-- Required for autoplay -->
  loop                   <!-- Loop playback -->
  playsinline            <!-- No full-screen on iOS -->
  preload="metadata"     <!-- none | metadata | auto -->
  poster="thumbnail.jpg" <!-- Shown before play -->
  crossorigin="anonymous"
>
  <!-- Multiple sources for browser support -->
  <source src="movie.av1.mp4"  type="video/mp4; codecs=av01"/>
  <source src="movie.h264.mp4" type="video/mp4"/>
  <source src="movie.webm"     type="video/webm"/>

  <!-- Subtitles / closed captions -->
  <track kind="subtitles"    src="subs.en.vtt" srclang="en" label="English" default/>
  <track kind="captions"     src="cc.en.vtt"   srclang="en" label="CC English"/>
  <track kind="descriptions" src="desc.vtt"     srclang="en"/>
  <track kind="chapters"     src="chapters.vtt" srclang="en"/>
  <track kind="metadata"     src="data.vtt"/>

  Your browser does not support the video element.
</video>

<!-- Audio -->
<audio controls preload="none">
  <source src="audio.ogg"  type="audio/ogg"/>
  <source src="audio.mp3"  type="audio/mpeg"/>
  <source src="audio.opus" type="audio/ogg; codecs=opus"/>
</audio>
Responsive Images
HTML — <picture>, srcset, sizes
<!-- Art direction: different crops per breakpoint -->
<picture>
  <!-- WebP format with art direction -->
  <source
    media="(max-width: 600px)"
    srcset="hero-mobile.webp"
    type="image/webp"
  />
  <source
    media="(min-width: 601px)"
    srcset="hero-desktop.webp"
    type="image/webp"
  />
  <!-- Fallback img -->
  <img src="hero.jpg" alt="Hero image" />
</picture>

<!-- Density / resolution switching -->
<img
  src="logo.png"
  srcset="logo.png 1x, [email protected] 2x, [email protected] 3x"
  alt="Company Logo"
/>

<!-- Width-based srcset with sizes hint -->
<img
  src="photo-800.jpg"
  srcset="
    photo-400.jpg  400w,
    photo-800.jpg  800w,
    photo-1200.jpg 1200w,
    photo-1600.jpg 1600w
  "
  sizes="
    (max-width: 600px)  100vw,
    (max-width: 1200px) 50vw,
    800px
  "
  alt="Responsive photo"
  loading="lazy"
/>
iFrame & Embedded Content
HTML — iFrame
<!-- Basic iframe -->
<iframe
  src="https://example.com"
  title="Example page"    <!-- REQUIRED for accessibility -->
  width="800"
  height="500"
  loading="lazy"
  sandbox="allow-scripts allow-same-origin"
  referrerpolicy="no-referrer"
  allowfullscreen
></iframe>

<!-- YouTube embed -->
<iframe
  src="https://www.youtube.com/embed/VIDEO_ID?rel=0"
  title="YouTube video player"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
  allowfullscreen
></iframe>

<!-- sandbox values -->
<!-- allow-scripts       — run JS -->
<!-- allow-same-origin   — treat as same origin -->
<!-- allow-forms         — submit forms -->
<!-- allow-popups        — open new windows -->
<!-- allow-top-navigation — navigate parent -->
<!-- allow-downloads     — trigger file downloads -->

<!-- Object (legacy) -->
<object data="file.pdf" type="application/pdf" width="600" height="400">
  <p>PDF not supported. <a href="file.pdf">Download it.</a></p>
</object>
SVG — Scalable Vector Graphics

SVG is an XML-based vector format that can be embedded directly in HTML. SVGs are resolution-independent, scriptable, and styleable with CSS.

SVG — Core Elements
<svg
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 200 200"
  width="200" height="200"
  role="img"
  aria-label="Geometric shapes demo"
>
  <title>Geometric shapes demo</title>

  <!-- Basic shapes -->
  <circle    cx="50"  cy="50"  r="40"              fill="#4fc3f7" />
  <rect      x="110" y="10" width="80" height="80"  fill="#e8c547" rx="8" />
  <ellipse   cx="50"  cy="150" rx="40" ry="25"    fill="#f06292" />
  <line      x1="110" y1="110" x2="190" y2="190" stroke="white" stroke-width="3" />
  <polygon   points="150,110 190,190 110,190"     fill="#4ade80" />
  <polyline  points="0,200 30,150 60,180 90,120" stroke="orange" fill="none" />

  <!-- Path — the most powerful shape -->
  <path d="M10,80 Q95,10 180,80 T350,80" stroke="white" fill="none" />

  <!-- Text -->
  <text x="100" y="195" text-anchor="middle" fill="white" font-size="12">SVG</text>

  <!-- Gradient definition + usage -->
  <defs>
    <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%"   stop-color="#e8c547"/>
      <stop offset="100%" stop-color="#f06292"/>
    </linearGradient>
    <filter id="blur"><feGaussianBlur stdDeviation="3"/></filter>
    <clipPath id="clip"><circle cx="100" cy="100" r="50"/></clipPath>
  </defs>

  <!-- SVG Animation -->
  <circle cx="100" cy="100" r="20" fill="url(#grad)">
    <animate attributeName="r" values="20;30;20" dur="2s" repeatCount="indefinite"/>
  </circle>
</svg>
Live SVG Demo
SVG — Inline, Accessible, Animatable
Canvas 2D API

The <canvas> element provides a pixel-based drawing surface. Drawing is done entirely via JavaScript using the Canvas 2D API.

HTML + JS — Canvas 2D
<canvas id="myCanvas" width="600" height="400"
        role="img" aria-label="Animated wave chart">
  Canvas not supported.  <!-- Fallback -->
</canvas>

<script>
  const canvas = document.getElementById('myCanvas');
  const ctx = canvas.getContext('2d');

  // Fill & stroke
  ctx.fillStyle = '#e8c547';
  ctx.fillRect(10, 10, 100, 50);

  // Path drawing
  ctx.beginPath();
  ctx.moveTo(200, 50);
  ctx.lineTo(300, 150);
  ctx.arcTo(350, 150, 350, 100, 30);
  ctx.closePath();
  ctx.strokeStyle = '#4fc3f7';
  ctx.lineWidth = 3;
  ctx.stroke();

  // Gradient
  const grad = ctx.createLinearGradient(0,0,600,0);
  grad.addColorStop(0, '#e8c547');
  grad.addColorStop(1, '#f06292');
  ctx.fillStyle = grad;
  ctx.fillRect(0, 200, 600, 20);

  // Text
  ctx.font = 'bold 24px Syne';
  ctx.fillStyle = '#fff';
  ctx.fillText('Canvas 2D', 10, 250);

  // Image drawing
  const img = new Image();
  img.src = 'photo.jpg';
  img.onload = () => ctx.drawImage(img, 400, 0, 200, 150);

  // Transform
  ctx.save();
  ctx.translate(100, 300);
  ctx.rotate(Math.PI / 4);
  ctx.fillRect(-25, -25, 50, 50);
  ctx.restore();

  // Animation loop
  let frame = 0;
  function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      frame++;
      // draw frame...
      requestAnimationFrame(animate);
    }
  animate();
</script>
Live Canvas 2D — Animated Wave
WebGL

WebGL provides a low-level GPU-accelerated 3D graphics API inside <canvas>. It is based on OpenGL ES and uses GLSL shaders.

HTML + WebGL
<canvas id="glCanvas" width="640" height="480"></canvas>

<script>
  const gl = canvas.getContext('webgl2')   // WebGL 2
              ?? canvas.getContext('webgl'); // fallback

  // Vertex Shader (runs per vertex on GPU)
  const vsSource = `
    attribute vec4 aPosition;
    uniform   mat4 uModelViewProjection;
    void main() {
        gl_Position = uModelViewProjection * aPosition;
      }
  `;

  // Fragment Shader (runs per pixel on GPU)
  const fsSource = `
    precision mediump float;
    uniform   vec4 uColor;
    void main() {
        gl_FragColor = uColor;
      }
  `;

  // Compile shader
  function compileShader(gl, type, source) {
    const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
    return shader;
    }

  // Buffer upload, link program, draw call…
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 3);

  // Key WebGL concepts:
  // VBO  — Vertex Buffer Object (geometry on GPU)
  // VAO  — Vertex Array Object (attribute layout)
  // EBO  — Element Buffer Object (index buffer)
  // FBO  — Framebuffer Object (off-screen render)
  // UBO  — Uniform Buffer Object (WebGL2)
  // SSBO — Shader Storage Buffer (WebGL2 ext)
</script>
Live WebGL — Rotating Gradient Triangle
ℹ️ WebGL LibrariesConsider Three.js, Babylon.js, or Regl for higher-level WebGL. Raw WebGL is powerful but verbose — these abstractions handle shader compilation, scene graphs, and asset loading.
HTML5 Semantic Elements

HTML5 introduced landmark elements that describe the purpose of page regions, enabling better accessibility, SEO, and browser features.

HTML — Complete Page Layout
<body>
  <!-- ❶ Site header -->
  <header>
    <nav aria-label="Primary">…</nav>
  </header>

  <!-- ❷ Skip link for keyboard users -->
  <a href="#main-content" class="skip-link">Skip to main content</a>

  <!-- ❸ Main content landmark -->
  <main id="main-content">

    <!-- Article: self-contained composable unit -->
    <article>
      <header>
        <h1>Article Title</h1>
        <p>By <address><a href="mailto:[email protected]">Author</a></address></p>
        <time datetime="2025-06-01">June 1, 2025</time>
      </header>

      <!-- Section: thematic grouping inside article -->
      <section aria-labelledby="intro-heading">
        <h2 id="intro-heading">Introduction</h2>
        <p>Content…</p>
      </section>

      <footer><p>Published by…</p></footer>
    </article>

    <!-- Aside: tangentially related content -->
    <aside aria-label="Related articles">
      <h2>Also Read</h2>
      …
    </aside>

  </main>

  <!-- ❹ Site footer -->
  <footer>
    <nav aria-label="Footer navigation">…</nav>
    <p>© 2025 My Company</p>
  </footer>
</body>

Full Semantic Element Reference

ElementARIA LandmarkUse Case
<header>banner (if top-level)Introductory content, navigation branding
<nav>navigationNavigation link groups
<main>mainPrimary unique content — ONE per page
<article>articleSelf-contained composable unit (blog post, product card)
<section>region (if labelled)Thematic grouping with a heading
<aside>complementaryRelated but tangential content (sidebar, callout)
<footer>contentinfo (if top-level)Footer for its nearest sectioning ancestor
<search>searchSearch form wrapper (HTML 2023)
<figure>figureReferenced media with optional caption
<figcaption>—Caption for <figure>
<hgroup>—Heading + sub-heading group
ARIA & Accessibility

ARIA (Accessible Rich Internet Applications) attributes extend HTML semantics for assistive technologies. The first rule of ARIA: don't use ARIA if native HTML semantics work.

ARIA Roles

HTML — Key ARIA Patterns
<!-- Live region: announces dynamic content to screen readers -->
<div role="status" aria-live="polite"   aria-atomic="true"></div>
<div role="alert"  aria-live="assertive"                  ></div>

<!-- Modal dialog -->
<div role="dialog" aria-modal="true"
     aria-labelledby="dlg-title" aria-describedby="dlg-desc">
  <h2 id="dlg-title">Confirm Action</h2>
  <p  id="dlg-desc">Are you sure?</p>
</div>

<!-- Tab widget -->
<div role="tablist" aria-label="Settings">
  <button role="tab" aria-selected="true"  aria-controls="panel-1">General</button>
  <button role="tab" aria-selected="false" aria-controls="panel-2">Privacy</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">…</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>…</div>

<!-- Toggle button -->
<button aria-pressed="false">Dark Mode</button>

<!-- Expandable menu -->
<button aria-expanded="false" aria-controls="submenu">Products ▾</button>
<ul id="submenu" hidden>…</ul>

<!-- Combobox / autocomplete -->
<input role="combobox" aria-expanded="true"
       aria-autocomplete="list" aria-controls="results-list" />

<!-- Visually hidden but accessible text -->
<span class="sr-only">Loading, please wait…</span>
<!-- CSS: .sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); } -->

<!-- aria-hidden: hide from AT but keep visible -->
<span aria-hidden="true">★★★☆☆</span>
<span class="sr-only">3 out of 5 stars</span>

Live ARIA Tab Demo

Accessible Tab Widget

HTML structure uses semantic elements like <header>, <main>, <article>, and <footer> to describe page regions meaningfully.

ARIA Properties Reference

AttributeValuesPurpose
aria-labelstringName when no visible label exists
aria-labelledbyid refPoints to element that is the label
aria-describedbyid refPoints to description element
aria-hiddentrue/falseRemove from accessibility tree
aria-liveoff/polite/assertiveAnnounce dynamic updates
aria-atomictrue/falseRead whole region on change
aria-expandedtrue/falseDisclosure widget open/closed state
aria-selectedtrue/falseSelection state (tabs, listbox)
aria-pressedtrue/false/mixedToggle button state
aria-checkedtrue/false/mixedCheckbox / switch state
aria-disabledtrue/falseSemantically disabled
aria-requiredtrue/falseField is required
aria-invalidtrue/false/grammar/spellingValidation failure
aria-currentpage/step/location/date/time/trueCurrent item in set
aria-sortascending/descending/none/otherColumn sort direction
aria-posinsetintegerPosition in set
aria-setsizeintegerSize of set (-1 = unknown)
aria-levelintegerHierarchical level
aria-valuemin/max/now/textnumber/stringRange widget values
aria-controlsid refElement this one controls
aria-ownsid refDOM child relationship override
aria-flowtoid refNext element in reading order
aria-modaltrue/falseDialog is a modal
aria-busytrue/falseContent is loading
aria-keyshortcutsstringKeyboard shortcut for element
aria-roledescriptionstringCustom role description
aria-placeholderstringHint text for empty field
aria-errormessageid refPoints to error message element
SEO & Meta Tags
HTML — Complete SEO Head
<head>
  <!-- ── Core ── -->
  <meta charset="UTF-8"/>
  <title>Primary Keyword — Brand Name | Max ~60 chars</title>
  <meta name="description" content="Compelling summary with keywords. Max 155-160 chars for Google."/>
  <meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large"/>
  <meta name="author" content="Author Name"/>
  <link rel="canonical" href="https://example.com/this-page"/>

  <!-- ── Open Graph (Facebook, LinkedIn, WhatsApp) ── -->
  <meta property="og:type"        content="article"/>
  <meta property="og:title"       content="Page Title"/>
  <meta property="og:description" content="Share description"/>
  <meta property="og:url"         content="https://example.com/page"/>
  <meta property="og:image"       content="https://example.com/og.jpg"/>
  <meta property="og:image:width" content="1200"/>
  <meta property="og:image:height"content="630"/>
  <meta property="og:site_name"   content="Brand Name"/>
  <meta property="og:locale"      content="en_US"/>

  <!-- ── Twitter Card ── -->
  <meta name="twitter:card"        content="summary_large_image"/>
  <meta name="twitter:site"        content="@YourHandle"/>
  <meta name="twitter:title"       content="Page Title"/>
  <meta name="twitter:description" content="Tweet description"/>
  <meta name="twitter:image"       content="https://example.com/card.jpg"/>

  <!-- ── JSON-LD Structured Data ── -->
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "Page Title",
    "author": { "@type": "Person", "name": "Jane Smith" },
    "datePublished": "2025-06-01",
    "image": "https://example.com/image.jpg"
  }
  </script>

  <!-- ── Hreflang for multilingual sites ── -->
  <link rel="alternate" hreflang="en" href="https://example.com/en/"/>
  <link rel="alternate" hreflang="fr" href="https://example.com/fr/"/>
  <link rel="alternate" hreflang="x-default" href="https://example.com/"/>
</head>

Google Search Preview

What users see in Google
https://example.com › html-course
Master HTML Course — Complete Guide | PromptCraft
Learn every HTML concept from foundations to WebGL. Covers semantics, forms, media, ARIA, SEO, Canvas and more. Perfect for beginners to advanced developers.
Modern HTML Elements
HTML — dialog, details, popover, output
<!-- Native Dialog (modal) -->
<dialog id="my-dialog">
  <h2>Dialog Title</h2>
  <p>Dialog content with backdrop support.</p>
  <button onclick="this.closest('dialog').close()">Close</button>
</dialog>
<button onclick="document.getElementById('my-dialog').showModal()">Open Dialog</button>

<!-- Details / Summary — native accordion -->
<details open>
  <summary>Click to toggle</summary>
  <p>Hidden content revealed on click. No JS needed!</p>
</details>

<!-- Popover API (2024) — No JS needed for basic use -->
<button popovertarget="my-popover">Show Popover</button>
<div id="my-popover" popover>
  <p>Popover content. Click outside to dismiss.</p>
</div>

<!-- Output — result of a calculation -->
<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="number" id="a" value="0"/> +
  <input type="number" id="b" value="0"/> =
  <output name="result" for="a b">0</output>
</form>

<!-- Progress and Meter -->
<progress value="70" max="100">70%</progress>

<meter value="0.6" min="0" max="1"
       low="0.25" high="0.75" optimum="0.8">
  60% disk used
</meter>

Live Demo

dialog, details, progress, meter — all native HTML

Native Accordion (no JS)
This entire toggle is driven by native HTML with zero JavaScript. The <details> element has been in browsers for years!

Native HTML Dialog

This is a <dialog> element — a native modal with a backdrop, focus trap, and Escape-to-close. No library needed.

Web Components

Web Components are a suite of standards for building reusable, encapsulated custom HTML elements.

HTML + JS — Custom Element
<!-- ① Usage in HTML -->
<user-card
  name="Jane Smith"
  role="Developer"
  avatar="jane.jpg"
></user-card>

<!-- ② Definition -->
<template id="user-card-template">
  <style>
    /* Styles are encapsulated — don't leak out */
    :host { display: block; padding: 16px; border-radius: 8px; }
    .name { font-weight: bold; }
  </style>
  <img class="avatar" alt=""/>
  <div class="name"></div>
  <div class="role"></div>
  <!-- Slot: allows parent to inject content -->
  <slot name="bio"></slot>
</template>

<script>
class UserCard extends HTMLElement {
  // Attributes to observe for changes
  static get observedAttributes() {
    return ['name', 'role', 'avatar'];
    }

  constructor() {
        super();
        // Attach Shadow DOM
        this.attachShadow({ mode: 'open' });
    const tmpl = document.getElementById('user-card-template');
        this.shadowRoot.appendChild(tmpl.content.cloneNode(true));
      }

  // Lifecycle callbacks
  connectedCallback()    { this.render(); }  // Added to DOM
  disconnectedCallback() { }                 // Removed from DOM
  adoptedCallback()      { }                 // Moved to new document
  attributeChangedCallback(name, old, next) { this.render(); }

  render() {
        this.shadowRoot.querySelector('.name').textContent = this.getAttribute('name');
        this.shadowRoot.querySelector('.role').textContent = this.getAttribute('role');
        this.shadowRoot.querySelector('.avatar').src = this.getAttribute('avatar');
      }
}

// Register the custom element
customElements.define('user-card', UserCard);
</script>
Performance & Loading
HTML — Resource Hints & Loading
<head>
  <!-- Preconnect: early TCP+TLS handshake to origin -->
  <link rel="preconnect" href="https://fonts.googleapis.com"/>
  <link rel="preconnect" href="https://cdn.example.com" crossorigin/>

  <!-- DNS Prefetch: cheaper than preconnect -->
  <link rel="dns-prefetch" href="https://analytics.example.com"/>

  <!-- Preload: fetch critical resource before parser finds it -->
  <link rel="preload" href="hero.jpg"   as="image"/>
  <link rel="preload" href="font.woff2" as="font" crossorigin/>
  <link rel="preload" href="critical.css"as="style"/>

  <!-- Prefetch: fetch next-page resource in idle time -->
  <link rel="prefetch" href="/next-page.html"/>

  <!-- Speculation Rules API (Chrome 2023) -->
  <script type="speculationrules">
  { "prerender": [{ "source": "list", "urls": ["/dashboard"] }] }
  </script>
</head>

<body>
  <!-- LCP image: eager load, priority fetch -->
  <img src="hero.jpg" alt="Hero"
       loading="eager"
       fetchpriority="high"
       decoding="sync"
  />

  <!-- Below-fold images: lazy load -->
  <img src="below-fold.jpg" alt="…"
       loading="lazy"
       decoding="async"
  />

  <!-- Script loading strategies -->
  <script src="app.js"      defer></script>    <!-- parse HTML, execute after -->
  <script src="widget.js"   async></script>    <!-- fetch in parallel, execute ASAP -->
  <script src="module.js"   type="module"></script><!-- ESM: deferred by default -->
  <script src="worker-hint.js" blocking="render"></script>
</body>
⚡

defer

Script downloads in parallel, executes after HTML is fully parsed. Order preserved. Use for most scripts.

🔀

async

Downloads in parallel, executes immediately when ready. No order guarantee. Best for independent analytics.

📦

type="module"

ES Modules. Deferred by default. Enables import/export syntax. Always strict mode. CORS required.

🖼️

loading="lazy"

Browser-native lazy loading for images and iframes. Loads only when near the viewport.

HTML APIs

Drag & Drop

HTML — Drag & Drop
<!-- Draggable source -->
<div draggable="true"
     ondragstart="e.dataTransfer.setData('text/plain', 'Hello')">
  Drag me!
</div>

<!-- Drop target -->
<div ondragover="event.preventDefault()"
     ondrop="e.target.textContent = e.dataTransfer.getData('text/plain')">
  Drop here
</div>

Content Editable

HTML — contenteditable
<!-- Any element can become editable -->
<article
  contenteditable="true"
  spellcheck="true"
  role="textbox"
  aria-multiline="true"
  aria-label="Edit article content"
>
  Click to edit this paragraph…
</article>

<!-- execCommand (legacy but still used) -->
<button onclick="document.execCommand('bold')">Bold</button>

Other Notable HTML APIs

FeatureHow to use
Web StoragelocalStorage.setItem('key', val) / sessionStorage
History APIhistory.pushState({}, '', '/new-url')
Geolocationnavigator.geolocation.getCurrentPosition(cb)
Clipboardnavigator.clipboard.writeText('text')
NotificationsNotification.requestPermission()
Vibrationnavigator.vibrate([200,100,200])
Batterynavigator.getBattery()
Sharenavigator.share({ title, text, url })
fullscreenel.requestFullscreen() / document.exitFullscreen()
Picture-in-Picturevideo.requestPictureInPicture()
Screen Wake Locknavigator.wakeLock.request('screen')
Intersection Observernew IntersectionObserver(cb, opts)
ResizeObservernew ResizeObserver(cb)
MutationObservernew MutationObserver(cb)
Web Workersnew Worker('worker.js')
Service Workersnavigator.serviceWorker.register('sw.js')
IndexedDBindexedDB.open('myDB', 1)
File APIinput.files[0].arrayBuffer()
Broadcast Channelnew BroadcastChannel('tab-sync')
Best Practices & Checklist
🏗️

Structure First

Write semantic HTML before adding CSS or JS. Your HTML alone should make sense.

♿

Accessibility

Test with a keyboard only. Run axe or WAVE. Add alt text, labels, skip links, and ARIA where needed.

📱

Mobile First

Include viewport meta tag. Use responsive images. Test on real devices.

⚡

Performance

Lazy-load below-fold images. Defer non-critical JS. Preload LCP image. Use modern formats (WebP, AVIF).

🔒

Security

Sanitize user input before inserting to DOM. Use sandbox on iframes. Set rel="noopener" on external links.

🔍

SEO

One H1 per page. Descriptive title + meta desc. Canonical URLs. JSON-LD structured data. Valid HTML.

HTML Validation Checklist

Checklist
✅ DOCTYPE declaration present
✅ <html lang="…"> set correctly
✅ <meta charset="UTF-8"> is first in <head>
✅ Viewport meta tag present
✅ <title> is descriptive and unique per page
✅ Meta description is present (150-160 chars)
✅ One <h1> per page, headings in order
✅ All images have alt attributes
✅ All inputs have associated <label> elements
✅ External links have rel="noopener noreferrer"
✅ iframes have title attributes
✅ Color contrast ratio ≥ 4.5:1 (WCAG AA)
✅ Interactive elements are keyboard-reachable
✅ Skip link provided for keyboard users
✅ Form errors associated with inputs via aria-describedby
✅ Canonical URL set in <head>
✅ Open Graph tags present
✅ Favicon provided (at minimum 32×32 and 180×180)
✅ Scripts use defer or are at end of <body>
✅ No deprecated elements (center, font, frame, etc.)
✅ HTML validates at validator.w3.org

Deprecated Elements — Never Use

<center> <font> <basefont> <big> <frame> <frameset> <noframes> <strike> <tt> <acronym> <applet> <dir> <marquee> <bgsound>
🎓 Keep LearningHTML is a living standard — new elements and APIs ship regularly. Follow WHATWG (html.spec.whatwg.org) and MDN Web Docs (developer.mozilla.org) to stay current.

Was this guide helpful?

Your feedback helps us continuously improve our developer docs.

Explore More Docs →