HTML5 Cheatsheet
Comprehensive quick reference for HTML5 elements, attributes, semantic markup, forms, media, accessibility, and best practices. Essential guide for modern web development.
Table of Contents
- Document Structure
- Semantic Elements
- Forms & Input
- Media Elements
- Metadata & SEO
- Accessibility
- Attributes
- Best Practices
- Common Pitfalls
Document Structure
Basic HTML5 Document 📄
<!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> <!-- Content goes here --> </body></html>DOCTYPE Declaration 🔧
<!-- HTML5 DOCTYPE (required, must be first line) --><!DOCTYPE html>
<!-- ❌ Old HTML4/XHTML (don't use) --><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">Essential Meta Tags 📋
<head> <!-- Character encoding (must be first meta tag) --> <meta charset="UTF-8" />
<!-- Viewport for responsive design --> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Page description --> <meta name="description" content="Brief description of page content" />
<!-- Keywords (less important, but still used) --> <meta name="keywords" content="keyword1, keyword2, keyword3" />
<!-- Author --> <meta name="author" content="Author Name" />
<!-- Open Graph (social media) --> <meta property="og:title" content="Page Title" /> <meta property="og:description" content="Page description" /> <meta property="og:image" content="image-url.jpg" />
<!-- Theme color (mobile browsers) --> <meta name="theme-color" content="#000000" /></head>Semantic Elements
Structural Semantic Elements 🏗️
<!-- Document outline --><header> <!-- Site header, navigation, logo --> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> </ul> </nav></header>
<main> <!-- Main content (only one per page) --> <article> <!-- Independent, self-contained content --> <header> <h1>Article Title</h1> <p>Published on <time datetime="2024-01-15">Jan 15, 2024</time></p> </header> <section> <h2>Section Heading</h2> <p>Content...</p> </section> </article>
<aside> <!-- Sidebar, related content --> <h2>Related Articles</h2> </aside></main>
<footer> <!-- Site footer, copyright, links --> <p>© 2024 Company Name</p></footer>Content Semantic Elements 📝
<!-- Article: independent content --><article> <h1>Blog Post Title</h1> <p>Article content...</p></article>
<!-- Section: thematic grouping --><section> <h2>Chapter Title</h2> <p>Section content...</p></section>
<!-- Navigation --><nav> <ul> <li><a href="/home">Home</a></li> <li><a href="/about">About</a></li> </ul></nav>
<!-- Aside: tangential content --><aside> <h3>Related Links</h3> <ul> <li><a href="#">Link 1</a></li> </ul></aside>
<!-- Figure with caption --><figure> <img src="image.jpg" alt="Description" /> <figcaption>Image caption text</figcaption></figure>
<!-- Mark: highlighted text --><p>This is <mark>important</mark> text.</p>
<!-- Time: machine-readable date/time --><time datetime="2024-01-15T10:30">Jan 15, 2024 at 10:30 AM</time>
<!-- Address: contact information --><address> <a href="mailto:contact@example.com">contact@example.com</a></address>Text-Level Semantic Elements ✍️
<!-- Emphasis (semantic, not just styling) --><p>This is <em>emphasized</em> text.</p>
<!-- Strong importance --><p>This is <strong>important</strong> text.</p>
<!-- Small print --><p><small>Copyright notice</small></p>
<!-- Citation --><p>As stated in <cite>The Book Title</cite>...</p>
<!-- Abbreviation --><p>Use <abbr title="HyperText Markup Language">HTML</abbr> for structure.</p>
<!-- Definition --><p><dfn>HTML</dfn> stands for HyperText Markup Language.</p>
<!-- Code --><p>Use <code>console.log()</code> to debug.</p>
<!-- Keyboard input --><p>Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy.</p>
<!-- Sample output --><p>Output: <samp>Hello, World!</samp></p>
<!-- Variable --><p>Let <var>x</var> = 10.</p>
<!-- Deleted text --><p>Price: <del>$100</del> <ins>$80</ins></p>Semantic Elements Comparison Table 📊
| Element | Purpose | Use Case |
|---|---|---|
<header> | Site/page header | Logo, navigation, page title |
<nav> | Navigation links | Main menu, breadcrumbs |
<main> | Main content | Primary page content (one per page) |
<article> | Independent content | Blog post, news article, comment |
<section> | Thematic grouping | Chapter, topic section |
<aside> | Tangential content | Sidebar, related links |
<footer> | Site/page footer | Copyright, contact info |
<figure> | Media with caption | Image, video, diagram |
<figcaption> | Figure caption | Description of figure |
Forms & Input
Form Structure 📋
<form action="/submit" method="POST" novalidate> <!-- Form fields --> <fieldset> <legend>Personal Information</legend>
<!-- Text input --> <label for="name">Name:</label> <input type="text" id="name" name="name" required />
<!-- Email input --> <label for="email">Email:</label> <input type="email" id="email" name="email" required />
<!-- Password --> <label for="password">Password:</label> <input type="password" id="password" name="password" minlength="8" required /> </fieldset>
<button type="submit">Submit</button> <button type="reset">Reset</button></form>Input Types 🎯
<!-- Text --><input type="text" name="username" placeholder="Enter username" />
<!-- Email (with validation) --><input type="email" name="email" placeholder="email@example.com" />
<!-- Password --><input type="password" name="password" />
<!-- Number --><input type="number" name="age" min="18" max="100" step="1" />
<!-- Range slider --><input type="range" name="volume" min="0" max="100" value="50" />
<!-- Date --><input type="date" name="birthday" />
<!-- Time --><input type="time" name="appointment" />
<!-- DateTime-local --><input type="datetime-local" name="event" />
<!-- Month --><input type="month" name="month" />
<!-- Week --><input type="week" name="week" />
<!-- Color picker --><input type="color" name="favcolor" value="#ff0000" />
<!-- URL --><input type="url" name="website" placeholder="https://example.com" />
<!-- Tel --><input type="tel" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" />
<!-- Search --><input type="search" name="query" placeholder="Search..." />
<!-- File upload --><input type="file" name="upload" accept="image/*,.pdf" />
<!-- Hidden --><input type="hidden" name="token" value="abc123" />
<!-- Checkbox --><input type="checkbox" id="agree" name="agree" value="yes" /><label for="agree">I agree</label>
<!-- Radio buttons --><input type="radio" id="male" name="gender" value="male" /><label for="male">Male</label><input type="radio" id="female" name="gender" value="female" /><label for="female">Female</label>Form Attributes 🔧
<!-- Required field --><input type="text" name="name" required />
<!-- Placeholder text --><input type="text" placeholder="Enter your name" />
<!-- Pattern validation (regex) --><input type="text" pattern="[A-Za-z]{3,}" title="3+ letters" />
<!-- Min/Max values --><input type="number" min="0" max="100" step="5" />
<!-- Min/Max length --><input type="text" minlength="3" maxlength="20" />
<!-- Autocomplete --><input type="email" autocomplete="email" /><input type="password" autocomplete="current-password" />
<!-- Disabled --><input type="text" disabled value="Cannot edit" />
<!-- Readonly --><input type="text" readonly value="Cannot change" />
<!-- Autofocus --><input type="text" autofocus />
<!-- Multiple values --><input type="file" multiple /><select multiple> <option>Option 1</option> <option>Option 2</option></select>Select & Textarea 📝
<!-- Dropdown select --><label for="country">Country:</label><select id="country" name="country"> <option value="">Select a country</option> <option value="us">United States</option> <option value="uk">United Kingdom</option> <optgroup label="Europe"> <option value="fr">France</option> <option value="de">Germany</option> </optgroup></select>
<!-- Textarea --><label for="message">Message:</label><textarea id="message" name="message" rows="4" cols="50" placeholder="Enter your message" maxlength="500"></textarea>
<!-- Datalist (autocomplete suggestions) --><label for="browser">Browser:</label><input list="browsers" id="browser" name="browser" /><datalist id="browsers"> <option value="Chrome"></option> <option value="Firefox"></option> <option value="Safari"></option></datalist>Form Validation ✅
<!-- HTML5 validation --><form novalidate> <!-- Email validation --> <input type="email" required />
<!-- URL validation --> <input type="url" required />
<!-- Pattern validation --> <input type="text" pattern="[0-9]{4}" title="Must be 4 digits" required />
<!-- Custom validation message --> <input type="text" required oninvalid="this.setCustomValidity('Custom error message')" oninput="this.setCustomValidity('')" /></form>
<!-- ✅ Do: Use proper input types --><input type="email" name="email" /><!-- Browser validates email format -->
<!-- ❌ Don't: Use text for everything --><input type="text" name="email" /><!-- No automatic validation -->Media Elements
Images 🖼️
<!-- Basic image --><img src="image.jpg" alt="Descriptive text" />
<!-- Responsive image (srcset) --><img src="image-small.jpg" srcset="image-small.jpg 480w, image-medium.jpg 768w, image-large.jpg 1200w" sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw" alt="Responsive image"/>
<!-- Picture element (art direction) --><picture> <source media="(min-width: 800px)" srcset="large.jpg" /> <source media="(min-width: 400px)" srcset="medium.jpg" /> <img src="small.jpg" alt="Responsive picture" /></picture>
<!-- Image with figure --><figure> <img src="diagram.png" alt="System architecture" /> <figcaption>System architecture diagram</figcaption></figure>
<!-- Lazy loading --><img src="image.jpg" alt="Description" loading="lazy" />
<!-- Decorative image (empty alt) --><img src="decoration.jpg" alt="" role="presentation" />Video & Audio 🎬
<!-- Video --><video controls width="640" height="360" poster="thumbnail.jpg"> <source src="video.mp4" type="video/mp4" /> <source src="video.webm" type="video/webm" /> <p> Your browser doesn't support video. <a href="video.mp4">Download it</a> instead. </p></video>
<!-- Video with attributes --><video controls autoplay muted loop preload="metadata"> <source src="video.mp4" type="video/mp4" /></video>
<!-- Audio --><audio controls> <source src="audio.mp3" type="audio/mpeg" /> <source src="audio.ogg" type="audio/ogg" /> <p>Your browser doesn't support audio.</p></audio>
<!-- Audio with attributes --><audio controls autoplay loop preload="auto"> <source src="audio.mp3" type="audio/mpeg" /></audio>Media Attributes Table 📊
| Attribute | Values | Description |
|---|---|---|
controls | boolean | Show playback controls |
autoplay | boolean | Start automatically |
loop | boolean | Repeat playback |
muted | boolean | Start muted |
preload | none, metadata, auto | Preload strategy |
poster | URL | Video thumbnail image |
width, height | pixels | Dimensions |
Metadata & SEO
Essential Meta Tags 🔍
<head> <!-- Title (50-60 characters optimal) --> <title>Page Title - Site Name</title>
<!-- Description (150-160 characters) --> <meta name="description" content="Brief, compelling description">
<!-- Keywords (less important now) --> <meta name="keywords" content="keyword1, keyword2, keyword3">
<!-- Author --> <meta name="author" content="Author Name">
<!-- Robots --> <meta name="robots" content="index, follow"> <!-- Values: index/noindex, follow/nofollow -->
<!-- Canonical URL --> <link rel="canonical" href="https://example.com/page">
<!-- Language --> <html lang="en"></head>Open Graph (Social Media) 📱
<head> <!-- Basic Open Graph --> <meta property="og:title" content="Page Title" /> <meta property="og:description" content="Page description" /> <meta property="og:image" content="https://example.com/image.jpg" /> <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" /> <meta name="twitter:description" content="Page description" /> <meta name="twitter:image" content="https://example.com/image.jpg" /></head>Structured Data (JSON-LD) 📊
<!-- JSON-LD structured data --><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "Article Title", "author": { "@type": "Person", "name": "Author Name" }, "datePublished": "2024-01-15", "image": "https://example.com/image.jpg" }</script>Accessibility
ARIA Attributes ♿
<!-- ARIA labels --><button aria-label="Close dialog">×</button>
<!-- ARIA describedby --><input type="text" aria-describedby="help-text" /><span id="help-text">Enter your username</span>
<!-- ARIA live regions --><div aria-live="polite" aria-atomic="true">Status updates appear here</div>
<!-- ARIA roles --><div role="navigation" aria-label="Main navigation"> <!-- Navigation content --></div>
<div role="banner"> <!-- Header content --></div>
<div role="main"> <!-- Main content --></div>
<div role="contentinfo"> <!-- Footer content --></div>Semantic HTML for Accessibility ✅
<!-- ✅ Do: Use semantic elements --><nav aria-label="Main navigation"> <ul> <li><a href="/">Home</a></li> </ul></nav>
<!-- ❌ Don't: Use divs for everything --><div class="nav"> <div class="nav-item"><a href="/">Home</a></div></div>
<!-- ✅ Do: Proper heading hierarchy --><h1>Page Title</h1><h2>Section Title</h2><h3>Subsection Title</h3>
<!-- ❌ Don't: Skip heading levels --><h1>Page Title</h1><h3>Subsection</h3><!-- Missing h2 -->Form Accessibility 📋
<!-- ✅ Do: Associate label with input --><label for="email">Email:</label><input type="email" id="email" name="email" />
<!-- ✅ Do: Implicit label association --><label> Email: <input type="email" name="email" /></label>
<!-- ✅ Do: Error messages with aria-describedby --><input type="email" id="email" aria-describedby="email-error" aria-invalid="true"/><span id="email-error" role="alert">Invalid email address</span>
<!-- ✅ Do: Required fields --><label for="name">Name: <span aria-label="required">*</span></label><input type="text" id="name" required aria-required="true" />
<!-- ✅ Do: Fieldset and legend for groups --><fieldset> <legend>Shipping Address</legend> <label for="street">Street:</label> <input type="text" id="street" name="street" /></fieldset>Keyboard Navigation ⌨️
<!-- Tab order --><input type="text" tabindex="1" /><input type="text" tabindex="2" /><button tabindex="3">Submit</button>
<!-- Skip navigation link --><a href="#main-content" class="skip-link">Skip to main content</a>
<!-- Focusable elements --><button>Click me</button><!-- ✅ Focusable --><a href="#">Link</a><!-- ✅ Focusable --><input type="text" /><!-- ✅ Focusable --><div tabindex="0">Focusable div</div><!-- ✅ Focusable with tabindex --><div>Not focusable</div><!-- ❌ Not focusable -->Attributes
Global Attributes 🌐
<!-- id: Unique identifier --><div id="unique-id">Content</div>
<!-- class: CSS class selector --><div class="container primary">Content</div>
<!-- data-*: Custom data attributes --><div data-user-id="123" data-role="admin">Content</div>
<!-- title: Tooltip text --><span title="This is a tooltip">Hover me</span>
<!-- lang: Language --><p lang="en">English text</p><p lang="es">Texto en español</p>
<!-- dir: Text direction --><p dir="ltr">Left to right</p><p dir="rtl">Right to left</p>
<!-- contenteditable: Editable content --><div contenteditable="true">Editable content</div>
<!-- hidden: Hide element --><div hidden>Not visible</div>
<!-- spellcheck: Spell checking --><textarea spellcheck="true">Text with spellcheck</textarea>
<!-- translate: Translation hint --><p translate="no">Don't translate this</p>Event Handler Attributes 🎯
<!-- Mouse events --><button onclick="handleClick()">Click</button><button onmouseover="handleHover()">Hover</button><button onmouseout="handleLeave()">Leave</button>
<!-- Form events --><form onsubmit="handleSubmit(event)"> <input onchange="handleChange()" /> <input onfocus="handleFocus()" /> <input onblur="handleBlur()" /></form>
<!-- Keyboard events --><input onkeydown="handleKeyDown()" /><input onkeyup="handleKeyUp()" /><input onkeypress="handleKeyPress()" />
<!-- ⚠️ Note: Prefer addEventListener in JavaScript --><!-- These are shown for reference but modern practice uses JS -->Common Attribute Patterns 📋
<!-- Boolean attributes (presence = true) --><input type="checkbox" checked /><input type="text" disabled /><input type="text" readonly /><video controls autoplay loop> <!-- Attributes with values --> <input type="text" value="Default value" /> <input type="number" min="0" max="100" /> <img src="image.jpg" alt="Description" width="300" height="200" />
<!-- Multiple values --> <input class="form-control primary large" /> <select multiple> <option selected>Option 1</option> <option selected>Option 2</option> </select></video>Best Practices
Document Structure ✅
<!-- ✅ Do: Proper HTML5 structure --><!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> <nav>...</nav> </header> <main>...</main> <footer>...</footer> </body></html>
<!-- ❌ Don't: Missing DOCTYPE or charset --><html> <head> <title>Page</title> </head></html>Semantic Markup ✅
<!-- ✅ Do: Use semantic elements --><article> <header> <h1>Article Title</h1> </header> <section> <h2>Section</h2> <p>Content...</p> </section></article>
<!-- ❌ Don't: Div soup --><div class="article"> <div class="header"> <div class="title">Article Title</div> </div> <div class="content"> <div class="section">Content...</div> </div></div>Images ✅
<!-- ✅ Do: Always include alt text --><img src="photo.jpg" alt="A beautiful sunset over the ocean" />
<!-- ✅ Do: Empty alt for decorative images --><img src="decoration.jpg" alt="" role="presentation" />
<!-- ❌ Don't: Missing alt attribute --><img src="photo.jpg" />
<!-- ❌ Don't: Vague alt text --><img src="photo.jpg" alt="image" />Forms ✅
<!-- ✅ Do: Associate labels with inputs --><label for="email">Email:</label><input type="email" id="email" name="email" required />
<!-- ✅ Do: Use appropriate input types --><input type="email" name="email" /><input type="tel" name="phone" /><input type="url" name="website" />
<!-- ❌ Don't: Unlabeled inputs --><input type="text" name="email" placeholder="Email" />
<!-- ❌ Don't: Use text for everything --><input type="text" name="email" /><!-- Should be type="email" -->Performance ✅
<!-- ✅ Do: Lazy load images --><img src="image.jpg" alt="Description" loading="lazy" />
<!-- ✅ Do: Use srcset for responsive images --><img srcset="small.jpg 480w, large.jpg 1200w" sizes="(max-width: 600px) 480px, 1200px" src="fallback.jpg" alt="Description"/>
<!-- ✅ Do: Preload critical resources --><link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin />
<!-- ✅ Do: Defer non-critical scripts --><script src="script.js" defer></script>
<!-- ❌ Don't: Block rendering with scripts --><script src="script.js"></script><!-- Blocks parsing -->Security ✅
<!-- ✅ Do: Use HTTPS for external resources --><link rel="stylesheet" href="https://example.com/style.css" />
<!-- ✅ Do: Set Content Security Policy --><meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline';"/>
<!-- ✅ Do: Prevent clickjacking --><meta http-equiv="X-Frame-Options" content="DENY" />
<!-- ✅ Do: Validate and sanitize form input server-side --><!-- HTML5 validation is client-side only, not secure -->Common Pitfalls
Missing DOCTYPE ⚠️
<!-- ❌ Missing DOCTYPE triggers quirks mode --><html> <head> <title>Page</title> </head></html>
<!-- ✅ Always include HTML5 DOCTYPE --><!DOCTYPE html><html></html>Warning: Missing DOCTYPE causes browsers to render in quirks mode, leading to inconsistent styling and layout issues.
Incorrect Heading Hierarchy ⚠️
<!-- ❌ Skipping heading levels --><h1>Title</h1><h3>Subsection</h3><!-- Missing h2 -->
<!-- ✅ Proper hierarchy --><h1>Title</h1><h2>Section</h2><h3>Subsection</h3>Missing Alt Text ⚠️
<!-- ❌ No alt text (accessibility issue) --><img src="photo.jpg" />
<!-- ✅ Descriptive alt text --><img src="photo.jpg" alt="A red bicycle parked outside a café" />
<!-- ✅ Empty alt for decorative images --><img src="decoration.jpg" alt="" />Improper Form Labels ⚠️
<!-- ❌ Unlabeled input --><input type="text" name="email" placeholder="Email" />
<!-- ✅ Properly labeled --><label for="email">Email:</label><input type="email" id="email" name="email" />
<!-- ✅ Implicit label --><label> Email: <input type="email" name="email" /></label>Using Divs Instead of Semantic Elements ⚠️
<!-- ❌ Div soup --><div class="header"> <div class="nav">...</div></div><div class="main"> <div class="article">...</div></div>
<!-- ✅ Semantic HTML5 --><header> <nav>...</nav></header><main> <article>...</article></main>Inline Styles Over Classes ⚠️
<!-- ❌ Inline styles (hard to maintain) --><div style="color: red; font-size: 16px;">Text</div>
<!-- ✅ Use classes --><div class="error-text">Text</div>Missing Viewport Meta Tag ⚠️
<!-- ❌ Missing viewport (breaks mobile layout) --><head> <meta charset="UTF-8" /> <title>Page</title></head>
<!-- ✅ Include viewport --><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Page</title></head>Incorrect Input Types ⚠️
<!-- ❌ Using text for everything --><input type="text" name="email" /><input type="text" name="phone" /><input type="text" name="url" />
<!-- ✅ Use appropriate types --><input type="email" name="email" /><input type="tel" name="phone" /><input type="url" name="url" />Missing Language Attribute ⚠️
<!-- ❌ No lang attribute --><html> <head> ... </head></html>
<!-- ✅ Specify language --><html lang="en"> <head> ... </head></html>Blocking Scripts ⚠️
<!-- ❌ Script blocks parsing --><script src="heavy-script.js"></script>
<!-- ✅ Defer or async --><script src="script.js" defer></script><!-- Executes after parsing --><script src="analytics.js" async></script><!-- Executes asynchronously -->