Every page you build will use these three elements. A nav is a list of links. A blog post is paragraphs, images, and links. A product page is a gallery of images, a spec list, and links to related items. Learn them properly once — ordered vs unordered lists, internal vs external links, and alt text that actually describes the image — and every page after this gets easier.
Three list types: <ul> (unordered, bullet points), <ol> (ordered, numbered), <dl> (definition lists, rarely used). Links: <a href="..."> with internal (/about), external (https://...), or anchor (#section) targets. Images: <img src="..." alt="..."> — alt is required, and it should describe the image content, not say "image of X". Wrap an image in <figure> when it needs a caption.
Before this lesson: complete Lesson 2. You need to know the semantic elements — lists and links live inside them.
📋 Lists — unordered, ordered, definition
Three list types. Two you'll use constantly. One you'll use rarely.
HTML
<!-- Unordered list — items without a specific order -->
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
<lt;/ul>
<!-- Ordered list — items with a meaningful sequence -->
<ol>
<li>Preheat oven to 350°F</li>
<li>Mix flour and sugar</li>
<li>Bake for 25 minutes</li>
</ol>
<!-- Nested list — list inside a list -->
<ul>
<li>Fruits
<ul>
<li>Apples</li>
<li>Bananas</li>
</ul>
</li>
<li>Vegetables
<ul>
<li>Carrots</li>
<li>Broccoli</li>
</ul>
</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 styling of web pages</dd>
</dl>
<ul>
Unordered list. Bullet points. Use for: navigation menus, feature lists, related links, tags, any group where order doesn't matter. The most common list type by far.
<ol>
Ordered list. Numbers. Use for: step-by-step instructions, ranked results, top-N lists, legal clauses. Order matters — reordering breaks the meaning.
<dl>
Description list. Pairs of terms and definitions. Use for: glossaries, product specs, FAQ summaries, metadata. Each <dt> (term) is followed by one or more <dd> (definitions).
Nesting lists
Put the nested <ul> or <ol> inside an <li>, not directly inside the parent list. The browser indents automatically. Don't mix <ul> and <ol> — a bulleted list inside a numbered list is fine, but the meaning should match.
Navigation menus are lists. Every real navigation uses a <ul> inside a <nav>. Screen readers announce "list, 5 items" and users can navigate item by item. Styling with CSS removes the bullets and displays them horizontally — that's how every horizontal nav bar works. The markup is a list; only the styling makes it look like a bar.
🔗 Links — the fabric of the web
Three kinds: internal, external, and anchor. Each has different rules.
HTML
<!-- Internal link — same site -->
<a href="/about.html">About Us</a>
<a href="../contact.html">Contact</a>
<!-- External link — different website -->
<a href="https://developer.mozilla.org">MDN</a>
<!-- External link — new tab + security -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
Visit Example
</a>
<!-- Anchor link — jump to a section on this page -->
<a href="#features">Jump to features</a>
...
<section id="features">
<h2>Features</h2>
</section>
<!-- Email link -->
<a href="mailto:hello@example.com">Email us</a>
<!-- Phone link -->
<a href="tel:+15551234567">Call us</a>
<!-- Download link -->
<a href="/files/report.pdf" download>Download report</a>
<!-- Linking to a specific section of another page -->
<a href="/docs/install.html#windows">Windows install instructions</a>
Internal links
Start with / (from site root) or ./ (current folder) or ../ (parent folder). Use relative URLs so the site works on any domain. Every internal link is a potential SEO signal.
External links
Full URLs with https://. Add target="_blank" so they open in a new tab. Add rel="noopener noreferrer" for security. Without noopener, the external page can access window.opener and redirect your original tab.
Anchor links
href="#section-id" jumps to the element with that ID. Use for table-of-contents, "back to top" links, and internal navigation. The ID must be unique and start with a letter.
Special links
mailto: opens the email client. tel: opens the phone dialer on mobile. download attribute prompts a file download instead of opening. Each is one line — no JavaScript needed.
Never use "click here" as link text. Screen readers can navigate between links — and if every link says "click here", a blind user has no idea where any of them go. Descriptive text like "Read the HTML installation guide" tells everyone where the link leads. It's also better for SEO: Google uses anchor text to understand what the destination page is about.
target="_blank" for external, same tab for internal. Users expect external links to open in new tabs (they don't want to lose your site). They expect internal links to stay in the same tab (clicking "About" shouldn't open a new tab). Follow this convention — it's what every major site does.
🖼️ Images — and alt text that matters
The element that breaks accessibility most often. And the easiest to get right.
HTML
<!-- Basic image -->
<img src="/images/photo.jpg" alt="A golden retriever running on a beach">
<!-- Decorative image — empty alt -->
<img src="/images/divider.png" alt="">
<!-- Logo — alt describes the brand -->
<img src="/images/logo.svg" alt="Acme Corp">
<!-- Image with explicit size (prevents layout shift) -->
<img src="/images/photo.jpg" alt="Sunset over mountains"
width="800" height="600">
<!-- Lazy loading — defer offscreen images -->
<img src="/images/photo.jpg" alt="Sunset" loading="lazy">
<!-- Responsive images — different files for different screen sizes -->
<img
src="/images/photo-small.jpg"
srcset="/images/photo-small.jpg 480w,
/images/photo-medium.jpg 960w,
/images/photo-large.jpg 1440w"
sizes="(max-width: 600px) 480px, 960px"
alt="Sunset over mountains"
loading="lazy">
<!-- Image as a link -->
<a href="/">
<img src="/images/logo.svg" alt="Home">
</a>
Alt text — the three cases.
1. Meaningful image: describe what's shown. alt="Red wallet, front view". Not "image of wallet", not "wallet.jpg". The content the image conveys.
2. Functional image (like a logo link): describe the destination. alt="Home" for a logo that links home. Not "logo".
3. Decorative image:alt="". Empty, not missing. Empty means "ignore this, it's pure decoration." Missing means "you forgot."
alt is required
Every <img> needs an alt attribute — even if it's empty. A missing alt fails accessibility validators and screen readers announce the filename instead. Always include it.
width and height
Always include width and height. This reserves space before the image loads, preventing layout shift (the content jumping as images arrive). Google tracks this as CLS — Cumulative Layout Shift.
loading="lazy"
Tells the browser to defer loading until the image is near the viewport. For pages with many images (galleries, long articles), this dramatically improves load time. Add it to every image below the fold.
srcset
Provides multiple image files at different sizes. The browser picks the best one for the user's screen — small on phones, large on desktop. Saves bandwidth, loads faster.
📸 figure & figcaption — images with captions
When an image needs a caption, wrap it in a figure.
HTML
<!-- Image with a caption -->
<figure>
<img src="/images/chart.png"
alt="Q3 revenue grew 20% over Q2"
width="800" height="600">
<figcaption>Q3 revenue growth compared to previous quarters.</figcaption>
</figure>
<!-- Code block with caption (yes, figure works for any content) -->
<figure>
<pre><code>const greeting = "Hello, world";</code></pre>
<figcaption>A basic JavaScript greeting.</figcaption>
</figure>
<!-- Blockquote with attribution -->
<figure>
<blockquote>
<p>The best way to predict the future is to invent it.</p>
</blockquote>
<figcaption>— Alan Kay</figcaption>
</figure>
<!-- Multiple images in one figure -->
<figure>
<img src="/images/before.jpg" alt="Before: empty lot">
<img src="/images/after.jpg" alt="After: finished house">
<figcaption>The lot before and after construction.</figcaption>
</figure>
When to use figure
When the image needs a caption that adds meaning. A photo credit, a chart description, a before/after comparison. Not every image needs a figure — only ones where the caption is important to understanding.
figure isn't only for images
figure can wrap code blocks, blockquotes, video, and any content that pairs with a caption. It's a semantic wrapper for "content plus its caption" — not just an image tag.
figcaption is optional
A figure doesn't require a figcaption. It's for when the caption matters. If there's no meaningful caption, skip the figure — just use a plain <img>.
Accessibility bonus
Screen readers announce "figure" before the content, then the caption after. This gives context about what the image is for — not just what it shows.
Alt text vs figcaption — they're different. Alt text describes the image content for someone who can't see it. Figcaption is a caption visible to everyone — it adds editorial context. Both can coexist. Example: alt="A bar chart showing Q3 revenue grew 20% over Q2" (accessibility) plus figcaption="Q3 2026 financial report" (editorial context).
💻 Build something — a complete recipe page
Everything from this lesson in one working example.
recipe.html
<!DOCTYPE html>
Classic Chocolate Chip Cookies
Classic Chocolate Chip Cookies
Prep time: 15 min · Cook time: 12 min · Makes 24 cookies
These cookies come out crisp on the edges and soft in the middle.
Ingredients
<ul>
<li>2¼ cups all-purpose flour</li>
<li>1 tsp baking soda</li>
<li>1 tsp salt</li>
<li>1 cup butter, softened</li>
<li>¾ cup granulated sugar</li>
<li>¾ cup brown sugar</li>
<li>2 large eggs</li>
<li>2 cups chocolate chips</li>
</ul>
Instructions
<ol>
<li>Preheat oven to 375°F (190°C).</li>
<li>Mix flour, baking soda, and salt in a bowl.</li>
<li>Beat butter and sugars until creamy.</li>
<li>Add eggs one at a time, beating well.</li>
<li>Gradually add the flour mixture.</li>
<li>Stir in chocolate chips.</li>
<li>Drop by rounded tablespoons onto ungreased baking sheets.</li>
<li>Bake 9–11 minutes until golden brown.</li>
</ol>
Notice the pattern. Ingredients are an unordered list (order doesn't matter). Instructions are an ordered list (step 3 makes no sense before step 2). The image has an alt and a figcaption. External links have target="_blank" and rel="noopener noreferrer". Every element is semantic. This is what a real recipe page looks like.
🏆 Challenge
Three tasks. Each one exercises a different element.
Task 1 — Fix broken links
Here are four links with problems. Fix each one:
1. <a href="http://example.com">Click here</a> — external, needs new tab and security
2. <a href="/about">click here</a> — bad link text
3. <a href="#features">Skip</a> — describes the action, not the destination
4. <a href="javascript:void(0)">Download</a> — dead link pretending to work
Rewrite each with descriptive text, correct target, and rel attributes. Make sure the anchor link actually points to a section that exists.
Task 2 — Add alt text
Write appropriate alt text for each of these situations:
1. A logo that links to the homepage
2. A photo of a specific dish on a restaurant menu
3. A chart showing monthly revenue
4. A decorative divider line
5. A product photo of a red t-shirt with a cat graphic on it
For each, decide whether the image is meaningful, functional, or decorative. Then write the alt attribute accordingly.
Task 3 — Build a product page
Build a single product page with these elements:
1. Product name as <h1>
2. Product image in a <figure> with caption
3. Price and rating
4. <h2> "Description" with paragraph
5. <h2> "Specifications" with a <dl> (dimensions, weight, material)
6. <h2> "Related Products" with a <ul> of links (external or internal)
7. A "Buy Now" button (use <a> for now)
8. Footer with copyright and a "Return to homepage" link
Every image must have alt text. Every list must be the right type. Every link must have descriptive text.
⚠️ Common mistakes
The list, link, and image bugs that catch every beginner.
1. Using <ul> when order matters
Step-by-step instructions in a <ul> look like a bulleted list, but the order is the point. Fix: use <ol> — the browser numbers them and screen readers announce "step 1, step 2".
2. Putting anything except <li> inside <ul>/<ol>
The only valid child of <ul> or <ol> is <li>. Adding text or other elements directly breaks semantics. If you need extra content, put it inside an <li>.
3. Missing alt on images
Every <img> needs alt. Missing alt fails accessibility and screen readers announce the filename instead. Use alt="" for decorative images, but never skip it entirely.
4. Using "click here" as link text
Screen readers can navigate between links — and "click here" gives no indication of where the link goes. Fix: descriptive text like "Read the HTML installation guide". Better for users, better for SEO.
5. Not using target="_blank" on external links
External links without target="_blank" take users away from your site in the same tab. They lose their place. Fix: add target="_blank" rel="noopener noreferrer" to every external link.
6. Using relative links for external sites
href="example.com" without https:// is treated as a relative URL — the browser looks for example.com in the current folder. Always include the full protocol on external links.
7. Anchor links pointing to nothing
href="#section" when no element has id="section" does nothing — the page doesn't scroll. Check that every anchor link points to a real ID.
8. Forgetting width and height on images
Without dimensions, the page reflows as images load — content jumps around. This is a "layout shift" (Google tracks it as CLS). Fix: always include width and height — or use CSS aspect-ratio.
➡️ What's next
You can build content pages. Next: forms that collect data.
ul is an unordered list — items without a specific order. Browsers show bullet points. ol is an ordered list — items with a meaningful sequence. Browsers show numbers. Use ul for navigation menus and feature lists. Use ol for step-by-step instructions and ranked results.
What is the difference between internal and external links?
Internal links point to pages on the same site — a href='/about.html'. External links point to other websites — a href='https://example.com'. External links should usually have target='_blank' and rel='noopener noreferrer' for security. Internal links should stay in the same tab.
What should alt text say on an image?
Alt text should describe what the image shows — not 'image' or 'photo of X'. Describe the content the image is meant to convey. For decorative images: alt='' (empty). Never skip alt entirely — a missing alt is different from an empty alt to screen readers.
How do I link to a section on the same page?
Use an anchor link with a hash. Add id='section-name' to the target element, then link to href='#section-name'. Clicking the link scrolls to that element. This is how table-of-contents links work. The id must be unique and start with a letter.
What is the difference between img and figure?
img is the actual image element — the image itself. figure is a semantic wrapper that pairs an image with a caption. Use figure when the image needs a caption (photo credit, chart description). Not every image needs a figure.
What is the difference between absolute and relative URLs?
An absolute URL includes the protocol and domain: https://example.com/about.html. A relative URL is interpreted relative to the current page: /about.html (from site root) or about.html (from current folder). Use absolute URLs for external links, relative URLs for internal links.
Should external links open in a new tab?
Yes, usually. Add target='_blank' to open external links in a new tab. Also add rel='noopener noreferrer' — noopener prevents the new page from accessing window.opener. For internal links, don't use target='_blank' — users expect same-tab navigation within a site.
What are responsive images in HTML?
Responsive images serve different image files based on the user's screen size. Use srcset to list image variants and sizes so the browser picks the best one: img srcset='small.jpg 480w, large.jpg 1440w'. This saves bandwidth on mobile and improves loading speed dramatically.