Skip to main content

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

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>&copy; 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 📊

ElementPurposeUse Case
<header>Site/page headerLogo, navigation, page title
<nav>Navigation linksMain menu, breadcrumbs
<main>Main contentPrimary page content (one per page)
<article>Independent contentBlog post, news article, comment
<section>Thematic groupingChapter, topic section
<aside>Tangential contentSidebar, related links
<footer>Site/page footerCopyright, contact info
<figure>Media with captionImage, video, diagram
<figcaption>Figure captionDescription 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 📊

AttributeValuesDescription
controlsbooleanShow playback controls
autoplaybooleanStart automatically
loopbooleanRepeat playback
mutedbooleanStart muted
preloadnone, metadata, autoPreload strategy
posterURLVideo thumbnail image
width, heightpixelsDimensions

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 -->