Semantic Elements
Document Structure
HTML5 introduced semantic elements that describe their meaning to both browser and developer. header, nav, main, article, aside, footer define document structure. DOCTYPE html triggers standards mode, lang improves accessibility and SEO, and charset UTF-8 is required for proper encoding.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<header>Header content</header>
<nav>Navigation</nav>
<main>
<article>Article content</article>
<aside>Sidebar</aside>
</main>
<footer>Footer</footer>
</body>
</html>Header & Footer
header represents introductory content (logos, titles, search forms) and may appear multiple times. footer holds ending content like copyright, links, or contact info. Both can be used within sectioning elements like article or section, not just at the page level.
<header>
<h1>Site Title</h1>
<p>Tagline</p>
</header>
<footer>
<nav>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<small>© 2024 Example</small>
</footer>Navigation Element
nav is reserved for major navigation blocks. Not every list of links needs nav—only groups significant for site navigation. Use aria-label to distinguish multiple nav elements (e.g., main vs breadcrumb). aria-current indicates the current page.
<nav aria-label="Main navigation">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
<li aria-current="page">Post</li>
</ol>
</nav>Main & Article
main wraps the dominant content of the page and should appear only once per page (mapped to the 'main' ARIA landmark). article is a self-contained composition—a blog post, news story, or widget—reusable independently. section groups thematically related content, always with a heading.
<body>
<header>Site header</header>
<main>
<article>
<h1>Blog Post Title</h1>
<p>Body content...</p>
<section>
<h2>Subsection</h2>
<p>More content</p>
</section>
</article>
</main>
</body>Section & Aside
section groups related content and should always include a heading. aside represents content tangentially related to the main content—sidebars, pull quotes, or ads. Both improve the document outline. Use aria-labelledby to give sections an accessible name.
<section aria-labelledby="features-heading">
<h2 id="features-heading">Features</h2>
<p>Feature description</p>
</section>
<aside aria-label="Related links">
<h2>Related</h2>
<ul>
<li><a href="/post-2">Next post</a></li>
</ul>
</aside>Figure & Figcaption
figure groups content (images, code listings, quotes) referenced from the main flow, with figcaption providing a caption. figcaption must be the first or last child. figure is not limited to images—it works for any self-contained content like code snippets or blockquotes.
<figure>
<img src="chart.png" alt="Sales chart showing growth">
<figcaption>Figure 1: Quarterly sales growth in 2024.</figcaption>
</figure>
<figure>
<blockquote>
<p>The best way to predict the future is to invent it.</p>
</blockquote>
<figcaption>— Alan Kay</figcaption>
</figure>Form Enhancements
New Input Types
HTML5 added input types like email, url, tel, date, time, color, range, number, month, week, and datetime-local. Browsers provide native validation and specialized UI (date pickers, color pickers). type=email/url trigger automatic format validation on form submission.
<form>
<label>Email: <input type="email" required></label>
<label>URL: <input type="url"></label>
<label>Phone: <input type="tel"></label>
<label>Date: <input type="date"></label>
<label>Time: <input type="time"></label>
<label>Color: <input type="color"></label>
<label>Range: <input type="range" min="0" max="100"></label>
<label>Number: <input type="number" min="0" step="0.01"></label>
<button>Submit</button>
</form>Datalist Autocomplete
datalist provides autocomplete suggestions for an input via the list attribute. Unlike select, users can type free-form text or pick a suggestion. Each option's value becomes a suggestion. datalist degrades gracefully on unsupported browsers as a plain text input.
<label>
Choose a browser:
<input list="browsers" name="browser">
</label>
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>Output Element
output represents the result of a calculation or user action. It has a value property accessible via JS and a for attribute referencing the inputs that contributed. It is a form-associated element, so its value is submitted with the form. Great for live calculators.
<form oninput="result.value = (+a.value + +b.value)">
<input type="number" name="a" value="0">
+
<input type="number" name="b" value="0">
=
<output name="result" for="a b">0</output>
</form>Progress & Meter
progress shows completion of a task (value/max); omit value for an indeterminate state. meter displays a scalar measurement within a known range, with low/high/optimum thresholds that affect its color. meter is read-only and not for progress indication.
<label>Uploading:
<progress value="70" max="100">70%</progress>
</label>
<label>Disk usage:
<meter value="0.6" min="0" max="1" low="0.4" high="0.8" optimum="0.2">
60%
</meter>
</label>
<!-- Indeterminate progress -->
<progress>Processing...</progress>Form Attribute & Fieldset
The form attribute associates an input, fieldset, or button with a form by id, even when the element is not nested inside it. fieldset groups related controls and legend provides a caption. The disabled attribute on fieldset disables all contained controls at once.
<form id="myForm" action="/submit" method="post"></form>
<!-- Input outside the form, but associated via form attribute -->
<label>
Name:
<input type="text" name="name" form="myForm" required>
</label>
<fieldset form="myForm" disabled>
<legend>Shipping Options</legend>
<label><input type="radio" name="ship" value="standard"> Standard</label>
<label><input type="radio" name="ship" value="express"> Express</label>
</fieldset>
<button type="submit" form="myForm">Submit</button>Placeholder & Autofocus
placeholder shows a hint inside the input and disappears on focus—it is not a replacement for a label. autofocus focuses the element on page load (use sparingly, one per page). autocomplete controls whether the browser remembers past values. title provides a tooltip but should not replace accessible labels.
<form>
<label>
Search:
<input type="search" name="q"
placeholder="Type to search..."
autofocus
autocomplete="off">
</label>
<label>
Hint text:
<input type="text" name="hint" title="Helpful tooltip">
</label>
<button type="submit">Go</button>
</form>Form Validation
Required Attribute
The boolean required attribute marks a field as mandatory; the browser blocks submission and shows an error bubble if it is empty. It works on all text, number, checkbox, radio, file, and select controls. Pair it with :invalid and :valid CSS pseudo-classes for visual feedback.
<form>
<label>
Email (required):
<input type="email" name="email" required>
</label>
<label>
Optional phone:
<input type="tel" name="phone">
</label>
<button>Submit</button>
</form>Pattern Validation
pattern accepts a JavaScript regular expression (no slashes) the value must match. Anchoring with ^ and $ is recommended. The title attribute gives users a hint on failure. Pattern is implicitly anchored for type=email/url but explicit for text-based inputs.
<form>
<label>
Product code:
<input type="text" name="code"
pattern="[A-Z]{3}-\d{4}"
title="Three letters, hyphen, four digits (e.g., ABC-1234)"
required>
</label>
<label>
Hex color:
<input type="text" name="color" pattern="^#[0-9A-Fa-f]{6}$">
</label>
<button>Submit</button>
</form>Min, Max & Step
min and max define the lower and upper bounds for numeric and date inputs. step specifies the increment; values must be min + n*step. step='any' allows any decimal. The browser rejects out-of-range values on submit and adjusts spinner clicks.
<form>
<label>
Quantity:
<input type="number" name="qty" min="1" max="99" step="1" value="1">
</label>
<label>
Price:
<input type="number" name="price" min="0" step="0.01">
</label>
<label>
Date range:
<input type="date" name="start" min="2024-01-01" max="2024-12-31">
</label>
<button>Submit</button>
</form>Minlength & Maxlength
minlength and maxlength constrain the number of characters for text inputs and textareas. minlength triggers validation only if the field has a value (combine with required for mandatory fields). maxlength hard-traps input beyond the limit, preventing typing.