HTML describes what things are: this is a heading, this is a paragraph, this is a link. It does not describe how they look — that is CSS’s job.
<h1>My page</h1>
<p>Some text with a <a href="/about/">link</a> in it.</p>The skeleton#
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page title shown in the browser tab</title>
<meta name="description" content="One sentence about this page.">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- everything visible goes here -->
<script src="app.js" defer></script>
</body>
</html>Two lines matter more than they look:
lang="en"tells screen readers which language to pronounce- The
viewportmeta tag is what makes a page work on phones. Without it, mobile browsers render at a fake desktop width and your media queries never fire.
Text#
<h1>One per page — the main subject</h1>
<h2>A major section</h2>
<h3>A subsection</h3>
<p>A paragraph with <strong>important</strong> and <em>emphasised</em> text.</p>
<ul>
<li>An unordered item</li>
</ul>
<ol>
<li>A numbered item</li>
</ol>Use heading levels in order and do not skip them. Do not pick h3 because it looks the right size — change the size in CSS instead.
Links and images#
<a href="/about/">About us</a>
<a href="https://example.com" target="_blank" rel="noopener">External site</a>
<a href="mailto:you@example.com">Email us</a>
<a href="#contact">Jump to a section on this page</a>
<img src="cat.jpg" alt="A ginger cat asleep on a keyboard" width="600" height="400">Three habits worth forming:
- Link text should make sense alone. “Read the pricing guide”, not “click here”.
altdescribes the image for people who cannot see it. Usealt=""for purely decorative images.widthandheightstop the page jumping around as images load.
Semantic structure#
<header>
<nav>...</nav>
</header>
<main>
<article>
<h1>Post title</h1>
<section>...</section>
</article>
<aside>Related links</aside>
</main>
<footer>...</footer>These behave exactly like a div visually. The difference is that search engines and screen readers understand them. A screen-reader user can jump straight to main; with divs, they cannot.
Use a div when you need a box purely for styling and no existing element fits.
Forms#
<form action="/subscribe" method="post">
<label for="email">Email address</label>
<input type="email" id="email" name="email" required autocomplete="email">
<label for="plan">Plan</label>
<select id="plan" name="plan">
<option value="free">Free</option>
<option value="pro">Pro</option>
</select>
<button type="submit">Subscribe</button>
</form>The for on the label must match the id on the input. That link is what lets someone tap the label to focus the field, and what tells a screen reader which label belongs to which box. It is the single most-skipped accessibility detail in web development.
Using the right type matters too — type="email" brings up the right keyboard on a phone and gives free validation.
Attributes worth knowing#
<div class="card featured"> <!-- for CSS and JS, reusable -->
<div id="main-nav"> <!-- unique on the page -->
<li data-id="42"> <!-- your own data, read in JS -->
<button aria-label="Close">×</button> <!-- name for screen readers -->Questions people ask#
Is HTML a programming language?
No. It has no logic, decisions or loops. It is a markup language — it labels content. That does not make it less essential.
Do I need to close every tag?
Most, yes. A few are self-closing: img, br, input, meta, link. Unclosed tags cause layout bugs that are very hard to spot.
What about HTML5?
HTML5 is just the current version. When people say it, they usually mean the semantic elements and the built-in audio, video and form types.
Where to go next#
- CSS basics explained
- Build a portfolio page
- Why is my HTML not showing correctly? — a troubleshooting checklist