Exercise: Speed Up the Travel Blog

Make a slow travel blog fast and friendly to screen readers, with alt text by purpose, width and height, lazy loading, srcset and a picture element, and measure the difference.

Journeyman · HTML · Web Development · Updated

Marisol writes Postcards from the Coast, a travel blog, and her newest post is beautiful on her laptop. On her phone, out on the coast with one bar of signal, it barely loads. The post shows six photos straight from her phone, several megabytes each, and most of them have no useful alt text. Her friend who uses a screen reader hears "image of lighthouse", a file name, and the same sentence twice.

Your job: fix the page's pictures, using everything in this chapter, without changing a word of the story. Tests check each step, and the browser's Network panel shows you how much lighter the page gets.

Get the exercise code

In the Exercise box beside the lesson, choose Get the starter on GitHub to open its GitHub repository. Click Code, then Download ZIP, and unzip it into the folder where you keep your practice projects. Open the folder in VS Code.

What's in it:

  • index.html: the blog post, and the only file you change. The comment at its top lists the five steps.
  • style.css: the page's styles, ready to use. Its img rule lets pictures shrink to fit a narrow screen.
  • images/originals/: the six photos as they came off the phone.
  • images/: every photo already resized for you, in three widths (480, 960 and 1600 pixels) and three formats (.jpg, .webp and .avif), plus the logo and a decorative wave.
  • README.md: the steps, and a table of every picture file with its width and height in pixels.
  • page.test.js and package.json: the tests. You don't need to change these.

Right-click index.html and choose Open with Live Server to see the page.

Measure it first

Before you change anything, find out how heavy the page is. Press F12, choose the Network panel, tick Disable cache, choose the Img filter, and reload. The bar at the bottom of the panel says how much was transferred. Write that number down: you'll compare it at the end.

What to do

The starter's pictures look like this, all straight from images/originals/:

<figure>
  <img src="images/originals/lighthouse.jpg" alt="image of lighthouse">
  <figcaption>Gull Point Lighthouse, built in 1874. The tower is open on Saturdays from 10 to 4.</figcaption>
</figure>
  1. Alt text by purpose. Each photo says what it shows, the logo says where its link goes, and the wave is decoration. A caption and its photo's alt text say different things.
  2. Width and height on every <img>, from the README's table.
  3. Loading. The logo and the big photo at the top load right away, and the big photo gets priority. Every photo further down waits until the reader scrolls near it.
  4. srcset and sizes for the five photos further down, using their 480, 960 and 1600 JPEG copies. They're shown the full width of a narrow screen, and at most 720 pixels wide.
  5. A <picture> for the big photo at the top, with AVIF and WebP sources in three widths each, and the JPEG <img> as the fallback. It fills the width of the window.

When you're done, no picture on the page loads a file from images/originals/.

Check your work

Open VS Code's terminal (Terminal > New Terminal) and type:

npm install
npm test

npm install downloads the tools the tests use, once. npm test runs the 13 tests. At first almost all of them fail: that's expected, and each step you finish turns some of them green. A failing test's message names the picture and what it still needs, for example images/originals/lighthouse.jpg is further down the page: give it loading="lazy". The last test runs an HTML validator over the whole page.

Hints

  • Read the alt text aloud with your eyes closed. If the post still makes sense, the alt text is doing its job. Alt Text That Helps has the rules for each kind of picture.
  • Width and height come from the files. For a photo with three copies, use the size of the 1600 copy: the browser only needs the shape.
  • The first screen loads eagerly. Image Dimensions and Lazy Loading says which pictures wait and which one hurries.
  • sizes describes the page, not the files. "The full width of a narrow screen, and at most 720 pixels" is the pattern in Responsive Images with srcset and sizes.
  • Inside a <picture>, the <img> comes last and keeps the alt, width, height and fetchpriority. The Picture Element shows the order.
  • A test says a file isn't there? Compare the spelling with the names in images/: a missing hyphen or a .jpeg for a .jpg is enough.

When you're done

Every test passes:

✔ 1) every picture has an alt attribute
✔ 2) the photos say what they show
✔ 3) a caption and its alt text say different things
✔ 4) the logo says where it goes, and the wave is decorative
✔ 5) every picture has width and height
✔ 6) the photos keep their shape
✔ 7) the pictures on the first screen load right away
✔ 8) the photos further down load lazily
✔ 9) the photos offer three widths with srcset and sizes
✔ 10) the big photo at the top offers a modern format
✔ 11) no picture loads a full-size original
✔ 12) every picture file the page names exists
✔ 13) the page passes the HTML validator
ℹ tests 13
ℹ pass 13
ℹ fail 0

Now measure the page again, the same way as before, and compare the transferred number with the one you wrote down. Then turn on the device toolbar (Ctrl+Shift+M, or Cmd+Shift+M on a Mac), choose a phone, and reload: how many photos does the browser download before you scroll, and which width did it choose?

One question to look back with: if Marisol adds a seventh photo next week, which attributes will she need to remember, and why does each one matter?

So what

This is the work behind every fast photo site: the same photos, the same story, a page many times lighter, and a post that makes sense to everyone, whether they see the pictures or hear them.

Key terms

Related