HTML Tutorial
HTML Project: Photo Gallery
A figure-based gallery with captions. Each picture has alt text and a short title.
What you will build
A six-picture gallery of a river walk. Each picture is a <figure> with a caption. The pictures themselves are inline SVG shapes, not files from the web. External image URLs 404 in this preview. Geometry still reads as a photo grid.
CSS places the figures in a simple grid. The HTML stays a list of figures. Do not wrap every tile in a nameless div if figure already names the pair of picture and caption.
Click Try it in HTML to open /html/try and see the grid as a page. Stay in the HTML preview.
Tags you will use
| Tag | Job on this page |
|---|---|
main | The gallery as the unique content of the page |
figure | One picture plus its caption |
figcaption | The short title under the picture |
svg | A placeholder drawing that cannot 404 |
title inside SVG | The accessible name, in place of img alt text |
If you later swap SVG for a real img, every image needs alt. Until then, put the same idea in an SVG title so the figure is not a silent block of color.
Build in slices
One figure first. A rectangle, a circle, a caption. Confirm the caption sits with the drawing.
Example
<figure>
<svg width="220" height="140" viewBox="0 0 220 140" role="img">
<title>Mist on the weir at dawn</title>
<rect width="220" height="140" fill="#8aa4b8" />
<rect y="90" width="220" height="50" fill="#4d6a7c" />
<circle cx="40" cy="36" r="18" fill="#f4e7c3" />
</svg>
<figcaption>Mist on the weir</figcaption>
</figure>Then wrap two figures in a grid container. Two tiles prove the layout before you draw all six.
Example
<div class="gallery">
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Mist on the weir at dawn</title>
<rect width="220" height="140" fill="#8aa4b8" />
<rect y="90" width="220" height="50" fill="#4d6a7c" />
</svg>
<figcaption>Mist on the weir</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Willow bank in late light</title>
<rect width="220" height="140" fill="#c5d6b0" />
<rect x="20" y="30" width="18" height="110" fill="#3f5c38" />
</svg>
<figcaption>Willow bank</figcaption>
</figure>
</div>Keep drawings inside the page. A src that points at a stock-photo host will fail in/html/try. SVG, a colored div, or a captioned block all survive.
Complete document
Six figures. Six captions. One two-column grid that becomes three columns on a wide preview. Each SVG uses a different palette so the tiles do not look copied.
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>River walk gallery</title>
<style>
body {
margin: 0;
background: #f3f1ec;
color: #1f2933;
font-family: "Segoe UI", sans-serif;
}
header, .gallery {
max-width: 52rem;
margin: 0 auto;
padding: 1.2rem;
}
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
gap: 1rem;
}
figure {
margin: 0;
background: #fff;
border: 1px solid #d7d2c8;
padding: 0.5rem 0.5rem 0.7rem;
}
svg { display: block; width: 100%; height: auto; }
figcaption {
margin-top: 0.45rem;
font-size: 0.9rem;
}
@media (max-width: 640px) {
.gallery { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header>
<h1>River walk</h1>
<p>Six stops from the lock to the old mill.</p>
</header>
<main class="gallery">
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Mist on the weir at dawn</title>
<rect width="220" height="140" fill="#8aa4b8" />
<rect y="90" width="220" height="50" fill="#4d6a7c" />
<circle cx="40" cy="36" r="18" fill="#f4e7c3" />
</svg>
<figcaption>Mist on the weir</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Willow bank in late light</title>
<rect width="220" height="140" fill="#c5d6b0" />
<rect x="20" y="30" width="18" height="110" fill="#3f5c38" />
<rect x="70" y="50" width="14" height="90" fill="#2f4a2c" />
<rect y="118" width="220" height="22" fill="#6a8f7a" />
</svg>
<figcaption>Willow bank</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Stone arch of the packhorse bridge</title>
<rect width="220" height="140" fill="#d8cfc4" />
<rect y="80" width="220" height="60" fill="#7b8ea3" />
<rect x="40" y="40" width="140" height="70" fill="#8b7a68" />
<rect x="80" y="70" width="60" height="40" fill="#7b8ea3" />
</svg>
<figcaption>Packhorse bridge</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Heron standing in shallows</title>
<rect width="220" height="140" fill="#b9c9d4" />
<rect y="100" width="220" height="40" fill="#5f7f8a" />
<rect x="150" y="45" width="10" height="60" fill="#2b2b2b" />
<circle cx="155" cy="40" r="8" fill="#2b2b2b" />
</svg>
<figcaption>Heron in shallows</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Mill race after rain</title>
<rect width="220" height="140" fill="#9bb0c4" />
<rect x="0" y="20" width="90" height="120" fill="#6d5a4a" />
</svg>
<figcaption>Mill race</figcaption>
</figure>
<figure>
<svg viewBox="0 0 220 140" role="img">
<title>Path along the towpath wall</title>
<rect width="220" height="140" fill="#e2d6c2" />
<rect y="90" width="220" height="50" fill="#8a8f6e" />
<rect x="0" y="70" width="220" height="12" fill="#6b5344" />
</svg>
<figcaption>Towpath wall</figcaption>
</figure>
</main>
</body>
</html>Studio studies, same grid
A second complete gallery uses colored blocks instead of scenery. The markup does not change: six figures, six titles, six captions.
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Paper studies</title>
<style>
body { margin: 0; font-family: Georgia, serif; background: #111; color: #eee; }
header, .gallery { max-width: 48rem; margin: 0 auto; padding: 1rem; }
.gallery { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
figure { margin: 0; }
.swatch { height: 7rem; }
figcaption { padding: 0.4rem 0; font-size: 0.9rem; }
@media (max-width: 640px) {
.gallery { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header>
<h1>Paper studies</h1>
<p>Six sheets from the studio table.</p>
</header>
<main class="gallery">
<figure>
<div class="swatch" style="background:#c45c26;" role="img" aria-label="Burnt orange sheet"></div>
<figcaption>Burnt orange</figcaption>
</figure>
<figure>
<div class="swatch" style="background:#2f5d50;" role="img" aria-label="Pine green sheet"></div>
<figcaption>Pine green</figcaption>
</figure>
<figure>
<div class="swatch" style="background:#d9c48a;" role="img" aria-label="Straw sheet"></div>
<figcaption>Straw</figcaption>
</figure>
<figure>
<div class="swatch" style="background:#3d4d6b;" role="img" aria-label="Slate sheet"></div>
<figcaption>Slate</figcaption>
</figure>
<figure>
<div class="swatch" style="background:#8b3a3a;" role="img" aria-label="Brick sheet"></div>
<figcaption>Brick</figcaption>
</figure>
<figure>
<div class="swatch" style="background:#f0efe8;" role="img" aria-label="Ivory sheet"></div>
<figcaption>Ivory</figcaption>
</figure>
</main>
</body>
</html>Common mistakes
- Using
imgwith a URL on another domain. Those files will not load here. - A caption as a sibling
poutsidefigure. Keep picture and title together. - Empty SVG with no
titleand no caption. Then nobody knows what the tile is. - Six identical drawings. Change fill colors so you can tell the tiles apart while you style the grid.
- A CSS grid on
bodythat also contains the page heading. Grid the gallery, not the banner.
Practice tasks
- Rewrite every figcaption for a different walk: a market, a harbour wall, or a hill path.
- Add a seventh figure. The grid should accept it without new CSS if you used
auto-fit. - Give each SVG a unique
titlethat would work as alt text. Preview at /html/try.