HTML (HyperText Markup Language) is the skeleton of every web page. This cheat sheet covers every tag you'll actually use — from document structure to forms — with examples and gotchas.
Quick reference
The 25 most-used HTML elements.
| Tag | Purpose | Example |
|---|---|---|
<!DOCTYPE html> |
Document type declaration | Required first line |
<html lang="en"> |
Root element | Wraps everything |
<head> |
Metadata container | Not rendered |
<title> |
Page title (tab + SEO) | <title>My Page</title> |
<meta> |
Metadata (charset, viewport) | <meta charset="UTF-8"> |
<link> |
External resources | <link rel="stylesheet" href="style.css"> |
<script> |
JavaScript | <script src="app.js" defer></script> |
<body> |
Page content | Visible content lives here |
<h1>–<h6> |
Headings | <h1> = largest, one per page |
<p> |
Paragraph | <p>Hello world</p> |
<a> |
Hyperlink | <a href="/about">About</a> |
<img> |
Image | <img src="cat.jpg" alt="A cat"> |
<ul> / <ol> |
Unordered / ordered list | <li> items inside |
<table> |
Tabular data | <tr>, <th>, <td> inside |
<form> |
User input | action + method attributes |
<input> |
Form field | type="text", "email", "checkbox" |
<button> |
Clickable button | <button type="submit">Send</button> |
<div> |
Generic block container | Layout / grouping |
<span> |
Generic inline container | Inline styling / JS hooks |
<header> |
Page / section header | Semantic landmark |
<nav> |
Navigation links | Semantic landmark |
<main> |
Primary content | One per page |
<section> |
Thematic content group | Use headings inside |
<article> |
Self-contained content | Blog post, card, comment |
<footer> |
Page / section footer | Semantic landmark |
Document structure
Every HTML file follows the same skeleton:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page description for SEO.">
<title>Page Title</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<h1>Main Heading</h1>
<p>Content goes here.</p>
</main>
<footer>
<p>© 2026 My Site</p>
</footer>
<script src="app.js" defer></script>
</body>
</html>
Key rules:
<!DOCTYPE html>must be the very first line — no whitespace before it.<html lang="en">sets the page language (important for screen readers and SEO).<meta charset="UTF-8">must come before<title>to prevent character encoding bugs.- Load scripts with
deferor at the bottom of<body>so they don't block rendering.
Text content
Headings
<h1>Page Title (one per page)</h1>
<h2>Section Heading</h2>
<h3>Subsection</h3>
<h4>Sub-subsection</h4>
<h5>Rarely needed</h5>
<h6>Almost never used</h6>
Use headings for document outline, not for font size. Style headings with CSS.
Inline text elements
<p>A paragraph of text with <strong>bold</strong> and <em>italic</em> words.</p>
<p>
Use <code>const x = 1</code> for inline code.
Keyboard shortcut: <kbd>Ctrl+S</kbd>.
Output example: <samp>Error: file not found</samp>.
Variable: <var>x</var>.
</p>
<p>H<sub>2</sub>O and E = mc<sup>2</sup></p>
<p><mark>Highlighted text</mark> and <s>strikethrough</s>.</p>
<abbr title="HyperText Markup Language">HTML</abbr>
<time datetime="2026-07-14">July 14, 2026</time>
<q cite="https://example.com">Inline quotation</q>
Block text elements
<blockquote cite="https://example.com">
A longer quotation pulled from another source.
</blockquote>
<pre><code>
function greet(name) {
return `Hello, ${name}!`;
}
</code></pre>
<address>
123 Main Street<br>
Podgorica, Montenegro
</address>
<hr> <!-- Thematic break / horizontal rule -->
<br> <!-- Line break (use sparingly — prefer CSS margins) -->
Links and images
Links (<a>)
<!-- Internal link -->
<a href="/about">About Us</a>
<!-- External link (open in new tab) -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External</a>
<!-- Email link -->
<a href="mailto:hello@example.com">Email Us</a>
<!-- Phone link -->
<a href="tel:+38267123456">Call Us</a>
<!-- Download link -->
<a href="/files/report.pdf" download>Download Report</a>
<!-- Anchor link (jump to section) -->
<a href="#section-2">Jump to Section 2</a>
<h2 id="section-2">Section 2</h2>
Always add rel="noopener noreferrer" on target="_blank" links — omitting it is a security vulnerability.
Images (<img>)
<!-- Always include alt text -->
<img src="hero.jpg" alt="Team working in office" width="800" height="450">
<!-- Decorative image (empty alt, screen readers skip it) -->
<img src="divider.svg" alt="">
<!-- Responsive image with srcset -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1600px"
alt="Mountain landscape"
loading="lazy"
>
<!-- Figure with caption -->
<figure>
<img src="chart.png" alt="Sales chart Q1 2026">
<figcaption>Figure 1: Q1 2026 sales by region.</figcaption>
</figure>
Lists
<!-- Unordered list -->
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
<!-- Ordered list -->
<ol start="1" type="1"> <!-- type: 1, A, a, I, i -->
<li>First step</li>
<li>Second step</li>
<li>Third step</li>
</ol>
<!-- Nested list -->
<ul>
<li>Frontend
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</li>
<li>Backend</li>
</ul>
<!-- Description list (term + definition) -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language — the structure of web pages.</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets — the appearance of web pages.</dd>
</dl>
Tables
Use <table> for tabular data only — never for layout.
<table>
<caption>Monthly Sales</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Revenue</th>
<th scope="col">Units</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>€12,000</td>
<td>240</td>
</tr>
<tr>
<td>February</td>
<td>€15,500</td>
<td>310</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>€27,500</td>
<td>550</td>
</tr>
</tfoot>
</table>
| Attribute | Purpose |
|---|---|
colspan="2" |
Span 2 columns |
rowspan="3" |
Span 3 rows |
scope="col" |
Header applies to column (accessibility) |
scope="row" |
Header applies to row (accessibility) |
Forms
<form action="/submit" method="post" novalidate>
<!-- Text inputs -->
<label for="name">Full name</label>
<input type="text" id="name" name="name" placeholder="Jane Doe" required autocomplete="name">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="password">Password</label>
<input type="password" id="password" name="password" minlength="8" required>
<!-- Number + range -->
<input type="number" name="qty" min="1" max="99" value="1">
<input type="range" name="volume" min="0" max="100" step="10" value="50">
<!-- Dates -->
<input type="date" name="dob">
<input type="time" name="appt">
<input type="datetime-local" name="meeting">
<!-- File upload -->
<input type="file" name="avatar" accept="image/*" multiple>
<!-- Checkbox and radio -->
<input type="checkbox" id="agree" name="agree" value="yes">
<label for="agree">I agree to the terms</label>
<fieldset>
<legend>Preferred contact</legend>
<input type="radio" id="email-pref" name="contact" value="email">
<label for="email-pref">Email</label>
<input type="radio" id="phone-pref" name="contact" value="phone">
<label for="phone-pref">Phone</label>
</fieldset>
<!-- Select -->
<label for="country">Country</label>
<select id="country" name="country">
<optgroup label="Europe">
<option value="me">Montenegro</option>
<option value="rs">Serbia</option>
</optgroup>
<option value="us">United States</option>
</select>
<!-- Textarea -->
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" cols="40"></textarea>
<!-- Datalist (autocomplete suggestions) -->
<input type="text" name="city" list="cities">
<datalist id="cities">
<option value="Podgorica">
<option value="Bar">
<option value="Budva">
</datalist>
<!-- Hidden field -->
<input type="hidden" name="csrf_token" value="abc123">
<!-- Buttons -->
<button type="submit">Submit</button>
<button type="reset">Reset</button>
<button type="button" id="cancel">Cancel</button>
</form>
Input types reference
| Type | Use case |
|---|---|
text |
Generic single-line text |
email |
Email address (validated) |
password |
Masked text |
number |
Numeric value |
tel |
Phone number (no validation) |
url |
URL (validated) |
search |
Search box |
date |
Calendar date picker |
time |
Time picker |
datetime-local |
Date + time without timezone |
month |
Month + year |
week |
Week + year |
color |
Color picker |
range |
Slider |
file |
File upload |
checkbox |
Boolean toggle |
radio |
One of many options |
hidden |
Not shown, sent on submit |
submit |
Submit button |
reset |
Reset form button |
button |
Generic clickable button |
Semantic elements
HTML5 semantic elements give meaning to your markup, helping search engines and screen readers understand page structure.
<header> <!-- Page or section header — can appear multiple times -->
<nav> <!-- Primary navigation -->
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main> <!-- One per page — the primary content -->
<article> <!-- Self-contained: blog post, news article, card -->
<header>
<h1>Article Title</h1>
<p>By <address><a rel="author" href="/author">Jane</a></address></p>
</header>
<section> <!-- Thematic section inside article -->
<h2>Introduction</h2>
<p>...</p>
</section>
<aside> <!-- Tangentially related: pull quote, ad, sidebar -->
<p>Related: ...</p>
</aside>
</article>
</main>
<footer> <!-- Page or section footer -->
<p>© 2026</p>
</footer>
| Element | Use when |
|---|---|
<header> |
Introductory content or navigation for page/section |
<nav> |
Major navigation links |
<main> |
The dominant content of the page (one per document) |
<article> |
Self-contained, reusable content |
<section> |
Thematic group with a heading |
<aside> |
Supplementary content (sidebar, callout box) |
<footer> |
Closing content, copyright, links |
<figure> |
Image, chart, code block with optional caption |
<figcaption> |
Caption for <figure> |
<details> + <summary> |
Disclosure widget (accordion) |
<dialog> |
Modal or dialog box |
<mark> |
Highlighted / search-result text |
<time> |
Machine-readable date/time |
Media elements
<!-- Video -->
<video controls width="640" height="360" poster="thumbnail.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
Your browser does not 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>
<!-- Inline SVG -->
<svg width="100" height="100" viewBox="0 0 100 100" aria-label="Red circle" role="img">
<circle cx="50" cy="50" r="40" fill="red"/>
</svg>
<!-- Embedded iframe -->
<iframe
src="https://www.openstreetmap.org/export/embed.html?..."
width="600"
height="400"
loading="lazy"
title="Map of Podgorica"
></iframe>
Meta tags (SEO and social)
<head>
<!-- Essentials -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="155-char page description for search results.">
<title>Page Title – Site Name</title>
<link rel="canonical" href="https://example.com/page/">
<!-- Open Graph (Facebook, LinkedIn) -->
<meta property="og:title" content="Page Title">
<meta property="og:description" content="Description for social cards.">
<meta property="og:image" content="https://example.com/og-image.jpg">
<meta property="og:url" content="https://example.com/page/">
<meta property="og:type" content="article">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Page Title">
<meta name="twitter:description" content="Description for Twitter.">
<meta name="twitter:image" content="https://example.com/og-image.jpg">
<!-- Favicons -->
<link rel="icon" href="/favicon.ico">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<!-- Preload critical assets -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://fonts.googleapis.com">
</head>
Common mistakes
| Mistake | Problem | Fix |
|---|---|---|
Missing alt on <img> |
Inaccessible; SEO penalty | Always add alt="" (empty for decorative) |
<div> instead of semantic elements |
No meaning for screen readers/SEO | Use <nav>, <main>, <article>, etc. |
<br> for spacing |
Structural hack | Use CSS margin / padding instead |
<table> for layout |
Inaccessible; not responsive | Use CSS Grid or Flexbox |
<b> / <i> for emphasis |
Presentational only | Use <strong> / <em> for meaning |
target="_blank" without rel |
Tabnapping vulnerability | Always add rel="noopener noreferrer" |
<label> not connected to input |
Inaccessible (unclickable label) | Use matching for + id, or nest <input> inside <label> |
Duplicate id attributes |
Breaks CSS, JS, accessibility | IDs must be unique per page |
Frequently asked questions
What is the difference between <div> and <span>?
<div> is a block-level container (starts on a new line, full width). <span> is an inline container (flows in text). Both are semantic-free — use semantic elements first, then <div>/<span> for styling hooks.
When should I use <section> vs <div>?
Use <section> when the content has a heading and represents a thematic group meaningful to the page outline. Use <div> for purely visual grouping with no semantic meaning.
What's the difference between <strong> and <b>?
<strong> conveys importance (screen readers may stress it). <b> is stylistically bold with no semantic meaning. Prefer <strong> for important content; use CSS font-weight: bold for purely visual bold.
Do I need to close void elements like <img>, <br>, <input>?
In HTML5: no. <img src="..." alt=""> is valid. The self-closing slash (<img />) is optional and mostly a JSX/XHTML habit — both work.
What is defer vs async on <script>?
Both download the script without blocking HTML parsing. defer runs the script after parsing is complete, in order. async runs it as soon as downloaded, in any order. Use defer for most scripts; async only for independent scripts like analytics.
How do I make a page accessible?
Key steps: use semantic HTML (not <div> for everything), always provide alt text on images, connect <label> to <input>, ensure keyboard navigability, use sufficient color contrast, and test with a screen reader.