Last time, in HTML Basics, Part 3, we covered links and navigation: how the <a> tag connects pages together with href, and how to build simple nav menus. Links let people move between pages. Today we’re covering how to put images on a page — because text alone rarely tells the whole story.
If you’re joining this series for the first time: HTML (HyperText Markup Language) is the language browsers use to structure web pages into elements like paragraphs, headings, links, and — as of today — images.
Why images need their own HTML element
You might think an image is just a picture you drop onto a page, like pasting a photo into a document. On the web it’s more deliberate than that. Every image on a page is a separate file (a .jpg, .png, .webp, etc.) that the browser has to separately request and download. HTML’s job is to tell the browser: which file to fetch, where to place it, and — critically — what it means for people and software that can’t see it.
The <img> tag
The basic tag for embedding an image is <img>. Unlike most tags you’ve seen so far (<p>...</p>, <h1>...</h1>), <img> is a void element — it has no closing tag and no content between tags, because an image doesn’t wrap other content; it just points to a file.
<img src="cat.jpg" alt="A tabby cat sleeping on a windowsill">
Two attributes matter most:
src(“source”) — the path or URL to the image file. This can be a relative path (images/cat.jpg, meaning “look in the images folder next to this HTML file”) or a full URL (https://example.com/cat.jpg).alt(“alternative text”) — a written description of the image. We’ll spend a whole section on this below, because it’s the single most-skipped, most-important attribute in this tag.
Sizing images with width and height
You can also tell the browser the image’s dimensions up front:
<img src="cat.jpg" alt="A tabby cat sleeping on a windowsill" width="600" height="400">
This looks like it’s just about sizing, but it does something more important: it lets the browser reserve the exact box of space the image will occupy before the image file has finished downloading. Without width/height, the page content jumps around as each image pops in — a jarring effect called layout shift. With them set, the text above and below the image stays put. Rule of thumb: always include the image’s real width and height in pixels, even if you also resize it visually with CSS later.
Why alt text is not optional
The alt attribute exists for three overlapping reasons, and skipping it breaks all three:
- Accessibility — people using screen readers (software that reads a page aloud for users who are blind or have low vision) hear the
alttext in place of the image. Noalt, and the image is either skipped silently or announced as a useless filename like “IMG_4213.jpg”. - Broken images — if the image file fails to load (typo in the path, slow connection, deleted file), the browser shows the
alttext instead of a blank box. - Search engines — search engines can’t “see” pictures. They read
alttext to understand what an image shows, which affects image search results and general SEO (search engine optimization — how well a page is understood and ranked by search engines).
Good alt text describes what matters about the image in context, briefly:
<!-- Bad: not descriptive -->
<img src="cat.jpg" alt="image">
<!-- Bad: keyword-stuffed, not natural -->
<img src="cat.jpg" alt="cat kitten pet cute animal tabby cats for sale buy">
<!-- Good: describes what's actually shown, plainly -->
<img src="cat.jpg" alt="A tabby cat sleeping curled up on a sunny windowsill">
One special case: if an image is purely decorative — a background flourish that adds nothing informative — the correct move is an empty alt attribute, alt="". This explicitly tells screen readers to skip it, rather than leaving it out (which some tools may still try to announce using the filename).
Captioning images with figure and figcaption
Often an image needs a caption — a photo credit, a short explanation, a figure number. HTML has a purpose-built pair of tags for this: <figure> wraps the image (and any related content), and <figcaption> holds the caption text.
<figure>
<img src="cat.jpg" alt="A tabby cat sleeping on a windowsill">
<figcaption>Our office cat, Biscuit, midway through his daily 16-hour nap.</figcaption>
</figure>
Using <figure>/<figcaption> instead of, say, an image followed by a plain <p>, tells both browsers and assistive technology that the caption belongs specifically to that image — they’re semantically linked, not just visually nearby.
Responsive images: one image, many screens
Here’s a problem unique to the web: the same page might be viewed on a phone screen 360 pixels wide or a desktop monitor 2560 pixels wide. If you serve one giant image sized for the desktop, phone users download megabytes of data they don’t need just to display a tiny thumbnail. HTML solves this with the srcset and sizes attributes, which let the browser pick the most appropriately-sized file itself.
<img
src="cat-800.jpg"
srcset="cat-400.jpg 400w, cat-800.jpg 800w, cat-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="A tabby cat sleeping on a windowsill">
Breaking this down:
srcsetlists multiple versions of the same image, each labeled with its actual width in pixels (400wmeans “this file is 400 pixels wide”).sizestells the browser how much screen space the image will actually occupy at different viewport widths — here, “full width (100vw) on screens up to 600px wide, otherwise half the viewport width (50vw)”.srcstays as a fallback for browsers that don’t understandsrcset.
The browser combines its own screen size and pixel density with your sizes hint to pick the smallest file from srcset that will still look sharp — without you writing a single line of JavaScript.
Here’s what that decision looks like conceptually:
Art direction with <picture>
srcset is great when you want the same image at different sizes. Sometimes, though, you want a genuinely different crop on small screens — for example, a tightly cropped close-up on mobile versus a wide landscape shot on desktop. That’s what the <picture> element is for:
<picture>
<source media="(max-width: 600px)" srcset="cat-closeup.jpg">
<source media="(min-width: 601px)" srcset="cat-wide.jpg">
<img src="cat-wide.jpg" alt="A tabby cat sleeping on a windowsill">
</picture>
The browser checks each <source>‘s media condition top to bottom and uses the first one that matches the current screen. The <img> inside is required — it’s both the fallback for browsers that don’t support <picture> and the element that actually needs the alt text.
Common mistakes to avoid
- Skipping alt text — even “just a quick prototype” page should have real
altvalues; it’s a habit worth building early. - Uploading full-resolution camera photos straight to a page — a 6000×4000 pixel, 8MB photo displayed at 400px wide wastes bandwidth for every visitor. Resize and compress images before uploading them.
- Using images of text — text baked into an image can’t be selected, searched, translated, or read by screen readers. Use real HTML text with CSS styling instead whenever possible.
- Forgetting width/height — leads to layout shift as images pop in, which also hurts how search engines score a page’s user experience.
Recap
In this lesson we covered: the <img> tag and its src/alt/width/height attributes; why alt text matters for accessibility, broken images, and SEO; captioning images semantically with <figure>/<figcaption>; serving appropriately-sized images with srcset/sizes; and art-directed image swaps with <picture>.
Coming up next: HTML Basics, Part 5 — lists (ordered, unordered, and nested) for structuring grouped content like steps, menus, and outlines.