Jump to section
HTML Cheatsheet
A practical HTML guide covering elements, forms, media, semantic layout, and accessibility.
Headings & Text
Headings give your page structure. Text tags let you style words to show importance, emphasis, or special meaning.
headings — h1 to h6
HTML
<!-- biggest — use only once per page -->
<h1>Main Page Title</h1>
<h2>Section Heading</h2>
<h3>Subsection Heading</h3>
<h4>Sub-subsection</h4>
<h5>Smaller heading</h5>
<!-- rarely used -->
<h6>Smallest heading</h6>Skipping heading levels (e.g. h1 → h4) confuses screen readers and hurts SEO. Always go in order.
paragraphs and line breaks
HTML
<p>First paragraph. Browser adds space around it.</p>
<p>Second paragraph. Starts on a new line automatically.</p>
<!-- <br> forces a line break INSIDE text -->
<p>
123 Main Street<br>
London, UK
</p>
<!-- horizontal divider -->
<hr/>text formatting — meaning vs appearance
HTML
<!-- meaningful — use for important content -->
<strong>Important warning!</strong>
<em>Please read carefully.</em>
<!-- visual only — no extra meaning -->
<b>Bold text</b>
<i>Italic text</i>
<u>Underlined text</u>
<!-- other useful tags -->
<mark>Highlighted text</mark>
<del>Crossed out</del>
<code>console.log("hello")</code>
<small>Fine print</small>
<!-- super and subscript -->
x<sup>2</sup>
H<sub>2</sub>Oblockquote and preformatted text
HTML
<!-- a quote from another source -->
<blockquote cite="https://example.com">
"The best way to predict the future
is to create it."
</blockquote>
<!-- pre preserves spaces and newlines exactly -->
<pre>
function hello() {
console.log("Hello!");
}
</pre>Links & Images
Links connect pages together. Images make pages visual. Both need a few key attributes to work well and stay accessible.
links — <a> tag
HTML
<!-- external website -->
<a href="https://example.com">Visit Example</a>
<!-- open in a new tab -->
<a href="https://example.com" target="_blank">
Open in new tab
</a>
<!-- another page in your site -->
<a href="/about.html">About Us</a>
<a href="./contact.html">Contact</a>
<!-- jump to a section on the same page -->
<a href="#features">Jump to Features</a>
<section id="features">...</section>
<!-- email and phone -->
<a href="mailto:[email protected]">Email us</a>
<a href="tel:+1234567890">Call us</a>Always write descriptive link text — never 'click here'. Screen readers read links out of context.
images — <img> tag
HTML
<!-- basic image -->
<img src="photo.jpg" alt="A sunset over the ocean" />
<!-- set width and height to prevent layout shift -->
<img
src="hero.jpg"
alt="Team at work"
width="800"
height="400"
/>
<!-- lazy load — only loads when near the screen -->
<img
src="gallery.jpg"
alt="Gallery item"
loading="lazy"
/>
<!-- ❌ bad alt — too vague -->
<img src="dog.jpg" alt="image" />
<!-- ✅ good alt — describes what's in the image -->
<img
src="dog.jpg"
alt="Golden retriever playing fetch in a park"
/>Always add width and height attributes — they prevent layout shift while the image loads.
figure and caption
HTML
<figure>
<img
src="chart.png"
alt="Bar chart showing sales growth 2020–2024"
/>
<figcaption>
Figure 1: Annual sales growth over 4 years.
</figcaption>
</figure>Lists
HTML has three types of lists: unordered (bullet points), ordered (numbered), and definition (term + description pairs).
ul and ol — bullet and numbered lists
HTML
<!-- unordered — bullet points -->
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
<!-- ordered — numbered -->
<ol>
<li>Preheat oven to 180°C</li>
<li>Mix the ingredients</li>
<li>Bake for 30 minutes</li>
</ol>
<!-- start from a different number -->
<ol start="5">
<li>Step five</li>
<li>Step six</li>
</ol>
<!-- nested list -->
<ul>
<li>Fruits
<ul>
<li>Apples</li>
<li>Bananas</li>
</ul>
</li>
</ul>dl — definition list
HTML
<dl>
<dt>HTML</dt>
<dd>
HyperText Markup Language —
the language used to structure web pages.
</dd>
<dt>CSS</dt>
<dd>
Cascading Style Sheets —
used to style and layout web pages.
</dd>
</dl>Semantic Structure
Semantic tags describe the purpose of content — not just how it looks. They help search engines, screen readers, and other developers understand your page.
page layout tags
HTML
<body>
<header>
<h1>My Website</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<section>
<h2>About Us</h2>
<p>We build great things.</p>
</section>
<article>
<h2>Latest Blog Post</h2>
<p>Today we launched something new...</p>
</article>
<aside>
<h3>Related Articles</h3>
</aside>
</main>
<footer>
<p>© 2024 My Website</p>
</footer>
</body>Use semantic tags instead of `<div>` everywhere — they make your page easier for search engines and screen readers to understand.
div and span — generic containers
HTML
<!-- div is BLOCK-level — full width, new line -->
<div class="card">
<h3>Product Name</h3>
<p>Description here.</p>
</div>
<!-- span is INLINE — flows with text -->
<p>
The price is
<span style="color: red; font-weight: bold;">
£9.99
</span>
today.
</p>Don't build an entire page with only divs. Use header, main, section, footer etc. — fall back to div only when nothing fits.
nav — navigation links
HTML
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>address — contact information
HTML
<!-- contact info for a person or organisation -->
<address>
<p>Written by <a href="mailto:[email protected]">Alice</a></p>
<p>
123 Main Street<br>
London, UK
</p>
<p><a href="tel:+441234567890">+44 1234 567890</a></p>
</address>Tables
Use tables for actual data that belongs in rows and columns — like a spreadsheet. Never use tables to control page layout.
basic table structure
HTML
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>30</td>
<td>London</td>
</tr>
<tr>
<td>Bob</td>
<td>25</td>
<td>Paris</td>
</tr>
</tbody>
</table>Never use tables for page layout — use CSS Flexbox or Grid instead. Tables are only for tabular data.
spanning rows and columns
HTML
<table>
<thead>
<tr>
<th>Product</th>
<!-- spans 2 columns -->
<th colspan="2">Sales</th>
</tr>
<tr>
<th></th>
<th>Q1</th>
<th>Q2</th>
</tr>
</thead>
<tbody>
<tr>
<!-- spans 2 rows -->
<td rowspan="2">Widget A</td>
<td>£1,200</td>
<td>£1,500</td>
</tr>
<tr>
<td>£1,800</td>
<td>£2,100</td>
</tr>
</tbody>
</table>Forms
Forms collect information from the user — like login, signup, or search. Every input needs a label so users know what to type.
basic form structure
HTML
<form action="/login" method="POST">
<!-- 'for' and 'id' must match -->
<label for="email">Email address</label>
<input
type="email"
id="email"
name="email"
required
/>
<label for="password">Password</label>
<input
type="password"
id="password"
name="password"
required
/>
<button type="submit">Log in</button>
<button type="reset">Clear</button>
</form>The 'for' on `<label>` must match the 'id' on `<input>` — this links them for screen readers and click behaviour.
text input types
HTML
<input type="text"
name="name"
placeholder="Full name"
/>
<input type="email"
name="email"
placeholder="[email protected]"
/>
<input type="password"
name="pass"
placeholder="Password"
/>
<input type="number"
name="age"
min="0"
max="120"
/>
<input type="tel"
name="phone"
placeholder="+44 1234 567890"
/>
<input type="url"
name="website"
placeholder="https://example.com"
/>date, file, range and other inputs
HTML
<!-- date and time -->
<input type="date" name="birthday" />
<input type="time" name="meeting" />
<!-- slider -->
<input
type="range"
name="volume"
min="0"
max="100"
value="50"
/>
<!-- colour picker -->
<input type="color" name="theme" value="#3b82f6" />
<!-- file upload -->
<input
type="file"
name="avatar"
accept="image/*"
/>
<!-- hidden — sent with form but not visible -->
<input type="hidden" name="userId" value="12345" />checkboxes, radio buttons, dropdowns, and textareas
HTML
<!-- checkboxes — any number -->
<fieldset>
<legend>Languages you use?</legend>
<input type="checkbox" id="js"
name="lang" value="javascript" />
<label for="js">JavaScript</label>
<!-- checked = ticked by default -->
<input type="checkbox" id="ts"
name="lang" value="typescript" checked />
<label for="ts">TypeScript</label>
</fieldset>
<!-- radio — pick only ONE -->
<fieldset>
<legend>Skill level?</legend>
<input type="radio" id="beginner"
name="level" value="beginner" />
<label for="beginner">Beginner</label>
<input type="radio" id="advanced"
name="level" value="advanced" />
<label for="advanced">Advanced</label>
</fieldset>
<!-- dropdown -->
<label for="country">Country</label>
<select id="country" name="country">
<option value="">-- Please choose --</option>
<option value="gb">United Kingdom</option>
<!-- selected = chosen by default -->
<option value="au" selected>Australia</option>
</select>
<!-- multi-line text box -->
<label for="message">Your message</label>
<textarea
id="message"
name="message"
rows="5"
placeholder="Type your message here..."
maxlength="500"
></textarea>input validation attributes
HTML
<!-- must be filled in -->
<input type="text" name="name" required />
<!-- character limits -->
<input type="text"
name="username"
minlength="3"
maxlength="20"
/>
<!-- number limits -->
<input type="number"
name="age"
min="18"
max="120"
/>
<!-- must match a regex pattern -->
<input type="text"
name="postcode"
pattern="[A-Z]{1,2}[0-9]{1,2} [0-9][A-Z]{2}"
placeholder="e.g. SW1A 1AA"
/>
<!-- browser fills in saved values -->
<input type="email"
name="email"
autocomplete="email"
/>Media — Video & Audio
HTML5 lets you embed video and audio directly without any plugins. Always include a text fallback for browsers that can't play it.
video and audio
HTML
<!-- video -->
<video
controls
width="640"
height="360"
poster="thumbnail.jpg"
muted
>
<!-- multiple formats for browser compatibility -->
<source src="video.mp4" type="video/mp4" />
<source src="video.webm" type="video/webm" />
Sorry, your browser doesn't support video.
</video>
<!-- audio -->
<audio controls>
<source src="podcast.mp3" type="audio/mpeg" />
<source src="podcast.ogg" type="audio/ogg" />
Your browser does not support audio.
</audio>embed a YouTube video
HTML
<!-- replace VIDEO_ID with the ID from the YouTube URL -->
<!-- youtube.com/watch?v=dQw4w9WgXcQ → use 'dQw4w9WgXcQ' -->
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/VIDEO_ID"
title="Video title"
allowfullscreen
></iframe>Head & Meta Tags
The <head> section is invisible to users but critical for SEO, social sharing, and telling browsers how to display your page.
essential meta tags
HTML
<head>
<!-- character encoding -->
<meta charset="UTF-8" />
<!-- makes your page fit on mobile -->
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<!-- browser tab + search result title -->
<title>My Page | My Site</title>
<!-- shows under title in search results -->
<meta
name="description"
content="A short description of this page."
/>
<!-- link to your CSS file -->
<link rel="stylesheet" href="style.css" />
<!-- small icon in the browser tab -->
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
</head>Keep your meta description under 160 characters — that's all search engines show in results.
Open Graph — how your page looks when shared
HTML
<head>
<!-- Facebook, LinkedIn, WhatsApp, Slack etc. -->
<meta property="og:title"
content="My Amazing Page" />
<meta property="og:description"
content="A short, enticing description." />
<meta property="og:image"
content="https://mysite.com/og-image.jpg" />
<meta property="og:url"
content="https://mysite.com/this-page" />
<meta property="og:type"
content="website" />
<!-- Twitter / X -->
<meta name="twitter:card"
content="summary_large_image" />
<meta name="twitter:title"
content="My Amazing Page" />
<meta name="twitter:description"
content="A short, enticing description." />
<meta name="twitter:image"
content="https://mysite.com/og-image.jpg" />
</head>Adding CSS & JavaScript
HTML, CSS, and JavaScript each live in their own file. Here's how to connect them to your HTML page.
linking CSS and JavaScript
HTML
<head>
<!-- CSS — always in <head> -->
<link rel="stylesheet" href="style.css" />
<!-- JS with defer — waits for HTML to load -->
<script src="main.js" defer></script>
<!-- async — loads immediately (analytics etc.) -->
<script src="analytics.js" async></script>
</head>
<body>
<h1>Hello</h1>
<!-- older pattern — JS at the bottom of body -->
<script src="main.js"></script>
</body>
<!-- inline CSS — avoid, hard to maintain -->
<p style="color: red; font-size: 18px;">Red text</p>Use `defer` on your `<script>` tags in `<head>` — it's cleaner than putting scripts at the bottom of `<body>`.
Accessibility
Accessible HTML works for everyone — including people using screen readers, keyboard navigation, or slow connections. Most of it is just using the right tags.
always label your inputs
HTML
<!-- ✅ 'for' matches the input's 'id' -->
<label for="username">Username</label>
<input type="text" id="username" name="username" />
<!-- ✅ wrap the input inside the label -->
<label>
Email address
<input type="email" name="email" />
</label>
<!-- ❌ no label — screen readers can't announce this -->
<input
type="text"
name="username"
placeholder="Username"
/>Never use placeholder as a label — it disappears when the user starts typing, leaving them with no reminder of what the field is for.
alt text and ARIA labels
HTML
<!-- ✅ descriptive alt -->
<img
src="team.jpg"
alt="Five team members smiling outside the office"
/>
<!-- ✅ empty alt for decorative images -->
<img src="divider.svg" alt="" />
<!-- ❌ bad alt -->
<img src="team.jpg" alt="image" />
<!-- aria-label for elements with no visible text -->
<button aria-label="Close menu">✕</button>
<!-- skip link — helps keyboard users jump past the menu -->
<a href="#main-content" class="skip-link">
Skip to main content
</a>
<main id="main-content">...</main>use semantic HTML first
HTML
<!-- ❌ div pretending to be a button -->
<div class="btn" onclick="doSomething()">
Click me
</div>
<!-- ✅ real button — keyboard + screen reader ready -->
<button type="button" onclick="doSomething()">
Click me
</button>
<!-- ❌ div pretending to be a link -->
<div onclick="window.location='/about'">About</div>
<!-- ✅ real link -->
<a href="/about">About</a>Never use `<div onclick=''>` as a button or link. Use real `<button>` and `<a>` elements — they come with accessibility built in.
role attribute basics
HTML
<!-- use when a native element isn't possible -->
<div role="button" tabindex="0">
Custom button
</div>
<!-- landmark roles — help screen readers navigate -->
<div role="navigation">...</div>
<div role="main">...</div>
<div role="complementary">...</div>
<!-- live regions — screen reader announces changes -->
<div role="alert">
<!-- content here announced immediately -->
Form submitted successfully!
</div>
<div role="status">
<!-- politely announced when screen reader is free -->
Loading results...
</div>
<!-- tooltip -->
<span role="tooltip" id="tip">
Must be at least 8 characters
</span>
<input aria-describedby="tip" type="password" />If you can use a native element like `<button>` or `<nav>`, do that instead. Roles don't add keyboard behaviour — only semantic meaning.
Responsive & Performance
These HTML attributes make your page load faster and look correct on any screen size — with no CSS or JavaScript needed.
responsive images — <picture> and srcset
HTML
<!-- picture: different image per screen size -->
<picture>
<source
srcset="hero-large.jpg"
media="(min-width: 800px)"
/>
<source
srcset="hero-medium.jpg"
media="(min-width: 400px)"
/>
<img src="hero-small.jpg" alt="Our team at work" />
</picture>
<!-- srcset: browser picks right resolution -->
<img
src="photo.jpg"
srcset="
photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w
"
sizes="(max-width: 600px) 400px, 800px"
alt="A mountain landscape"
/>lazy loading and preloading
HTML
<!-- lazy load images below the fold -->
<img
src="blog-post.jpg"
alt="Blog post thumbnail"
loading="lazy"
/>
<!-- iframes can also be lazy loaded -->
<iframe
src="map.html"
loading="lazy"
title="Location map"
></iframe>
<!-- preload critical resources in <head> -->
<head>
<!-- preload hero image — appears instantly -->
<link rel="preload" href="hero.jpg" as="image" />
<!-- preload a font — prevents invisible text -->
<link
rel="preload"
href="fonts/MyFont.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<!-- prefetch a page the user may visit next -->
<link rel="prefetch" href="/about.html" />
</head>Never lazy-load the hero image at the top of the page — it will make the page feel slow. Only lazy-load images further down.
Interactive Elements
HTML5 has built-in interactive elements that work without any JavaScript — great for FAQs, tooltips, and progress bars.
details & summary — accordion without JavaScript
HTML
<details>
<summary>What is HTML?</summary>
<p>HTML is the standard language for creating web pages.</p>
</details>
<details>
<summary>What is CSS?</summary>
<p>CSS controls the appearance — colours, fonts, layout.</p>
</details>
<!-- start open by default -->
<details open>
<summary>Already expanded</summary>
<p>This section is visible without clicking.</p>
</details>progress, datalist, and dialog
HTML
<!-- progress bar -->
<label for="upload">Upload progress:</label>
<progress id="upload" value="70" max="100"></progress>
<!-- indeterminate — animated loading bar -->
<progress></progress>
<!-- datalist — autocomplete suggestions -->
<label for="browser">Favourite browser:</label>
<input list="browsers" id="browser" name="browser" />
<datalist id="browsers">
<option value="Chrome" />
<option value="Firefox" />
<option value="Safari" />
<option value="Edge" />
</datalist>
<!-- dialog — native modal popup -->
<button onclick="
document.getElementById('myDialog').showModal()
">
Open dialog
</button>
<dialog id="myDialog">
<h2>Confirm action</h2>
<p>Are you sure you want to delete this item?</p>
<button onclick="
document.getElementById('myDialog').close()
">
Cancel
</button>
<button>Delete</button>
</dialog>Special Characters
Some characters have special meaning in HTML (like < and >). Use HTML entities to display them as text instead.
HTML entities — characters that need escaping
HTML
<!-- must-escape characters -->
< →
> → >
& → &
" → "
<!-- useful symbols -->
→ non-breaking space
© → ©
® → ®
™ → ™
€ → €
£ → £
<!-- example usage -->
<p>Tags look like <p> and </p>.</p>
<p>© 2024 My Company. All rights reserved.</p>
<p>Price: £9.99 (inc. VAT)</p>If you type `<` or `>` directly in text content, the browser may treat them as HTML tags. Always use `<` and `>` instead.
No login required to share feedback
More Cheatsheets
Keep your reference handy
Explore more zero-to-hero cheatsheets for the tools you use daily.