🌐 HTML Cheat Sheet
Document structure, forms, semantics, accessibility, and HTML5 APIs.
📄 Document Structure
HTML5 boilerplate
<!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> <link rel="stylesheet" href="style.css" /> </head> <body> <!-- content --> <script src="app.js" defer></script> </body> </html>
Script loading strategies
<!-- blocks parsing (avoid) -->
<script src="app.js"></script>
<!-- downloads in parallel, executes after parse -->
<script src="app.js" defer></script>
<!-- downloads in parallel, executes immediately -->
<script src="app.js" async></script>
<!-- inline module -->
<script type="module">
import { fn } from './utils.js';
</script>🔖 Meta & Head
Essential meta tags
<meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content="Page description for SEO" /> <meta name="author" content="Devtor" /> <meta name="robots" content="index, follow" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
Open Graph (social sharing)
<meta property="og:title" content="Page Title" /> <meta property="og:description" content="Description" /> <meta property="og:image" content="https://example.com/image.png" /> <meta property="og:url" content="https://example.com/page" /> <meta property="og:type" content="website" /> <!-- Twitter Card --> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content="Page Title" />
Favicon & icons
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/icon.svg" type="image/svg+xml" /> <link rel="apple-touch-icon" href="/apple-touch-icon.png" /> <link rel="manifest" href="/manifest.webmanifest" />
✏️ Text Elements
Headings & paragraphs
<h1>Main heading (one per page)</h1> <h2>Section heading</h2> <h3>Subsection</h3> ... <h6></h6> <p>Paragraph text</p> <br /> <!-- line break --> <hr /> <!-- thematic break --> <blockquote cite="https://...">Quoted text</blockquote> <pre>Preformatted text</pre> <code>inline code</code>
Inline semantics
<strong>Bold (important)</strong> <em>Italic (emphasis)</em> <mark>Highlighted</mark> <del>Deleted</del> <ins>Inserted</ins> <sub>subscript</sub> <sup>superscript</sup> <abbr title="HyperText Markup Language">HTML</abbr> <kbd>Ctrl</kbd> + <kbd>C</kbd> <time datetime="2024-06-22">June 22, 2024</time>
🔗 Links & Media
Anchor tags
<a href="https://example.com">External link</a> <a href="about.html">Relative link</a> <a href="#section">Anchor link</a> <a href="mailto:hello@example.com">Email</a> <a href="tel:+1234567890">Phone</a> <a href="file.pdf" download>Download PDF</a> <a href="https://..." target="_blank" rel="noopener noreferrer"> New tab (safe) </a>
Images
<img src="photo.jpg" alt="Descriptive alt text"
width="800" height="600" loading="lazy" />
<!-- Responsive images -->
<img
srcset="photo-400.jpg 400w, photo-800.jpg 800w"
sizes="(max-width: 600px) 400px, 800px"
src="photo-800.jpg"
alt="Description"
/>
<!-- Figure with caption -->
<figure>
<img src="chart.png" alt="Q4 Revenue" />
<figcaption>Q4 2024 Revenue Chart</figcaption>
</figure>Video & Audio
<video src="video.mp4" controls width="640"
poster="thumb.jpg" preload="metadata">
<track kind="subtitles" src="subs.vtt" srclang="en" label="English" />
Your browser does not support video.
</video>
<audio src="audio.mp3" controls preload="none"></audio>
<!-- Multiple sources fallback -->
<video controls>
<source src="video.webm" type="video/webm" />
<source src="video.mp4" type="video/mp4" />
</video>📋 Lists & Tables
Lists
<ul> <!-- unordered --> <li>Item</li> </ul> <ol type="1" start="1"> <!-- ordered: 1, A, a, I, i --> <li>First</li> </ol> <dl> <!-- definition list --> <dt>Term</dt> <dd>Definition</dd> </dl>
Tables
<table>
<caption>Monthly Sales</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Revenue</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jan</td>
<td>$10,000</td>
</tr>
</tbody>
<tfoot>
<tr><td colspan="2">Total: $10,000</td></tr>
</tfoot>
</table>📝 Forms
Form structure
<form action="/submit" method="post" novalidate>
<fieldset>
<legend>Personal Info</legend>
<label for="name">Name *</label>
<input id="name" name="name" type="text"
required minlength="2" maxlength="100"
placeholder="Your name" autocomplete="name" />
<label for="email">Email</label>
<input id="email" name="email" type="email" />
</fieldset>
<button type="submit">Send</button>
<button type="reset">Reset</button>
</form>Input types
type="text" type="email" type="password" type="number" type="tel" type="url" type="date" type="time" type="datetime-local" type="color" type="range" type="file" type="checkbox" type="radio" type="hidden" type="search" type="submit" type="button" <input type="range" min="0" max="100" step="5" value="50" /> <input type="file" accept="image/*" multiple /> <input type="number" min="1" max="99" />
Select, Textarea, Datalist
<select name="role" multiple>
<optgroup label="Dev">
<option value="fe">Frontend</option>
<option value="be" selected>Backend</option>
</optgroup>
</select>
<textarea name="bio" rows="4" cols="50"></textarea>
<!-- Autocomplete suggestions -->
<input list="langs" name="lang" />
<datalist id="langs">
<option value="Dart">
<option value="Swift">
<option value="Kotlin">
</datalist>🧱 Semantic HTML
Page layout elements
<header> Site or section header</header>
<nav> Navigation links</nav>
<main> Primary content (one per page)</main>
<aside> Sidebar / supplementary content</aside>
<article> Self-contained content (blog post, card)</article>
<section> Thematic grouping with heading</section>
<footer> Footer for page or section</footer>
<!-- Interactive -->
<details>
<summary>Click to expand</summary>
Hidden content revealed on click
</details>
<dialog id="modal">
<p>Modal content</p>
<button onclick="this.closest('dialog').close()">Close</button>
</dialog>
<script>document.getElementById('modal').showModal();</script>♿ Accessibility
ARIA attributes
aria-label="Close dialog" <!-- accessible name --> aria-labelledby="heading-id" <!-- name from element --> aria-describedby="hint-id" <!-- extra description --> aria-hidden="true" <!-- hide from screen readers --> aria-expanded="false" <!-- toggle state --> aria-live="polite" <!-- dynamic content updates --> aria-required="true" <!-- required field --> aria-invalid="true" <!-- field validation error --> role="button | dialog | alert | ..."
Skip links & focus
<!-- Skip navigation for keyboard users -->
<a href="#main" class="skip-link">Skip to content</a>
<!-- Make non-interactive element focusable -->
<div tabindex="0" role="button" onkeydown="...">Custom button</div>
<!-- Remove from tab order -->
<div tabindex="-1"></div>
.skip-link {
position: absolute;
transform: translateY(-100%);
}
.skip-link:focus { transform: translateY(0); }🚀 HTML5 APIs
Canvas
<canvas id="c" width="400" height="300"></canvas>
<script>
const ctx = document.getElementById('c').getContext('2d');
ctx.fillStyle = '#6366f1';
ctx.fillRect(10, 10, 100, 80);
ctx.strokeStyle = '#fff';
ctx.lineWidth = 2;
ctx.strokeRect(10, 10, 100, 80);
ctx.font = '16px sans-serif';
ctx.fillStyle = '#fff';
ctx.fillText('Hello Canvas', 15, 55);
</script>Drag and Drop API
<div draggable="true" ondragstart="drag(event)">Drag me</div>
<div ondragover="event.preventDefault()" ondrop="drop(event)">Drop here</div>
function drag(e) { e.dataTransfer.setData('text/plain', e.target.id); }
function drop(e) {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain');
e.target.appendChild(document.getElementById(id));
}Web Storage & Geolocation
// localStorage (persists)
localStorage.setItem('key', JSON.stringify(obj));
const val = JSON.parse(localStorage.getItem('key'));
localStorage.removeItem('key');
// sessionStorage (per tab)
sessionStorage.setItem('token', '...');
// Geolocation
navigator.geolocation.getCurrentPosition(
pos => console.log(pos.coords.latitude, pos.coords.longitude),
err => console.error(err),
{ enableHighAccuracy: true, timeout: 5000 }
);⚙️ Misc / Patterns
Template & Slot
<template id="card-tpl">
<div class="card">
<h3 class="title"></h3>
<slot name="body"></slot>
</div>
</template>
const tpl = document.getElementById('card-tpl');
const clone = tpl.content.cloneNode(true);
clone.querySelector('.title').textContent = 'My Card';
document.body.appendChild(clone);Character entities
& → & < → < > → > " → " ' → ' → non-breaking space © → © — → — …→ … ❤→ ❤