HTML Exercises
Practise what you've learned. Type the missing piece into each highlighted gap and press Check. Further down are build challenges with live editors and model solutions.
Fill in the blanks
Document basics
Declare the document type for modern HTML.
<!DOCTYPE >
<!DOCTYPE html> is always the first line (lesson 03).
Set the page language to English.
<html ="en">
lang helps screen readers and translation tools (lesson 03).
Declare the character encoding.
<meta ="utf-8">
UTF-8 supports every language and emoji (lesson 03).
Give the page a title shown in the browser tab.
<>My Recipes</title>
The <title> is required (lesson 03).
Make the page display at the right size on phones.
<meta name="" content="width=device-width, initial-scale=1">
The viewport meta tag is essential for mobile (lesson 43).
Text and links
Use the most important heading level.
<>Welcome to my site</h1>
Use one <h1> per page (lesson 06).
Mark the text as strongly important.
<p><>Warning:</strong> hot surface.</p>
<strong> conveys importance (lesson 07).
Write the attribute that holds a link's destination.
<a ="https://developer.mozilla.org">MDN</a>
href = hypertext reference (lesson 10).
Link to the element with id "contact" on the same page.
<a href="">Contact us</a>
A # followed by an id links to a fragment (lesson 10).
Show a literal less-than sign in text.
<p>5 10</p>
< displays < (lesson 09).
Images and media
Add the text alternative for the image.
<img src="dog.jpg" ="A puppy chasing a ball" width="400" height="300">
alt is required on every image (lesson 12).
Load the image only when the user scrolls near it.
<img src="gallery.jpg" alt="Market stall" width="600" height="400" loading="">
Lazy-load images below the fold (lesson 45).
Show playback controls on the video.
<video src="clip.mp4" width="640"></video>
Without controls, users can't play the video (lesson 16).
Add a caption to the figure.
<figure> <img src="chart.png" alt="Sales doubled in 2026" width="600" height="300"> <>Figure 1: annual sales</figcaption> </figure>
<figcaption> captions a figure (lesson 14).
Structure
Create a numbered list.
<> <li>Preheat the oven</li> <li>Mix the batter</li> </ol>
<ol> is for ordered lists (lesson 18).
Make the first row's cells into header cells.
<tr><>Name</th><th>Score</th></tr>
<th> marks header cells (lesson 19).
Make the cell span two columns.
<td ="2">Total</td>
colspan and rowspan merge cells (lesson 20).
Wrap the page's primary content in the right landmark.
<> <h1>Latest news</h1> </main>
There's one <main> per page (lesson 24).
Mark up a self-contained blog post.
<> <h2>My trip to Porto</h2> <p>…</p> </article>
<article> is for content that stands on its own (lesson 24).
Give the element a class for styling.
<p ="note">Remember to save.</p>
Classes group elements for CSS (lesson 23).
Forms
Connect the label to the input.
<label ="email">Email</label> <input id="email" name="email" type="email">
for matches the input's id (lesson 29).
Choose the input type that validates email addresses.
<input id="e" name="email" type="">
Phones also show an @ key (lesson 27).
Make the field mandatory.
<input id="n" name="name" >
required blocks empty submissions (lesson 32).
Group the radio buttons with a caption.
<fieldset> <>Size</legend> <label><input type="radio" name="size" value="s"> Small</label> </fieldset>
A legend names a fieldset (lesson 29).
Stop this button from submitting the form.
<button type="">Show password</button>
Buttons in forms submit by default (lesson 31).
Send the form data in the request body rather than the URL.
<form action="/signup" method="">
Use POST for data that changes something (lesson 33).
Let the browser autofill the user's email.
<input id="m" name="email" type="email" autocomplete="">
autocomplete speeds up forms (lesson 28).
Modern HTML
Make this element a popover.
<div id="menu" >Menu items…</div>
The popover attribute creates a top-layer pop-up (lesson 38).
Add the always-visible toggle text for a disclosure widget.
<details> <>Show answer</summary> <p>42</p> </details>
<summary> is the clickable label (lesson 39).
Hide this decorative icon from screen readers.
<span aria-hidden="">★</span>
aria-hidden="true" removes it from the accessibility tree (lesson 44).
Build challenges
1. A recipe card
Build a recipe with a heading, a photo with a caption, an ingredients list and numbered steps.
Show a model solution
<article> <h2>Avocado toast</h2> <figure> <img src="https://picsum.photos/id/1080/320/200" alt="Toast topped with avocado and chilli flakes" width="320" height="200"> <figcaption>Ready in 5 minutes.</figcaption> </figure> <h3>Ingredients</h3> <ul> <li>1 slice of sourdough</li> <li>½ ripe avocado</li> <li>Salt, pepper and chilli flakes</li> </ul> <h3>Method</h3> <ol> <li>Toast the bread.</li> <li>Mash the avocado and spread it on top.</li> <li>Season to taste.</li> </ol> </article>
2. A timetable
Build an accessible table of three classes with day and time columns, a caption and header cells with scope.
Show a model solution
<table> <caption>Gym classes this week</caption> <thead> <tr><th scope="col">Class</th><th scope="col">Day</th><th scope="col">Time</th></tr> </thead> <tbody> <tr><th scope="row">Yoga</th><td>Monday</td><td>18:00</td></tr> <tr><th scope="row">Spin</th><td>Wednesday</td><td>07:30</td></tr> <tr><th scope="row">Pilates</th><td>Friday</td><td>12:15</td></tr> </tbody> </table>
3. A sign-up form
Build a form with name, email and password fields (all required, all labelled), a "plan" radio group in a fieldset, a terms checkbox and a submit button.
Show a model solution
<form action="/signup" method="post"> <p><label for="su-name">Name</label><br><input id="su-name" name="name" autocomplete="name" required></p> <p><label for="su-email">Email</label><br><input id="su-email" name="email" type="email" autocomplete="email" required></p> <p><label for="su-pw">Password</label><br><input id="su-pw" name="password" type="password" minlength="10" autocomplete="new-password" required></p> <fieldset> <legend>Plan</legend> <label><input type="radio" name="plan" value="free" checked> Free</label> <label><input type="radio" name="plan" value="pro"> Pro</label> </fieldset> <p><label><input type="checkbox" name="terms" required> I accept the terms</label></p> <button type="submit">Create account</button> </form>
4. A semantic page skeleton
Create a page with a header containing a site name and navigation list, a main area with one article that has its own header and two sections, an aside, and a footer.
Show a model solution
<header> <p><strong>Travel Notes</strong></p> <nav aria-label="Main"> <ul> <li><a href="#home">Home</a></li> <li><a href="#trips">Trips</a></li> </ul> </nav> </header> <main> <article> <header> <h1>A weekend in Porto</h1> <p>Published <time datetime="2026-10-06">6 October 2026</time></p> </header> <section> <h2>Where to stay</h2> <p>Ribeira is lively; Bonfim is quieter.</p> </section> <section> <h2>What to eat</h2> <p>Try a francesinha at least once.</p> </section> </article> <aside> <h2>Related</h2> <p><a href="#lisbon">Three days in Lisbon</a></p> </aside> </main> <footer> <p>© 2026 Travel Notes</p> </footer>