HTML5
A comprehensive guide to HTML5 semantic elements, forms, media, accessibility, and modern document structure patterns.
HTML5 Cheatsheet
A comprehensive guide to HTML5 semantic elements, forms, media, accessibility, and modern document structure patterns.
Overview
HTML5 is the fifth major revision of the HyperText Markup Language, introducing semantic elements, native multimedia support, improved forms, and enhanced accessibility features for building modern, well-structured web documents.
graph TB
subgraph "HTML5 Core Features"
A[HTML5 Document] --> B[Semantic Structure]
A --> C[Forms & Validation]
A --> D[Media Elements]
A --> E[Graphics]
A --> F[Accessibility]
A --> G[Metadata & SEO]
B --> B1[header/footer]
B --> B2[nav/main]
B --> B3[article/section]
B --> B4[aside/figure]
C --> C1[Input Types]
C --> C2[Validation]
C --> C3[Attributes]
D --> D1[audio]
D --> D2[video]
D --> D3[picture]
E --> E1[Canvas]
E --> E2[SVG]
F --> F1[ARIA]
F --> F2[Roles]
F --> F3[Data Attributes]
end
Semantic Elements
Key Concepts
Semantic HTML5 elements provide meaning to the structure of web content, improving accessibility, SEO, and code maintainability. They replace generic <div> elements with descriptive tags that indicate the purpose of content.
graph TB
subgraph "Semantic Document Layout"
BODY[body] --> HEADER[header]
BODY --> NAV[nav]
BODY --> MAIN[main]
BODY --> FOOTER[footer]
MAIN --> ARTICLE[article]
MAIN --> SECTION[section]
MAIN --> ASIDE[aside]
ARTICLE --> FIGURE[figure]
FIGURE --> FIGCAPTION[figcaption]
end
Common Patterns
| Element | Purpose | Usage |
|---|---|---|
<header> |
Introductory content or navigation | Page header, article header |
<nav> |
Navigation links | Main menu, breadcrumbs, pagination |
<main> |
Main content (unique per page) | Primary content area |
<article> |
Self-contained content | Blog post, news article, comment |
<section> |
Thematic grouping | Chapters, tabbed content |
<aside> |
Tangentially related content | Sidebars, pull quotes, advertisements |
<footer> |
Footer information | Copyright, contact info, related links |
<figure> |
Self-contained media | Images, diagrams, code listings |
<figcaption> |
Caption for figure | Image descriptions |
Examples
Basic Page Structure
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<header>
<h1>Site Title</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h2>Article Title</h2>
<p>Published on <time datetime="2025-01-15">15 January 2025</time></p>
</header>
<section>
<h3>Introduction</h3>
<p>Article content goes here...</p>
</section>
<section>
<h3>Main Points</h3>
<p>More content...</p>
<figure>
<img src="diagram.png" alt="Explanatory diagram">
<figcaption>Figure 1: System architecture overview</figcaption>
</figure>
</section>
<footer>
<p>Author: Jane Smith</p>
</footer>
</article>
<aside>
<h3>Related Articles</h3>
<ul>
<li><a href="/article-2">Related Topic</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2025 Organisation Name. All rights reserved.</p>
<address>
Contact: <a href="mailto:info@example.com">info@example.com</a>
</address>
</footer>
</body>
</html>
Article with Multiple Sections
<article>
<header>
<h1>Understanding HTML5 Semantics</h1>
<p>A comprehensive guide to modern markup</p>
</header>
<section id="introduction">
<h2>Introduction</h2>
<p>HTML5 semantic elements improve document structure...</p>
</section>
<section id="benefits">
<h2>Benefits</h2>
<ul>
<li>Better accessibility</li>
<li>Improved SEO</li>
<li>Clearer code organisation</li>
</ul>
</section>
<section id="conclusion">
<h2>Conclusion</h2>
<p>Adopting semantic HTML improves web standards...</p>
</section>
</article>
Forms
Key Concepts
HTML5 forms introduce new input types, built-in validation, and attributes that reduce reliance on JavaScript for common form behaviours. Native validation provides better user experience and accessibility.
Input Types
| Type | Description | Example |
|---|---|---|
text |
Single-line text | <input type="text"> |
email |
Email address with validation | <input type="email"> |
password |
Masked text input | <input type="password"> |
number |
Numeric input with spinners | <input type="number" min="0" max="100"> |
range |
Slider control | <input type="range" min="0" max="100"> |
date |
Date picker | <input type="date"> |
time |
Time picker | <input type="time"> |
datetime-local |
Date and time picker | <input type="datetime-local"> |
month |
Month and year picker | <input type="month"> |
week |
Week picker | <input type="week"> |
tel |
Telephone number | <input type="tel"> |
url |
URL with validation | <input type="url"> |
search |
Search field | <input type="search"> |
color |
Colour picker | <input type="color"> |
file |
File upload | <input type="file" accept=".pdf,.doc"> |
hidden |
Hidden data | <input type="hidden" name="token"> |
checkbox |
Checkbox | <input type="checkbox"> |
radio |
Radio button | <input type="radio"> |
Validation Attributes
| Attribute | Description | Example |
|---|---|---|
required |
Field must be filled | <input required> |
pattern |
Regex pattern match | <input pattern="[A-Za-z]{3}"> |
min / max |
Minimum/maximum value | <input type="number" min="1" max="10"> |
minlength / maxlength |
Character limits | <input minlength="8" maxlength="20"> |
step |
Increment value | <input type="number" step="0.01"> |
multiple |
Allow multiple values | <input type="email" multiple> |
Form Attributes
| Attribute | Description | Example |
|---|---|---|
placeholder |
Hint text | <input placeholder="Enter name"> |
autofocus |
Focus on page load | <input autofocus> |
autocomplete |
Browser autocomplete | <input autocomplete="email"> |
readonly |
Read-only field | <input readonly> |
disabled |
Disabled field | <input disabled> |
form |
Associate with form | <input form="myform"> |
list |
Datalist reference | <input list="options"> |
novalidate |
Skip validation | <form novalidate> |
formnovalidate |
Skip validation on submit | <button formnovalidate> |
Examples
Complete Registration Form
<form action="/register" method="POST" id="registration">
<fieldset>
<legend>Personal Information</legend>
<div>
<label for="fullname">Full Name:</label>
<input type="text" id="fullname" name="fullname"
required minlength="2" maxlength="100"
placeholder="Enter your full name"
autocomplete="name">
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email"
required placeholder="you@example.com"
autocomplete="email">
</div>
<div>
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone"
pattern="[0-9]{11}"
placeholder="07123456789"
autocomplete="tel">
</div>
<div>
<label for="dob">Date of Birth:</label>
<input type="date" id="dob" name="dob"
min="1900-01-01" max="2010-12-31">
</div>
</fieldset>
<fieldset>
<legend>Account Details</legend>
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username"
required pattern="[a-zA-Z0-9_]{3,20}"
title="3-20 characters, letters, numbers, underscores only"
autocomplete="username">
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password"
required minlength="8"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="Must contain at least one number, one uppercase and lowercase letter, and at least 8 characters"
autocomplete="new-password">
</div>
<div>
<label for="website">Website:</label>
<input type="url" id="website" name="website"
placeholder="https://example.com">
</div>
</fieldset>
<fieldset>
<legend>Preferences</legend>
<div>
<label for="country">Country:</label>
<input type="text" id="country" name="country" list="countries">
<datalist id="countries">
<option value="United Kingdom">
<option value="United States">
<option value="Australia">
<option value="Canada">
</datalist>
</div>
<div>
<label for="experience">Experience Level:</label>
<input type="range" id="experience" name="experience"
min="1" max="10" value="5">
<output for="experience">5</output>
</div>
<div>
<label for="colour">Favourite Colour:</label>
<input type="color" id="colour" name="colour" value="#3498db">
</div>
<div>
<label>
<input type="checkbox" name="newsletter" value="yes">
Subscribe to newsletter
</label>
</div>
</fieldset>
<div>
<button type="submit">Register</button>
<button type="reset">Clear Form</button>
</div>
</form>
Search Form with Datalist
<form action="/search" method="GET">
<label for="search">Search:</label>
<input type="search" id="search" name="q"
list="suggestions" autofocus
placeholder="Search...">
<datalist id="suggestions">
<option value="HTML5">
<option value="CSS3">
<option value="JavaScript">
<option value="Web Components">
</datalist>
<button type="submit">Search</button>
</form>
Form with Output Element
<form oninput="result.value=parseInt(a.value)+parseInt(b.value)">
<input type="number" id="a" name="a" value="0"> +
<input type="number" id="b" name="b" value="0"> =
<output name="result" for="a b">0</output>
</form>
Media Elements
Key Concepts
HTML5 provides native support for audio and video playback without plugins. The <picture> element enables responsive images, while <source> elements specify multiple media resources for browser selection.
Audio Element
<!-- Basic audio -->
<audio src="audio.mp3" controls></audio>
<!-- Multiple sources with fallback -->
<audio controls preload="metadata">
<source src="audio.ogg" type="audio/ogg">
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.wav" type="audio/wav">
<p>Your browser does not support audio playback.</p>
</audio>
<!-- Audio with attributes -->
<audio controls autoplay loop muted>
<source src="background.mp3" type="audio/mpeg">
</audio>
Video Element
<!-- Basic video -->
<video src="video.mp4" controls width="640" height="360"></video>
<!-- Multiple sources with subtitles -->
<video controls width="800" height="450" poster="thumbnail.jpg" preload="metadata">
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
<source src="video.ogv" type="video/ogg">
<!-- Subtitles and captions -->
<track kind="subtitles" src="subs-en.vtt" srclang="en" label="English" default>
<track kind="subtitles" src="subs-fr.vtt" srclang="fr" label="Français">
<track kind="captions" src="captions.vtt" srclang="en" label="English Captions">
<p>Your browser does not support video playback.</p>
</video>
Picture Element (Responsive Images)
<!-- Art direction: different crops for different viewports -->
<picture>
<source media="(min-width: 1200px)" srcset="hero-large.jpg">
<source media="(min-width: 768px)" srcset="hero-medium.jpg">
<img src="hero-small.jpg" alt="Hero image description">
</picture>
<!-- Format selection: modern formats with fallback -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Image description">
</picture>
<!-- Combined: responsive with format selection -->
<picture>
<source media="(min-width: 1200px)"
srcset="large.avif" type="image/avif">
<source media="(min-width: 1200px)"
srcset="large.webp" type="image/webp">
<source media="(min-width: 1200px)"
srcset="large.jpg" type="image/jpeg">
<source media="(min-width: 768px)"
srcset="medium.webp" type="image/webp">
<source srcset="small.webp" type="image/webp">
<img src="small.jpg" alt="Responsive image"
loading="lazy" decoding="async">
</picture>
Media Attributes Reference
| Attribute | Elements | Description |
|---|---|---|
controls |
audio, video | Show playback controls |
autoplay |
audio, video | Start playing automatically |
loop |
audio, video | Loop playback |
muted |
audio, video | Mute audio |
preload |
audio, video | Preload hint: none, metadata, auto |
poster |
video | Preview image |
width / height |
video | Dimensions |
playsinline |
video | Play inline on mobile |
crossorigin |
audio, video | CORS settings |
Track Element Kinds
| Kind | Description |
|---|---|
subtitles |
Translations of dialogue |
captions |
Transcription including sound effects |
descriptions |
Text descriptions of video |
chapters |
Chapter titles for navigation |
metadata |
Machine-readable data |
Canvas and SVG Basics
Key Concepts
Canvas provides a bitmap drawing surface for dynamic graphics via JavaScript. SVG (Scalable Vector Graphics) is an XML-based format for resolution-independent vector graphics that can be styled with CSS and manipulated with JavaScript.
Canvas Basics
<!-- Canvas element -->
<canvas id="myCanvas" width="400" height="300">
Your browser does not support canvas.
</canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// Rectangle
ctx.fillStyle = '#3498db';
ctx.fillRect(10, 10, 100, 80);
// Stroke rectangle
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 3;
ctx.strokeRect(130, 10, 100, 80);
// Path (triangle)
ctx.beginPath();
ctx.moveTo(250, 90);
ctx.lineTo(290, 10);
ctx.lineTo(330, 90);
ctx.closePath();
ctx.fillStyle = '#2ecc71';
ctx.fill();
// Circle
ctx.beginPath();
ctx.arc(60, 150, 40, 0, Math.PI * 2);
ctx.fillStyle = '#9b59b6';
ctx.fill();
// Text
ctx.font = '20px Arial';
ctx.fillStyle = '#333';
ctx.fillText('Hello Canvas', 120, 160);
// Line
ctx.beginPath();
ctx.moveTo(10, 220);
ctx.lineTo(380, 220);
ctx.strokeStyle = '#f39c12';
ctx.lineWidth = 2;
ctx.stroke();
// Gradient
const gradient = ctx.createLinearGradient(10, 250, 200, 250);
gradient.addColorStop(0, '#3498db');
gradient.addColorStop(1, '#e74c3c');
ctx.fillStyle = gradient;
ctx.fillRect(10, 240, 200, 40);
</script>
SVG Basics
<!-- Inline SVG -->
<svg width="400" height="300" xmlns="http://www.w3.org/2000/svg">
<!-- Rectangle -->
<rect x="10" y="10" width="100" height="80" fill="#3498db"/>
<!-- Rectangle with stroke -->
<rect x="130" y="10" width="100" height="80"
fill="none" stroke="#e74c3c" stroke-width="3"/>
<!-- Circle -->
<circle cx="60" cy="150" r="40" fill="#9b59b6"/>
<!-- Ellipse -->
<ellipse cx="180" cy="150" rx="50" ry="30" fill="#f39c12"/>
<!-- Line -->
<line x1="10" y1="220" x2="380" y2="220"
stroke="#2ecc71" stroke-width="2"/>
<!-- Polyline -->
<polyline points="10,280 50,250 90,280 130,250 170,280"
fill="none" stroke="#3498db" stroke-width="2"/>
<!-- Polygon (triangle) -->
<polygon points="250,90 290,10 330,90" fill="#2ecc71"/>
<!-- Path -->
<path d="M 200 250 Q 250 200 300 250 T 400 250"
fill="none" stroke="#e74c3c" stroke-width="2"/>
<!-- Text -->
<text x="250" y="160" font-family="Arial" font-size="20" fill="#333">
Hello SVG
</text>
<!-- Group with transform -->
<g transform="translate(300, 50) rotate(45)">
<rect x="0" y="0" width="30" height="30" fill="#9b59b6"/>
</g>
</svg>
SVG with CSS Styling
<style>
.icon {
width: 24px;
height: 24px;
fill: currentColor;
}
.icon:hover {
fill: #3498db;
}
.animated-circle {
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { r: 20; }
50% { r: 30; }
}
</style>
<svg class="icon" viewBox="0 0 24 24">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>
<svg width="100" height="100">
<circle class="animated-circle" cx="50" cy="50" r="20" fill="#3498db"/>
</svg>
Canvas vs SVG Comparison
| Feature | Canvas | SVG |
|---|---|---|
| Type | Bitmap (raster) | Vector |
| Scaling | Pixelates | Resolution independent |
| DOM Access | No | Yes (each element) |
| Event Handling | Manual (coordinates) | Native (per element) |
| Performance | Better for many objects | Better for few, complex objects |
| Best For | Games, image editing | Icons, charts, diagrams |
| Accessibility | Requires extra effort | Built-in text support |
Data Attributes
Key Concepts
Custom data attributes (data-*) allow storing extra information on HTML elements without affecting presentation or behaviour. They are accessible via JavaScript and CSS, providing a clean way to attach metadata to elements.
Syntax and Usage
<!-- Basic data attributes -->
<div id="user"
data-user-id="12345"
data-role="admin"
data-active="true"
data-last-login="2025-01-15T10:30:00Z">
User Profile
</div>
<!-- Data attributes on various elements -->
<button data-action="delete" data-confirm="Are you sure?">Delete</button>
<article data-category="technology"
data-author="Jane Smith"
data-publish-date="2025-01-15"
data-read-time="5">
Article content...
</article>
<li data-product-id="SKU123"
data-price="29.99"
data-currency="GBP"
data-in-stock="true">
Product Item
</li>
JavaScript Access
<div id="config"
data-api-url="https://api.example.com"
data-max-retries="3"
data-enable-cache="true">
</div>
<script>
const element = document.getElementById('config');
// Using dataset property (camelCase)
console.log(element.dataset.apiUrl); // "https://api.example.com"
console.log(element.dataset.maxRetries); // "3"
console.log(element.dataset.enableCache); // "true"
// Setting data attributes
element.dataset.timeout = "5000";
element.dataset.newFeature = "enabled";
// Using getAttribute/setAttribute (kebab-case)
console.log(element.getAttribute('data-api-url'));
element.setAttribute('data-version', '2.0');
// Checking existence
if (element.dataset.enableCache === 'true') {
// Enable caching logic
}
// Deleting data attributes
delete element.dataset.newFeature;
</script>
CSS Styling with Data Attributes
<style>
/* Attribute selectors */
[data-status="active"] {
background-color: #2ecc71;
color: white;
}
[data-status="inactive"] {
background-color: #95a5a6;
}
[data-priority="high"] {
border-left: 4px solid #e74c3c;
}
/* Display data attribute value */
[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
background: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
}
/* Wildcard matching */
[data-theme*="dark"] {
background-color: #2c3e50;
color: #ecf0f1;
}
</style>
<span data-status="active">Online</span>
<span data-status="inactive">Offline</span>
<div data-priority="high">Urgent Task</div>
<button data-tooltip="Click to save">Save</button>
Common Use Cases
<!-- Toggle functionality -->
<button data-toggle="modal" data-target="#loginModal">Login</button>
<!-- Sorting and filtering -->
<table id="products">
<tr data-sortable="true" data-sort-key="name">
<td data-value="Apple">Apple</td>
<td data-value="1.50">£1.50</td>
</tr>
</table>
<!-- Analytics tracking -->
<a href="/products"
data-track-event="click"
data-track-category="navigation"
data-track-label="products-link">
View Products
</a>
<!-- Form validation messages -->
<input type="email"
data-error-required="Email is required"
data-error-invalid="Please enter a valid email">
<!-- Internationalisation -->
<span data-i18n="welcome.message">Welcome!</span>
Accessibility Attributes
Key Concepts
ARIA (Accessible Rich Internet Applications) attributes enhance accessibility for users with disabilities. They provide semantic information about elements, their states, and relationships to assistive technologies like screen readers.
ARIA Roles
<!-- Landmark roles -->
<div role="banner">Site header content</div>
<div role="navigation">Navigation links</div>
<div role="main">Main content</div>
<div role="complementary">Sidebar content</div>
<div role="contentinfo">Footer content</div>
<div role="search">Search form</div>
<!-- Widget roles -->
<div role="button" tabindex="0">Custom Button</div>
<div role="checkbox" aria-checked="false" tabindex="0">Option</div>
<div role="dialog" aria-labelledby="dialog-title">Modal content</div>
<div role="tablist">
<div role="tab" aria-selected="true">Tab 1</div>
<div role="tab" aria-selected="false">Tab 2</div>
</div>
<div role="tabpanel">Tab content</div>
<ul role="menu">
<li role="menuitem">Menu Item</li>
</ul>
<div role="alert">Important message</div>
<div role="status">Status update</div>
<div role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
Loading...
</div>
Common ARIA Attributes
| Attribute | Description | Example |
|---|---|---|
aria-label |
Accessible name | <button aria-label="Close">X</button> |
aria-labelledby |
Reference to labelling element | <div aria-labelledby="title-id"> |
aria-describedby |
Reference to description | <input aria-describedby="help-text"> |
aria-hidden |
Hide from assistive tech | <span aria-hidden="true">★</span> |
aria-expanded |
Expandable state | <button aria-expanded="false"> |
aria-pressed |
Toggle button state | <button aria-pressed="true"> |
aria-selected |
Selection state | <li aria-selected="true"> |
aria-checked |
Checkbox state | <div aria-checked="mixed"> |
aria-disabled |
Disabled state | <button aria-disabled="true"> |
aria-required |
Required field | <input aria-required="true"> |
aria-invalid |
Validation state | <input aria-invalid="true"> |
aria-live |
Live region updates | <div aria-live="polite"> |
aria-atomic |
Announce entire region | <div aria-atomic="true"> |
aria-busy |
Loading state | <div aria-busy="true"> |
aria-current |
Current item | <a aria-current="page"> |
aria-haspopup |
Has popup | <button aria-haspopup="menu"> |
aria-controls |
Controls another element | <button aria-controls="panel-id"> |
aria-owns |
Parent-child relationship | <div aria-owns="child-id"> |
Examples
Accessible Navigation
<nav aria-label="Main navigation">
<ul role="menubar">
<li role="none">
<a role="menuitem" href="/" aria-current="page">Home</a>
</li>
<li role="none">
<button role="menuitem" aria-haspopup="true" aria-expanded="false">
Products
</button>
<ul role="menu" aria-label="Products submenu">
<li role="none">
<a role="menuitem" href="/products/new">New Arrivals</a>
</li>
<li role="none">
<a role="menuitem" href="/products/sale">Sale</a>
</li>
</ul>
</li>
</ul>
</nav>
Accessible Modal Dialog
<button aria-haspopup="dialog" aria-controls="modal">Open Modal</button>
<div id="modal"
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
hidden>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-desc">Are you sure you want to proceed with this action?</p>
<button>Confirm</button>
<button aria-label="Close modal">Cancel</button>
</div>
Accessible Form
<form aria-labelledby="form-title">
<h2 id="form-title">Contact Us</h2>
<div>
<label for="name">Name <span aria-hidden="true">*</span></label>
<input type="text" id="name"
aria-required="true"
aria-describedby="name-hint">
<span id="name-hint" class="hint">Enter your full name</span>
</div>
<div>
<label for="email">Email <span aria-hidden="true">*</span></label>
<input type="email" id="email"
aria-required="true"
aria-invalid="false"
aria-describedby="email-error">
<span id="email-error" class="error" role="alert" hidden>
Please enter a valid email address
</span>
</div>
<div>
<label for="message">Message</label>
<textarea id="message"
aria-describedby="message-count"></textarea>
<span id="message-count" aria-live="polite">
0/500 characters
</span>
</div>
<button type="submit">
<span aria-hidden="true">📧</span>
Send Message
</button>
</form>
Live Regions
<!-- Polite announcements (wait for idle) -->
<div aria-live="polite" aria-atomic="true" id="status">
<!-- Dynamic status updates -->
</div>
<!-- Assertive announcements (immediate) -->
<div aria-live="assertive" role="alert" id="errors">
<!-- Error messages -->
</div>
<!-- Loading indicator -->
<div aria-busy="true" aria-live="polite">
<span role="status">Loading results...</span>
</div>
Accessible Tabs
<div class="tabs">
<div role="tablist" aria-label="Content sections">
<button role="tab"
id="tab-1"
aria-selected="true"
aria-controls="panel-1">
Overview
</button>
<button role="tab"
id="tab-2"
aria-selected="false"
aria-controls="panel-2"
tabindex="-1">
Details
</button>
<button role="tab"
id="tab-3"
aria-selected="false"
aria-controls="panel-3"
tabindex="-1">
Reviews
</button>
</div>
<div role="tabpanel"
id="panel-1"
aria-labelledby="tab-1">
Overview content...
</div>
<div role="tabpanel"
id="panel-2"
aria-labelledby="tab-2"
hidden>
Details content...
</div>
<div role="tabpanel"
id="panel-3"
aria-labelledby="tab-3"
hidden>
Reviews content...
</div>
</div>
Meta Tags and SEO
Key Concepts
Meta tags provide metadata about HTML documents. They inform browsers, search engines, and social media platforms about page content, behaviour, and presentation, directly impacting SEO and user experience.
Essential Meta Tags
<!DOCTYPE html>
<html lang="en-GB">
<head>
<!-- Character encoding (must be within first 1024 bytes) -->
<meta charset="UTF-8">
<!-- Viewport for responsive design -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Page title (50-60 characters) -->
<title>Page Title | Brand Name</title>
<!-- Meta description (150-160 characters) -->
<meta name="description" content="Concise description of page content for search engine results. Include primary keywords naturally.">
<!-- Keywords (less important for SEO now) -->
<meta name="keywords" content="keyword1, keyword2, keyword3">
<!-- Author -->
<meta name="author" content="Author Name">
<!-- Robots directives -->
<meta name="robots" content="index, follow">
<!-- Canonical URL -->
<link rel="canonical" href="https://example.com/page">
<!-- Language alternatives -->
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/page">
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/page">
<link rel="alternate" hreflang="x-default" href="https://example.com/page">
</head>
</html>
Open Graph (Social Media)
<!-- Basic Open Graph -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.com/page">
<meta property="og:title" content="Page Title">
<meta property="og:description" content="Description for social media sharing">
<meta property="og:image" content="https://example.com/images/og-image.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Image description">
<meta property="og:site_name" content="Site Name">
<meta property="og:locale" content="en_GB">
<!-- Article-specific -->
<meta property="og:type" content="article">
<meta property="article:published_time" content="2025-01-15T09:00:00Z">
<meta property="article:modified_time" content="2025-01-16T10:30:00Z">
<meta property="article:author" content="https://example.com/author">
<meta property="article:section" content="Technology">
<meta property="article:tag" content="HTML5">
Twitter Cards
<!-- Summary card -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@username">
<meta name="twitter:creator" content="@author">
<meta name="twitter:title" content="Page Title">
<meta name="twitter:description" content="Description for Twitter">
<meta name="twitter:image" content="https://example.com/images/twitter-card.jpg">
<meta name="twitter:image:alt" content="Image description">
<!-- Large image card -->
<meta name="twitter:card" content="summary_large_image">
Technical Meta Tags
<!-- Refresh/redirect -->
<meta http-equiv="refresh" content="5;url=https://example.com/new-page">
<!-- Content Security Policy -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
<!-- Cache control -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- Theme colour (mobile browsers) -->
<meta name="theme-color" content="#3498db">
<!-- Mobile app capable -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="App Name">
<!-- Disable telephone number detection -->
<meta name="format-detection" content="telephone=no">
Favicon and Icons
<!-- Standard favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<!-- Apple touch icons -->
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<!-- Android/Chrome -->
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3498db">
<!-- Microsoft tiles -->
<meta name="msapplication-TileColor" content="#3498db">
<meta name="msapplication-config" content="/browserconfig.xml">
Structured Data (JSON-LD)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Article Title",
"description": "Article description",
"image": "https://example.com/image.jpg",
"author": {
"@type": "Person",
"name": "Author Name"
},
"publisher": {
"@type": "Organisation",
"name": "Publisher Name",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
},
"datePublished": "2025-01-15",
"dateModified": "2025-01-16"
}
</script>
Common Document Structure Patterns
Basic HTML5 Template
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page description here">
<title>Page Title | Site Name</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>Site Name</h1>
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main>
<h2>Page Heading</h2>
<p>Content goes here...</p>
</main>
<footer>
<p>© 2025 Site Name</p>
</footer>
<script src="scripts.js"></script>
</body>
</html>
Blog Post Template
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Brief summary of the article">
<meta name="author" content="Author Name">
<!-- Open Graph -->
<meta property="og:type" content="article">
<meta property="og:title" content="Article Title">
<meta property="og:description" content="Article description">
<meta property="og:image" content="https://example.com/image.jpg">
<title>Article Title | Blog Name</title>
<link rel="canonical" href="https://example.com/article-slug">
</head>
<body>
<header>
<nav aria-label="Main navigation">
<!-- Site navigation -->
</nav>
</header>
<main>
<article>
<header>
<h1>Article Title</h1>
<p class="meta">
By <a rel="author" href="/author/name">Author Name</a>
on <time datetime="2025-01-15">15 January 2025</time>
</p>
</header>
<section>
<p>Introduction paragraph...</p>
</section>
<section>
<h2>Section Heading</h2>
<p>Content...</p>
<figure>
<img src="image.jpg" alt="Description" loading="lazy">
<figcaption>Figure 1: Caption text</figcaption>
</figure>
</section>
<footer>
<p>Tags: <a href="/tag/html5">HTML5</a>, <a href="/tag/web">Web</a></p>
</footer>
</article>
<aside>
<h2>Related Articles</h2>
<ul>
<li><a href="/related-1">Related Article 1</a></li>
<li><a href="/related-2">Related Article 2</a></li>
</ul>
</aside>
<section aria-labelledby="comments-heading">
<h2 id="comments-heading">Comments</h2>
<!-- Comments section -->
</section>
</main>
<footer>
<p>© 2025 Blog Name</p>
</footer>
</body>
</html>
Product Page Template
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Name | Shop Name</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Product Name",
"image": "https://example.com/product.jpg",
"description": "Product description",
"brand": {
"@type": "Brand",
"name": "Brand Name"
},
"offers": {
"@type": "Offer",
"price": "29.99",
"priceCurrency": "GBP",
"availability": "https://schema.org/InStock"
}
}
</script>
</head>
<body>
<header>
<!-- Site header and navigation -->
</header>
<main>
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/category">Category</a></li>
<li aria-current="page">Product Name</li>
</ol>
</nav>
<article>
<div class="product-gallery">
<figure>
<picture>
<source srcset="product-large.webp" type="image/webp">
<img src="product-large.jpg" alt="Product Name">
</picture>
</figure>
</div>
<div class="product-info">
<h1>Product Name</h1>
<p class="price">£29.99</p>
<form action="/cart/add" method="POST">
<input type="hidden" name="product_id" value="SKU123">
<div>
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity"
min="1" max="10" value="1">
</div>
<div>
<label for="size">Size:</label>
<select id="size" name="size" required>
<option value="">Select size</option>
<option value="S">Small</option>
<option value="M">Medium</option>
<option value="L">Large</option>
</select>
</div>
<button type="submit">Add to Cart</button>
</form>
<section aria-labelledby="description-heading">
<h2 id="description-heading">Description</h2>
<p>Product description text...</p>
</section>
</div>
</article>
<section aria-labelledby="reviews-heading">
<h2 id="reviews-heading">Customer Reviews</h2>
<!-- Reviews -->
</section>
</main>
<footer>
<!-- Footer content -->
</footer>
</body>
</html>
Quick Reference
HTML5 Doctype and Basic Structure
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
</head>
<body>
<!-- Content -->
</body>
</html>
Semantic Elements Summary
| Element | Purpose |
|---|---|
<header> |
Introductory content |
<nav> |
Navigation links |
<main> |
Main content |
<article> |
Self-contained content |
<section> |
Thematic grouping |
<aside> |
Sidebar content |
<footer> |
Footer information |
<figure> |
Media with caption |
<figcaption> |
Caption for figure |
<time> |
Date/time |
<mark> |
Highlighted text |
<details> |
Disclosure widget |
<summary> |
Summary for details |
<dialog> |
Dialog box |
<template> |
HTML template |
Form Input Types
| Type | Description |
|---|---|
text |
Single-line text |
email |
Email address |
password |
Password field |
number |
Numeric input |
range |
Slider |
date |
Date picker |
time |
Time picker |
datetime-local |
Date and time |
month |
Month picker |
week |
Week picker |
tel |
Telephone |
url |
URL |
search |
Search field |
color |
Colour picker |
file |
File upload |
Essential ARIA Attributes
| Attribute | Purpose |
|---|---|
aria-label |
Accessible name |
aria-labelledby |
Label reference |
aria-describedby |
Description reference |
aria-hidden |
Hide from AT |
aria-expanded |
Expanded state |
aria-pressed |
Toggle state |
aria-selected |
Selection state |
aria-required |
Required field |
aria-invalid |
Validation state |
aria-live |
Live updates |
aria-current |
Current item |
Common Roles
| Role | Purpose |
|---|---|
banner |
Site header |
navigation |
Navigation |
main |
Main content |
complementary |
Sidebar |
contentinfo |
Footer |
search |
Search area |
button |
Button |
dialog |
Modal |
alert |
Alert message |
tab / tabpanel |
Tabs |
menu / menuitem |
Menus |
Common Issues and Solutions
Issue: Form Validation Not Working
Problem: HTML5 validation is bypassed or not showing error messages.
Solutions:
<!-- Ensure form doesn't have novalidate -->
<form action="/submit" method="POST">
<!-- NOT: <form novalidate> -->
<!-- Use correct input types -->
<input type="email" required>
<!-- Custom validation with pattern -->
<input type="text" pattern="[A-Z]{2}[0-9]{6}"
title="Two letters followed by six numbers">
</form>
<!-- Custom validation messages with JavaScript -->
<script>
const input = document.querySelector('input[type="email"]');
input.addEventListener('invalid', function() {
this.setCustomValidity('Please enter a valid email address');
});
input.addEventListener('input', function() {
this.setCustomValidity('');
});
</script>
Issue: Video Not Playing
Problem: Video doesn't play or shows black screen.
Solutions:
<!-- Provide multiple formats -->
<video controls>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
<source src="video.ogv" type="video/ogg">
<p>Your browser doesn't support video.</p>
</video>
<!-- For autoplay, must be muted -->
<video autoplay muted playsinline>
<source src="video.mp4" type="video/mp4">
</video>
<!-- Check MIME types on server -->
<!-- .htaccess: AddType video/mp4 .mp4 -->
Issue: Responsive Images Not Working
Problem: Picture element not showing correct image.
Solutions:
<!-- Order matters: first match wins -->
<picture>
<!-- Larger breakpoints first -->
<source media="(min-width: 1200px)" srcset="large.jpg">
<source media="(min-width: 768px)" srcset="medium.jpg">
<!-- Fallback last -->
<img src="small.jpg" alt="Description">
</picture>
<!-- Always include img as fallback -->
<!-- img is required for picture to work -->
Issue: ARIA Not Being Announced
Problem: Screen readers not announcing ARIA content.
Solutions:
<!-- Use correct aria-live values -->
<div aria-live="polite">Status updates here</div>
<div aria-live="assertive" role="alert">Errors here</div>
<!-- Ensure element exists in DOM before updating -->
<div id="status" aria-live="polite"></div>
<script>
// Element exists, now update content
document.getElementById('status').textContent = 'Updated';
</script>
<!-- Don't use aria-hidden on focusable elements -->
<!-- WRONG: -->
<button aria-hidden="true">Hidden Button</button>
<!-- RIGHT: -->
<button hidden>Hidden Button</button>
Issue: Data Attributes Not Accessible in JavaScript
Problem: Cannot read data attributes from JavaScript.
Solutions:
<div id="element" data-user-id="123" data-is-active="true"></div>
<script>
const el = document.getElementById('element');
// Use dataset with camelCase
console.log(el.dataset.userId); // "123"
console.log(el.dataset.isActive); // "true"
// NOT: el.dataset['user-id'] or el.dataset.user-id
// Values are always strings
if (el.dataset.isActive === 'true') {
// Handle boolean
}
const id = parseInt(el.dataset.userId, 10);
</script>
Issue: Canvas Blurry on Retina Displays
Problem: Canvas appears blurry on high-DPI screens.
Solutions:
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
// Set display size
canvas.style.width = '400px';
canvas.style.height = '300px';
// Set actual size in memory
canvas.width = 400 * dpr;
canvas.height = 300 * dpr;
// Scale context
ctx.scale(dpr, dpr);
// Now draw as normal
ctx.fillRect(10, 10, 100, 100);
</script>
Issue: Semantic Elements Not Styled Correctly in Old Browsers
Problem: HTML5 elements not displayed as block in older browsers.
Solutions:
/* Ensure block display for semantic elements */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
display: block;
}
/* Hidden attribute support */
[hidden] {
display: none;
}
Issue: Form autocomplete Not Working
Problem: Browser not auto-filling form fields.
Solutions:
<!-- Use correct autocomplete values -->
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="street-address">
<input type="text" name="city" autocomplete="address-level2">
<input type="text" name="postcode" autocomplete="postal-code">
<input type="text" name="cc-number" autocomplete="cc-number">
<!-- Group related fields -->
<fieldset>
<legend>Shipping Address</legend>
<!-- address fields with autocomplete="shipping ..." -->
</fieldset>
Related Topics
The following topics complement this HTML5 cheatsheet and would help build a more complete understanding of modern web development:
-
CSS3 - Styling, layouts (Flexbox, Grid), animations, and responsive design techniques that work alongside HTML5 elements
-
JavaScript DOM Manipulation - Interacting with HTML5 elements, handling events, form validation, and dynamic content updates
-
Web Accessibility (WCAG) - Comprehensive accessibility guidelines, testing tools, and best practices beyond basic ARIA implementation
-
Progressive Web Apps (PWA) - Service workers, web manifests, offline support, and native-like web application features
-
Web Performance Optimisation - Image optimisation, lazy loading, critical rendering path, Core Web Vitals, and caching strategies
-
SEO Best Practices - On-page optimisation, structured data, content strategy, and search engine ranking factors beyond meta tags