From a5f5d976742ba004e11bc71ea5af8ebbc4bb6342 Mon Sep 17 00:00:00 2001 From: Ajay Dhangar Date: Sun, 4 Oct 2026 21:47:18 +0530 Subject: [PATCH 1/2] Done html images docs --- .../html/05-images/accessible-images.mdx | 514 +++++++++++++++++- .../html/05-images/figure-and-figcaption.mdx | 503 ++++++++++++++++- tutorials/html/05-images/image-formats.mdx | 386 ++++++++++++- tutorials/html/05-images/img-element.mdx | 423 +++++++++++++- tutorials/html/05-images/index.mdx | 252 ++++++++- tutorials/html/05-images/lazy-loading.mdx | 444 ++++++++++++++- tutorials/html/05-images/picture-element.mdx | 445 ++++++++++++++- .../html/05-images/responsive-images.mdx | 395 +++++++++++++- tutorials/html/05-images/src-and-alt.mdx | 453 ++++++++++++++- tutorials/html/05-images/srcset-and-sizes.mdx | 454 +++++++++++++++- tutorials/html/05-images/width-and-height.mdx | 408 +++++++++++++- 11 files changed, 4565 insertions(+), 112 deletions(-) diff --git a/tutorials/html/05-images/accessible-images.mdx b/tutorials/html/05-images/accessible-images.mdx index b63da577c..1b0868b91 100644 --- a/tutorials/html/05-images/accessible-images.mdx +++ b/tutorials/html/05-images/accessible-images.mdx @@ -1,16 +1,512 @@ --- -id: accessible-images -title: "Best Practices for Accessible Web Images" +id: html-accessible-images +title: "Accessible Images in HTML" sidebar_label: "Accessible Images" sidebar_position: 11 slug: /html/images/accessible-images -description: "Learn how to make visual media fully accessible with decorative alt semantics, complex image descriptions, SVG accessibility, and ARIA roles." +description: "Learn how to make every image in your HTML pages accessible. Decide between informative, decorative, functional, and complex images, write useful alt text, handle text in images, linked images, SVG, animated GIFs, and test with real tools on CodeHarborHub." keywords: - accessible images HTML - - empty alt attribute decorative - - SVG accessibility aria - - web accessibility WCAG images + - HTML alt text best practices + - decorative images alt empty + - functional images links buttons + - complex images long description + - text in images accessibility + - SVG accessibility role img + - prefers-reduced-motion GIF + - web accessibility images + - WCAG non-text content + - screen reader images + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, accessibility, wcag, a11y] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, accessibility, alt-text, wcag, frontend] +--- + +export const sample = "data:image/svg+xml;utf8," + encodeURIComponent(""); + +export const searchIcon = "data:image/svg+xml;utf8," + encodeURIComponent(""); + +Imagine opening your favorite website, but every picture on it is invisible. Menus are just empty boxes, charts are blank, and the photos have vanished. For millions of people, this is not a thought experiment. Some are blind and use screen readers. Some have low vision. Some are on a slow mobile connection in a remote area, where images never finish loading. Some simply turned images off to save data. + +Accessible images make sure that **everyone gets the same information and the same abilities**, whether or not they can see the picture. The good news: you already know most of the tools. This final lesson of the section shows you how to **decide** what each image needs, and how to do it well. + + +
+ +## What You Will Learn + +- The four jobs an image can have, and how each changes your `alt` text +- How to write `alt` text that is short, useful, and honest +- When to use an empty `alt=""` and why it is not a mistake +- How to handle linked images, buttons, icons, and text in images +- How to describe charts and other complex images +- How to make SVG and animated images accessible +- How to test your work with free tools + +## Why Accessibility Is Everyone's Job + +Accessible images are not only a "nice extra" for a small group. They are part of the rules in many countries, and part of the international standard called **WCAG** (Web Content Accessibility Guidelines). The first rule in that standard is simple: *every non-text item needs a text alternative that serves the same purpose.* + +They also help everyone else: + +- **Slow connections:** When an image fails to load, the `alt` text appears in its place. +- **Search engines:** Google reads `alt` text to understand your images. +- **Voice assistants and translation tools:** They read text, not pixels. +- **Bright sunlight, broken screens, old devices:** Text still gets through. + +:::info The core idea +The right `alt` text depends on the **purpose** of the image in that place, not only on what the image shows. The same photo can need different `alt` text on two different pages. +::: + +## Step One: Ask "What Is This Image For?" + +Before you type a single word of `alt`, ask what job the image does. Almost every image fits one of these four jobs. + +| Job | What it does | What `alt` should be | +| :-- | :-- | :-- | +| **Informative** | Adds meaning or information | A short description of the meaning | +| **Decorative** | Only for looks, adds nothing new | Empty: `alt=""` | +| **Functional** | Is inside a link or button, so it does something | Describe the **action**, not the picture | +| **Complex** | Contains a lot of data (chart, map, diagram) | A short summary, plus a longer description nearby | + +Let's look at each one. + +## 1. Informative Images + +An informative image adds something the text does not already say. Write a short description of what matters. + + + + +```html title="index.html" +A white sailboat on blue waves under a bright sun +``` + + + + + +<> +A white sailboat on blue waves under a bright sun + + + + + + +### Tips for Writing Good `alt` Text + +1. **Be concise.** One short sentence is usually enough. A good guide is under 125 characters, but meaning matters more than counting. +2. **Describe what matters in context.** On a travel blog, "A white sailboat at sea" works. On a sailing-shop product page, the boat model and rig type might matter. +3. **Do not start with "image of" or "picture of."** Screen readers already announce that it is an image. +4. **Skip the file name.** `alt="IMG_20250311.jpg"` helps nobody. +5. **Do not stuff keywords.** `alt="boat boat sailing boat buy boat cheap"` is bad for people and for search engines. +6. **Include text that is in the picture,** if that text matters. +7. **End with a period** if it is a full sentence. It gives screen readers a natural pause. + + + + +```html +image +boat.jpg +Picture of a boat boat sailing buy cheap boat +``` + + + + +```html +A white sailboat on calm blue water. +Sailboat leaving the harbor at sunrise. +The Lotus 28, a small sailboat with one white sail. +``` + + + + +## 2. Decorative Images + +Some images are purely for style: a divider swirl, a background texture, a pretty shape beside a heading. They add no information. If a screen reader announced each one, it would only create noise. + +For these, use an **empty** `alt` attribute: + +```html + +``` + +With `alt=""`, screen readers skip the image completely. + +:::warning Empty alt is not the same as no alt +- `alt=""` says: "I thought about it. This image is decorative." Screen readers skip it. ✅ +- **No `alt` attribute at all** says: "I forgot." Some screen readers then read out the file name, like "swirl dot s v g." ❌ + +Always include the attribute, even when it is empty. +::: + +### The Even Better Option: CSS Backgrounds + +If an image is purely decoration, ask whether it belongs in HTML at all. Style belongs in CSS, so a decorative image can often be a background. + +```css +.hero { + background-image: url("images/waves.svg"); + background-size: cover; +} +``` + +Images added through CSS are ignored by screen readers, which is exactly what you want for decoration. But never put important information in a CSS background. There is no way to give it `alt` text. + +## 3. Functional Images + +A **functional image** is inside a link or a button. Clicking it *does* something. Here, `alt` must describe the **action or destination**, not the appearance. + + + + +```html title="index.html" + + + + + + CodeHarborHub home + +``` + + + + + +<> + + + + + + + +A screen reader announces the first example as "Search, button." That is exactly what a user needs. If the `alt` said "magnifying glass," they would hear "magnifying glass, button" and have to guess. + +| Image | Weak `alt` | Strong `alt` | +| :-- | :-- | :-- | +| Magnifier icon in a search button | `magnifying glass` | `Search` | +| Logo inside a home link | `logo` | `CodeHarborHub home` | +| Printer icon in a button | `printer icon` | `Print this page` | +| Arrow in a "next" link | `right arrow` | `Next lesson` | + +### When the Link Also Has Text + +If the link or button already has visible text, the icon beside it is decorative. Give it an empty `alt` so the label is not read twice. + +```html + + + Download the guide (PDF) + +``` + +## 4. Complex Images + +Charts, maps, infographics, and diagrams hold more information than a single sentence can carry. One short `alt` cannot do the job, and a very long `alt` is hard to navigate. + +The pattern is simple: + +1. Put a **short summary** in `alt`: what it is, and the main point. +2. Provide the **full information** in text nearby, such as a data table or a paragraph. + + + + +```html title="index.html" +
+ Bar chart of monthly visitors. Details follow below. +
Monthly visitors, January to March.
+
+ +
+ Chart data as a table + + + + + +
MonthVisitors
January12,000
February18,500
March25,200
+
+``` + +
+ + + +<> +
+ Illustration standing in for a bar chart. Details follow below. +
Monthly visitors, January to March.
+
+ +
+ Chart data as a table + + + + + + + +
MonthVisitors
January12,000
February18,500
March25,200
+
+ +
+ +
+
+ +Here a sample drawing stands in for the chart. In your project, `src` points to the real chart. + +The table is useful for **everyone**: a screen reader user can move through it cell by cell, and a sighted user can read exact numbers that a bar can only suggest. Accessible content often turns out to be better content. + +:::tip Linking the image to its long description +You can also connect an image to a longer description on the same page with `aria-describedby`: + +```html +Bar chart of monthly visitors. +

Visitors grew from 12,000 in January to 25,200 in March...

+``` + +Screen readers will read the `alt` first and offer the longer description. +::: + +## Text Inside Images + +Putting words inside a picture (a banner, a screenshot of a quote, a button drawn in an image editor) causes many problems: + +- Screen readers cannot read the words unless you repeat them in `alt`. +- Text cannot be resized, translated, searched, or copied. +- The words can turn blurry on a high-resolution screen. +- Low-vision users cannot change the colors or the font. + +**The best solution is to use real HTML text** and style it with CSS. If you must keep text in an image (a logo, for example), repeat the exact words in `alt`. + + + + +```html + + +``` + + + + +```html + + +``` + + + + +## SVG and Icons + +Inline SVG is a favorite for icons and charts because it scales perfectly. Like an image, it needs a text alternative when it carries meaning. + + + + +```html + + Warning + + +``` + + + + +```html + + +``` + + + + +- `role="img"` tells assistive tech to treat the SVG as one image. +- `` plus `aria-labelledby` provides its name. +- `aria-hidden="true"` hides an SVG that is only decoration (for example, an icon next to a text label). + +For an SVG loaded through `<img src="icon.svg">`, use the `alt` attribute as usual. + +## Animated Images and Motion + +Animated GIFs and looping animations can distract people with attention difficulties. Fast flashing can even trigger seizures for people with photosensitive epilepsy. + +- **Avoid flashing more than three times per second.** This is a safety rule from WCAG. +- **Give users control.** If something moves for more than five seconds, provide a way to pause it. +- **Respect the "reduce motion" setting.** Many people turn this on in their operating system, and CSS can read it: + +```css +@media (prefers-reduced-motion: reduce) { + .animated-banner { + animation: none; + } +} +``` + +For a video-like animation, a real `<video>` with controls is often better than a GIF. It can be paused, and it is usually far smaller in file size. + +## Color and Contrast + +Some images carry meaning only through color, such as a red dot for "error" and a green dot for "success." About 1 in 12 men has some form of color vision difference. Add a second clue: a shape, a pattern, or a text label. + +When text sits on top of an image, check the **contrast ratio**. WCAG asks for at least **4.5:1** for normal text and **3:1** for large text. A busy photo behind white text can fail in some areas. A semi-transparent dark overlay behind the text is an easy fix. + +## Quick Decision Guide + +Use this when you are unsure what to write. + +| Question | If yes | If no | +| :-- | :-- | :-- | +| Is the image inside a link or button? | Describe the **action** | Go to the next question | +| Does it only decorate, or repeat nearby text? | `alt=""` | Go to the next question | +| Does it hold lots of data? | Short `alt` plus a full text version | Go to the next question | +| Does it contain important text? | Put the same words in `alt` | Describe the meaning in a short phrase | + +## Testing Your Images + +You do not need expensive tools. Try these in order: + +1. **Turn images off.** In your browser's developer tools or settings, block images and read your page. Does it still make sense? +2. **Check with a screen reader.** NVDA (Windows, free), VoiceOver (built into macOS and iPhone), and TalkBack (Android) all work. Even five minutes of listening teaches a lot. +3. **Run an automated checker.** Lighthouse (inside Chrome DevTools), axe DevTools, and WAVE will find missing `alt` attributes. +4. **Read the `alt` text out loud, alone.** If it does not make sense without the picture, rewrite it. +5. **Ask real users** when you can. No tool replaces their feedback. + +:::note Automated tools only catch about a third of the problems +A checker can tell you if `alt` is *missing*, but not if it is *useful*. `alt="image"` passes the test, but helps nobody. Human judgment is the most important tool. +::: + +## Global Audience Notes + +- **Write `alt` in the same language as the page.** If one image is in another language, mark the element with `lang`. +- **Use plain, clear words.** Many of your readers use translation tools, and simple sentences translate best. +- **Avoid culture-specific references** that need local knowledge to understand. +- **Keep file sizes small.** In many regions, data is expensive and connections are slow. Accessible also means *reachable*. + +## Common Mistakes to Avoid + +1. **Missing `alt` attributes.** Always include one, even if empty. +2. **Starting with "image of" or "photo of."** Screen readers already say "image." +3. **Using the file name as `alt`.** It carries no meaning. +4. **Describing the icon instead of the action.** Write "Search," not "magnifying glass." +5. **Repeating the caption or nearby text** word for word. +6. **Putting important text inside images** without matching `alt`. +7. **Using `alt=""` on an informative image** just to pass a checker. This hides real content. +8. **Stuffing keywords** into `alt` for search ranking. +9. **Relying on color alone** to carry meaning. +10. **Autoplaying, flashing animations** with no way to pause them. + +## Practice Time + +Take any page from your project, or build a small one, and try these: + +1. Add one informative image with a short, clear `alt`. +2. Add one decorative image with `alt=""`. +3. Add a search button with an icon, and give the icon an action-based `alt`. +4. Add a link that has both an icon and a text label. Make the icon decorative. +5. Create a "chart" figure with a short `alt` and a hidden data table inside `<details>`. +6. Replace one text-in-image banner with real HTML text and CSS. +7. Add an inline SVG with `role="img"` and a `<title>`, and another with `aria-hidden="true"`. +8. Add a `prefers-reduced-motion` rule that stops one animation. +9. Block images in your browser and read the page. Fix anything that no longer makes sense. +10. Bonus: run Lighthouse and aim for a perfect accessibility score. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What are the four jobs an image can have?</summary> + +Informative, decorative, functional (inside a link or button), and complex (charts, maps, diagrams). + +</details> + +<details> +<summary>2. When should you use `alt=""`?</summary> + +When an image is purely decorative or just repeats nearby text. The empty value tells screen readers to skip it. + +</details> + +<details> +<summary>3. What is the difference between `alt=""` and no `alt` at all?</summary> + +`alt=""` is a deliberate choice that hides the image from assistive technology. A missing `alt` is an error, and some screen readers read out the file name instead. + +</details> + +<details> +<summary>4. What should `alt` say for an icon inside a button?</summary> + +The action, such as "Search" or "Print this page," not a description of the icon. + +</details> + +<details> +<summary>5. How do you make a complex chart accessible?</summary> + +Give it a short `alt` that names the chart and its main point, and provide the full data nearby as text or a table. + +</details> + +<details> +<summary>6. How do you make an inline SVG accessible?</summary> + +Use `role="img"` with a `<title>` (and `aria-labelledby`) when it has meaning, or `aria-hidden="true"` when it is only decoration. + +</details> + +## Key Takeaways + +- Start every image with one question: **what is this image for?** The answer decides the `alt`. +- Informative images get short, useful descriptions. Decorative images get `alt=""`. Functional images describe the action. Complex images get a summary plus full text. +- Prefer real HTML text over text in images, and CSS backgrounds for pure decoration. +- Make SVGs, animations, and color-based meaning accessible too. +- Test by blocking images, listening with a screen reader, and running an automated checker. Then use your own judgment. +- Accessible images are clearer, lighter, and kinder for everyone, wherever they are in the world. + +You have now finished the Images section: from the `<img>` tag to responsive formats, lazy loading, captions, and accessibility. Head back to the [Images overview](/tutorials/html/images) to review the full path, or keep going with the next section of the HTML course. \ No newline at end of file diff --git a/tutorials/html/05-images/figure-and-figcaption.mdx b/tutorials/html/05-images/figure-and-figcaption.mdx index 66f576226..e51de1b60 100644 --- a/tutorials/html/05-images/figure-and-figcaption.mdx +++ b/tutorials/html/05-images/figure-and-figcaption.mdx @@ -1,16 +1,495 @@ --- -id: figure-and-figcaption -title: "Structuring Image Captions with figure and figcaption" -sidebar_label: "Figure & Figcaption" -sidebar_position: 8 +id: html-figure-and-figcaption +title: "HTML figure and figcaption" +sidebar_label: "Figure and Figcaption" +sidebar_position: 10 slug: /html/images/figure-and-figcaption -description: "Wrap self-contained media content with figure and provide semantic text captions using figcaption for clean document structure." +description: "Learn how to use the HTML figure and figcaption elements to add captions to images, diagrams, code, quotes and tables. Understand captions versus alt text, numbering with CSS counters, credits and licenses, accessibility, styling, and common mistakes on CodeHarborHub." keywords: - - HTML figure element - - figcaption element - - image with caption HTML - - semantic image wrapping + - HTML figure + - HTML figcaption + - image captions HTML + - figure vs img + - figcaption vs alt + - CSS counter figure numbering + - HTML figure code block + - HTML figure blockquote + - image credits license HTML + - accessible captions + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, figure, semantics, typography] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, figure, figcaption, accessibility, frontend] +--- + +export const sample = "data:image/svg+xml;utf8," + encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='#dbeafe'/><circle cx='170' cy='50' r='24' fill='#fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='#2563eb'/><path d='M70 110 V62 L112 110 Z' fill='#ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='#334155'/></svg>"); + +Open a printed book or a magazine, and you will notice that pictures rarely stand alone. Underneath each one is a short line of text: "Figure 3. A fishing harbor at sunrise. Photo: A. Okafor." The picture and its caption belong together. If you moved the picture to another page, its caption would go with it. + +HTML has two elements for exactly this: `<figure>`, which holds the picture, and `<figcaption>`, which holds the caption. They are simple, but they carry real meaning: "this content is a self-contained unit, and this text describes it." In this lesson, you will learn how to use them well. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- What `<figure>` and `<figcaption>` mean, and what you can put in them +- How a caption differs from `alt` text +- How to caption images, diagrams, code, quotes, and more +- How to number figures automatically with CSS +- How to give credit and show licenses +- How to style figures and keep them accessible +- Common mistakes, and how to avoid them + +## The Basics + +Wrap the image in a `<figure>`, and add a `<figcaption>` as the first or last child. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="index.html" +<figure> + <img + src="images/harbor.jpg" + alt="A white sailboat on blue waves under a bright sun" + width="600" + height="400" + /> + <figcaption> + A sailboat leaves the harbor just after sunrise. + </figcaption> +</figure> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/index.html"> +<> +<figure> + <img + src={sample} + alt="A white sailboat on blue waves under a bright sun" + width="240" + height="160" + /> + <figcaption> + A sailboat leaves the harbor just after sunrise. + </figcaption> +</figure> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo uses a small drawing built into the page. In your project, `src` points to a real photo. + +By default, browsers indent a `<figure>` with left and right margins (usually about 40 pixels) and show the caption as normal text below the picture. You can style both with CSS. + +## What the Elements Mean + +| Element | Meaning | Rules | +| :-- | :-- | :-- | +| `<figure>` | A **self-contained** piece of content, referred to from the main text, that could move elsewhere without changing the meaning of the text | Can hold images, diagrams, code, quotes, tables, videos, and more | +| `<figcaption>` | The **caption or legend** for the figure | Must be the **first or last** child of `<figure>`. Only one per figure | + +The key idea is in "self-contained." If you removed the figure from the page and put it in an appendix, the main text would still make sense. That is why a decorative image is **not** a figure, but a chart that the text refers to is. + +:::tip A quick test +Ask: "Does this content have a caption, and could it be moved to another place without breaking the sentence around it?" If yes, it is a good candidate for `<figure>`. +::: + +## Caption, `alt`, and `title`: Three Different Jobs + +Beginners often mix these up. They answer different questions for different people. + +| | `alt` | `<figcaption>` | `title` | +| :-- | :-- | :-- | :-- | +| Question it answers | "What is in this image?" (the replacement for the picture) | "What should everyone know about this image?" (extra context) | "Anything else?" (a tooltip) | +| Visible to | People who cannot see the image, and failed loads | **Everyone** | Mouse hover only | +| Required? | Always | Optional | Optional, avoid | +| Where | On the `<img>` | Inside the `<figure>` | On the element | + +### How They Work Together + +If the caption already describes the picture, the `alt` text should not simply repeat it. A screen reader would read the same information twice. + +<Tabs> +<TabItem value="repeat" label="Repetitive" default> + +```html +<figure> + <img src="boat.jpg" alt="A sailboat leaves the harbor just after sunrise." width="600" height="400" /> + <figcaption>A sailboat leaves the harbor just after sunrise.</figcaption> +</figure> +``` + +</TabItem> +<TabItem value="complement" label="Complementary"> + +```html +<figure> + <img + src="boat.jpg" + alt="A white sailboat with one sail on calm blue water, a low sun behind it" + width="600" + height="400" + /> + <figcaption> + Morning departure from Port Meridian, the first day of the regatta. + </figcaption> +</figure> +``` + +The `alt` describes what is *seen*. The caption adds what is *known*: where, when, why. + +</TabItem> +</Tabs> + +If the caption fully conveys the picture's meaning, a short `alt` is fine, or even `alt=""` in some cases. Just make sure a person who cannot see the image still gets the information once. You will go deeper in [Accessible Images](./accessible-images). + +## It Is Not Only for Images + +`<figure>` can wrap any content that has a caption and is referenced from the text. + +<Tabs> +<TabItem value="code" label="Code listing" default> + +```html +<figure> + <pre><code>console.log("Hello, harbor!");</code></pre> + <figcaption>Listing 1. Printing a message in JavaScript.</figcaption> +</figure> +``` + +</TabItem> +<TabItem value="quote" label="Quotation"> + +```html +<figure> + <blockquote> + <p>The best way to learn to code is to build something you care about.</p> + </blockquote> + <figcaption> + A tip often shared with beginners, from <cite>the CodeHarborHub forum</cite>. + </figcaption> +</figure> +``` + +You saw this pattern in [Quotations](/html/text-content/quotations). + +</TabItem> +<TabItem value="table" label="Data"> + +```html +<figure> + <table> + <caption>Course sign-ups by month</caption> + <tr><th>Month</th><th>Sign-ups</th></tr> + <tr><td>March</td><td>120</td></tr> + <tr><td>June</td><td>250</td></tr> + </table> +</figure> +``` + +A table has its own caption element, `<caption>`. Use it inside the `<table>` instead of a `<figcaption>`. + +</TabItem> +<TabItem value="video" label="Video"> + +```html +<figure> + <video controls width="560" poster="images/intro-poster.jpg"> + <source src="media/intro.mp4" type="video/mp4" /> + <track kind="captions" src="media/intro.en.vtt" srclang="en" label="English" default /> + Your browser does not support the video tag. + </video> + <figcaption>A two-minute introduction to the course.</figcaption> +</figure> +``` + +</TabItem> +</Tabs> + +## Several Images in One Figure + +A figure may hold more than one image if they share a single caption, such as a before-and-after comparison. + +```html title="before-after.html" +<figure> + <img src="images/room-before.jpg" alt="The classroom before: bare walls and old desks" width="400" height="300" /> + <img src="images/room-after.jpg" alt="The classroom after: bright walls and new desks" width="400" height="300" /> + <figcaption>The school computer lab before (left) and after (right) its renovation.</figcaption> +</figure> +``` + +If the images need **separate** captions, use separate figures. If they are a gallery of different pictures, give each its own `<figure>`. + +## Numbering Figures Automatically + +Books say "Figure 1," "Figure 2," and refer to them in the text. You can do the same with CSS counters, so you never renumber by hand. + +```css title="figure-numbers.css" +body { + counter-reset: figure; +} +figure { + counter-increment: figure; +} +figcaption::before { + content: "Figure " counter(figure) ". "; + font-weight: 700; +} +``` + +```html title="numbered.html" +<p> + As you can see in <a href="#fig-harbor">Figure 1</a>, the harbor is calm in the morning. +</p> + +<figure id="fig-harbor"> + <img src="images/harbor.jpg" alt="Boats in a calm harbor" width="600" height="400" /> + <figcaption>Fishing boats resting in the harbor at sunrise.</figcaption> +</figure> +``` + +The caption now begins with "Figure 1." automatically. The `id` on the figure lets other parts of the page link to it, as you learned in [Internal Links](/html/links-and-navigation/internal-links). + +:::info Text added by CSS +Words added with `content` in CSS may not be announced by every screen reader, and they cannot be selected or translated like normal text. If the numbers matter, write "Figure 1." directly in the HTML. Use CSS counters for convenience, not for essential information. +::: + +## Giving Credit and Showing Licenses + +Many images need a credit: who made it, where it came from, and the license that allows you to use it. The caption is the perfect place. + +```html title="credit.html" +<figure> + <img src="images/lighthouse.jpg" alt="A white lighthouse glowing at dusk on a rocky coast" width="600" height="400" /> + <figcaption> + A lighthouse at dusk. + Photo by <a href="https://example.com/photographers/a-okafor">A. Okafor</a>, + licensed under + <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>. + </figcaption> +</figure> +``` + +Tips for credits: + +- **Follow the license's rules exactly.** Some require the creator's name, a link to the license, or a note that you changed the image. +- **Use full links** for the source and the license, so readers can check them. +- **Keep the credit short,** and put the longer details on a separate credits page if needed. +- **Never claim someone else's work as your own.** +- **When in doubt, ask,** or choose a different image. + +## Styling Figures + +A small amount of CSS makes figures neat. Style the `<img>` for sizing and the `<figcaption>` for text. + +<Tabs> +<TabItem value="code" label="HTML + CSS" default> + +```html title="styled-figure.html" +<style> + figure { + margin: 2rem auto; + max-width: 40rem; + } + figure img { + display: block; + max-width: 100%; + height: auto; + border-radius: 8px; + } + figcaption { + margin-top: 0.5rem; + color: #475569; + font-size: 0.9rem; + line-height: 1.5; + } +</style> + +<figure> + <img src="images/harbor.jpg" alt="Boats in a calm harbor" width="800" height="533" /> + <figcaption>Fishing boats resting in the harbor at sunrise.</figcaption> +</figure> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/styled-figure.html"> +<> +<figure style={{margin: '1rem auto', maxWidth: '20rem'}}> + <img + src={sample} + alt="Boats in a calm harbor" + width="240" + height="160" + style={{display: 'block', maxWidth: '100%', height: 'auto', borderRadius: '8px'}} + /> + <figcaption style={{marginTop: '0.5rem', color: '#475569', fontSize: '0.9rem', lineHeight: 1.5}}> + Fishing boats resting in the harbor at sunrise. + </figcaption> +</figure> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +### Caption on Top, or Beside + +A `<figcaption>` may go first, to appear above the content. For a side-by-side layout, use CSS Grid. + +```css +figure.side { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 1rem; + align-items: center; +} +``` + +Keep the caption's contrast high and its text size readable. Gray text that is too light is hard for many people. + +## Accessibility and Global Readers + +- **Browsers connect the caption to the figure.** Many screen readers announce the figure as a group with its caption as its label. That is why a caption should make sense by itself. +- **Do not repeat yourself.** The `alt` and the caption should not say the same thing. +- **Write captions in the page's language,** and mark foreign names or terms with `lang`. +- **Use plain words.** Many readers use a second language. Avoid idioms and long sentences. +- **Right-to-left pages work as they are.** The caption follows the reading direction. Use logical CSS properties such as `margin-inline` if you set margins. +- **Do not put important text only inside the image.** Say it in the caption or the text, where it can be searched and translated. +- **Name the figure if there is no caption.** If a `<figure>` has no `<figcaption>`, give it an accessible name with `aria-label`, or reconsider whether it needs to be a figure at all. + +```html title="aria-label.html" +<figure aria-label="Bar chart of course sign-ups from March to June"> + <img src="images/signups.png" alt="Bar chart: sign-ups doubled between March and June" width="600" height="360" /> +</figure> +``` + +## When Not to Use `<figure>` + +Not every image needs a figure. Skip it when: + +- The image is **decoration** with `alt=""`. +- The image is a **logo** or an **icon**. +- The image is a **small inline picture** inside a sentence. +- There is **no caption** and nothing refers to it. +- The image is part of the **page design**, such as a background or banner. + +Using `<figure>` on everything adds noise for screen reader users, without adding meaning. + +## Choosing the Right Tool + +| You want to... | Use | +| :-- | :-- | +| Show a plain picture inside the flow of text | `<img>` | +| Add a visible caption that belongs to a picture, diagram, code, or quote | `<figure>` with `<figcaption>` | +| Describe the image for people who cannot see it | `alt` on the `<img>` | +| Caption a table | `<caption>` inside the `<table>` | +| Group items in a gallery | A `<figure>` for each, in a list or grid | +| Add a hover tooltip | `title`, used sparingly | + +## Common Mistakes + +### Mistake 1: Using `<figure>` for every image + +Reserve it for content that is self-contained and captioned. + +### Mistake 2: Placing `<figcaption>` in the wrong place + +It must be the **first or last** child of the `<figure>`, never in the middle. + +### Mistake 3: More than one `<figcaption>` + +A figure takes only one. Use separate figures for separate captions. + +### Mistake 4: Copying the caption into `alt` + +Screen reader users hear it twice. Make the two complement each other. + +### Mistake 5: Using `<figcaption>` outside a `<figure>` + +It has no meaning on its own. + +### Mistake 6: Skipping credits + +Always name the creator and the license when they are required. + +### Mistake 7: Using the caption for critical information that must stay hidden from no one but is not visible + +A caption is visible to everyone. Do not put in it things you do not want everyone to see. + +### Mistake 8: Forgetting default margins + +Browsers indent figures by default. If your layout looks off, set `margin` on `figure`. + +## Try It Yourself + +Here is a short project. + +1. Create `captions.html` with a heading **A Day at the Harbor**. +2. Add three figures: a photo, a diagram or screenshot, and a short code listing. +3. Write a caption for each, and a separate `alt` for the images that complements it, not repeats it. +4. Add a CSS counter that numbers the captions as "Figure 1.", "Figure 2.", and so on. +5. In the paragraph above the first figure, add a link to it using its `id`. +6. Credit one image with a creator name and license link in its caption. +7. Build a before-and-after figure with two images and one caption. +8. Style the figures: a centered `max-width`, a rounded image, and a muted caption with good contrast. +9. Bonus: caption the same photo in a second language, with the correct `lang` attribute. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What does `<figure>` represent?</summary> + +A self-contained piece of content, such as an image, diagram, code listing, or quote, that is referred to from the main text and could be moved elsewhere without changing its meaning. + +</details> + +<details> +<summary>2. Where must `<figcaption>` go?</summary> + +Inside the `<figure>`, as its first or last child. There can be only one. + +</details> + +<details> +<summary>3. How is a caption different from `alt` text?</summary> + +The `alt` text replaces the image for people who cannot see it. The caption is visible to everyone and adds context. They should complement each other, not repeat. + +</details> + +<details> +<summary>4. How can you number figures automatically?</summary> + +With CSS counters: `counter-reset` on `body`, `counter-increment` on `figure`, and `counter()` in `figcaption::before`. + +</details> + +<details> +<summary>5. What should you use to caption a table?</summary> + +The `<caption>` element inside the `<table>`, instead of a `<figcaption>`. + +</details> + +## Key Takeaways + +- `<figure>` groups self-contained content, and `<figcaption>` gives it a caption, first or last, one per figure. +- A caption is for everyone. `alt` is for people who cannot see the image. Make them complement each other. +- Figures can hold images, code, quotes, video, and more, but a table uses `<caption>`. +- Use captions for credits and licenses, and CSS for numbering and styling. +- Use `<figure>` only where it adds meaning, and write captions in plain, clear language for a global audience. + +Now your images have captions that stay with them. The last lesson brings everything together: how to make every image work for every visitor in [Accessible Images](./accessible-images). \ No newline at end of file diff --git a/tutorials/html/05-images/image-formats.mdx b/tutorials/html/05-images/image-formats.mdx index b306b147b..8b814ce3c 100644 --- a/tutorials/html/05-images/image-formats.mdx +++ b/tutorials/html/05-images/image-formats.mdx @@ -1,16 +1,380 @@ --- -id: image-formats -title: "Comparing Web Image Formats: JPEG, PNG, GIF, SVG, WebP, and AVIF" +id: html-image-formats +title: "Image Formats for the Web" sidebar_label: "Image Formats" -sidebar_position: 10 +sidebar_position: 5 slug: /html/images/image-formats -description: "Understand the strengths, compression types, transparency support, and compatibility of modern web image formats like WebP, AVIF, and SVG." +description: "Learn which image format to use on the web. Compare JPEG, PNG, GIF, WebP, AVIF and SVG, understand lossy and lossless compression, transparency and animation, browser support, optimization tools, metadata privacy, and how to choose the best format on CodeHarborHub." keywords: - - web image formats - - WebP vs AVIF - - SVG vector graphics - - JPEG vs PNG lossy lossless + - image formats for web + - JPEG vs PNG vs WebP + - AVIF image format + - SVG images HTML + - GIF vs animated WebP + - lossy vs lossless compression + - raster vs vector images + - optimize images for web + - image compression tools + - favicon formats + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, image-formats, webp, avif, performance] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, formats, performance, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +Save the same photograph in different ways, and you can end up with files that differ in size by ten times, with almost no difference to the eye. On a page with twenty images, that gap decides whether your site loads in a second or in ten, and whether a visitor on a limited data plan can afford to open it. + +The **format** of an image file is the biggest choice you make about its weight and quality. This lesson explains the main formats in plain language, so you can pick the right one for each image, and know how to shrink files without spoiling them. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- The difference between **raster** and **vector** images +- What **lossy** and **lossless** compression mean +- When to use JPEG, PNG, GIF, WebP, AVIF, and SVG +- How transparency and animation fit in +- Which formats browsers support, and how to offer fallbacks +- How to compress and prepare images, including privacy tips +- How to choose a format with a simple decision guide + +## Two Big Ideas + +### Raster vs Vector + +| | Raster | Vector | +| :-- | :-- | :-- | +| Made of | A grid of colored **pixels** | **Shapes and paths** described by math | +| Zooming in | Gets blocky and blurry | Stays perfectly sharp | +| Best for | Photographs, detailed pictures | Logos, icons, diagrams, simple illustrations | +| File size | Grows with pixel count | Stays small for simple shapes | +| Examples | JPEG, PNG, GIF, WebP, AVIF | SVG | + +A photo of a harbor has millions of subtle color changes, so it must be raster. A logo is a few clean shapes, so vector is ideal. + +### Lossy vs Lossless + +Compression makes files smaller by storing the picture more cleverly. + +| | Lossy | Lossless | +| :-- | :-- | :-- | +| What it does | **Throws away** details your eyes barely notice | Packs the data tighter, **losing nothing** | +| File size | Much smaller | Smaller than raw, but larger than lossy | +| Quality | Slightly reduced, adjustable | Identical to the original | +| Best for | Photographs | Screenshots, sharp text, graphics with flat colors | +| Repeated saving | Each save can lower quality further | No damage | + +:::tip Keep your originals +Always keep the original, full-quality file somewhere safe. Make web copies from it. Once a lossy file has been compressed, the lost detail cannot come back. +::: + +## The Formats + +### JPEG (`.jpg`, `.jpeg`) + +The classic format for photographs. It uses **lossy** compression and supports millions of colors. + +- **Good for:** photos with smooth gradients and many colors +- **Not good for:** sharp text, line art, logos, or anything that needs a transparent background +- **Transparency:** no +- **Animation:** no +- **Support:** every browser, ever + +### PNG (`.png`) + +A **lossless** format that keeps crisp edges and supports **transparency**. + +- **Good for:** screenshots, diagrams, images with text, graphics that need a see-through background +- **Not good for:** large photographs, where files become heavy +- **Transparency:** yes, with smooth edges +- **Animation:** not in common use +- **Support:** every browser + +### GIF (`.gif`) + +An old format limited to **256 colors**, famous for short looping animations. + +- **Good for:** very small, simple animations +- **Not good for:** photos, or longer animations. Files are large and the color is poor +- **Transparency:** yes, but with hard, jagged edges +- **Animation:** yes +- **Support:** every browser + +For most animations today, a short **video** or an animated **WebP** is far smaller than a GIF with better quality. + +### WebP (`.webp`) + +A modern format from Google that can be **lossy or lossless**, with transparency and animation in one format. + +- **Good for:** almost everything. It is often noticeably smaller than JPEG and PNG +- **Transparency:** yes +- **Animation:** yes +- **Support:** all current major browsers + +### AVIF (`.avif`) + +A newer format based on a video codec. It often gives the **smallest files** for a given quality, with support for transparency and wide color. + +- **Good for:** photographs and graphics where every kilobyte counts +- **Trade-off:** slower to create, and a little slower to decode on weak devices +- **Transparency:** yes +- **Animation:** yes, but less common +- **Support:** current versions of the major browsers, though older ones may lack it, so offer a fallback + +### SVG (`.svg`) + +A **vector** format written in text (XML). It scales to any size without losing sharpness and can be styled and animated with CSS. + +- **Good for:** logos, icons, charts, illustrations with flat shapes +- **Not good for:** photographs +- **Transparency:** yes +- **Animation:** yes, with CSS or script +- **Support:** every modern browser + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="svg-sizes.html" +<!-- The same SVG file, shown at two sizes: both stay sharp --> +<img src="images/boat.svg" alt="A sailboat on blue waves" width="60" height="40" /> +<img src="images/boat.svg" alt="A sailboat on blue waves" width="240" height="160" /> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/svg-sizes.html"> +<> +<img src={sample} alt="A sailboat on blue waves" width="60" height="40" />{' '} +<img src={sample} alt="A sailboat on blue waves" width="240" height="160" /> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The drawing above is itself an SVG. Notice how it stays crisp at both sizes. A raster image enlarged four times would look soft. + +:::warning Treat SVG files from strangers with care +An SVG is text, and it can contain scripts. Loaded through `<img>`, scripts are blocked, so that is safe. Pasted directly into your page, or opened on its own, an untrusted SVG can run code. Only use SVGs from sources you trust, and sanitize any SVG that visitors upload. +::: + +### Others You May Meet + +| Format | What it is | Advice | +| :-- | :-- | :-- | +| **ICO** | The classic favicon format | Fine for favicons, though a PNG or SVG favicon also works in modern browsers | +| **HEIC / HEIF** | The default photo format on many phones | Convert to JPEG, WebP, or AVIF before using it on a web page | +| **BMP, TIFF** | Large, uncompressed formats | Do not use them on the web | +| **JPEG XL** | A newer format with strong features | Browser support is still limited, so check current support before relying on it | + +## Comparing the Main Formats + +| | JPEG | PNG | GIF | WebP | AVIF | SVG | +| :-- | :-- | :-- | :-- | :-- | :-- | :-- | +| Type | Raster | Raster | Raster | Raster | Raster | Vector | +| Compression | Lossy | Lossless | Lossless (256 colors) | Both | Both | Text | +| Photos | Great | Heavy | Poor | Great | Great | No | +| Sharp graphics and text | Poor | Great | Fair | Great | Great | Great | +| Transparency | No | Yes | Basic | Yes | Yes | Yes | +| Animation | No | No | Yes | Yes | Yes | Yes | +| Typical file size | Medium | Large | Large | Small | Smallest | Tiny for simple shapes | +| Browser support | Universal | Universal | Universal | Universal today | Wide, offer a fallback | Universal | + +Exact savings depend on the image, but as a rough guide, WebP is often around a quarter to a third smaller than a comparable JPEG, and AVIF is often smaller still. Always test your own images. + +## A Simple Decision Guide + +Ask these questions in order. + +1. **Is it a logo, icon, chart, or simple flat illustration?** Use **SVG**. +2. **Is it a photograph or a picture with rich color?** Use **AVIF or WebP**, with a **JPEG** fallback. +3. **Is it a screenshot, diagram, or picture with sharp text?** Use **WebP** (lossless) or **PNG**. +4. **Does it need a transparent background and it is not a vector?** Use **WebP**, **AVIF**, or **PNG**. +5. **Is it an animation?** Use a short **video** or an **animated WebP**. Avoid GIF unless it is tiny. + +| Your image | First choice | Fallback | +| :-- | :-- | :-- | +| Hero photo | AVIF or WebP | JPEG | +| Product photo with a white background | WebP | JPEG | +| Logo | SVG | PNG | +| Icon set | SVG | PNG | +| Chart | SVG, or WebP | PNG | +| Screenshot | WebP | PNG | +| Cutout with a transparent background | WebP | PNG | +| Short looping clip | Video | Animated WebP | +| Favicon | SVG or PNG | ICO | + +## Offering Fallbacks + +Not every browser understands every format. HTML gives you a clean way to offer several versions, and the browser picks the first one it can use. It is called the `<picture>` element, and you will study it in [Picture Element](./picture-element). Here is a preview. + +```html title="picture-preview.html" +<picture> + <source srcset="images/harbor.avif" type="image/avif" /> + <source srcset="images/harbor.webp" type="image/webp" /> + <img + src="images/harbor.jpg" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1200" + height="800" + /> +</picture> +``` + +A modern browser takes the AVIF. One that does not understand AVIF takes the WebP. The oldest takes the JPEG in the `<img>`, which also holds the `alt` text and the dimensions. + +## Preparing Images: A Practical Routine + +Picking a format is only part of the job. These steps make files light and tidy. + +1. **Resize first.** Decide the largest size the image will be shown at, then resize to about that (or twice that for sharp high-density screens). Never upload a 6000-pixel photo to show at 600. +2. **Crop** to the part that matters. +3. **Choose the format** with the guide above. +4. **Compress.** For lossy photos, a quality between about 70 and 85 usually looks the same as the original to the eye, at a fraction of the size. Compare before you decide. +5. **Strip extra data.** Photos often carry hidden **metadata** such as camera model, time, and even **GPS location**. Remove it before publishing. +6. **Name the file clearly,** in lowercase with hyphens. +7. **Check the result** in a browser, on a phone, at the real display size. + +### Tools to Help + +| Tool | What it is | +| :-- | :-- | +| **Squoosh** (web app) | Compare formats and quality side by side in your browser | +| **ImageMagick** | A command-line tool for resizing and converting | +| **cwebp / avifenc** | Command-line encoders for WebP and AVIF | +| **Sharp** | A popular library for processing images in Node.js builds | +| **SVGO** | A tool that makes SVG files smaller | +| **Your image editor** | "Export for web" options in many editors | + +A few commands, for those who like the terminal: + +```bash title="terminal" +# Resize a JPEG to 1200 pixels wide, with good quality +magick input.jpg -resize 1200x -quality 80 harbor-1200.jpg + +# Convert to WebP +cwebp -q 80 harbor-1200.jpg -o harbor-1200.webp + +# Convert to AVIF +avifenc --min 20 --max 35 harbor-1200.jpg harbor-1200.avif +``` + +Exact options differ between versions, so check each tool's help. + +:::info Privacy: remove location data +A photo taken on a phone may contain the exact coordinates of where it was taken. Publishing it without removing that data can reveal someone's home. Most export tools have a "remove metadata" option, and command-line tools such as `exiftool -all= photo.jpg` can strip it. +::: + +## Formats and Page Speed + +Image weight directly affects speed, and speed affects real people. + +| For a visitor on... | A heavy image page means... | +| :-- | :-- | +| A slow mobile network | Long waiting, and a page that may never finish loading | +| A limited data plan | Paying for every extra megabyte | +| An older phone | Slower decoding and a laggy page | +| A battery that is low | More energy used | + +Smaller images are one of the kindest things you can do for a global audience. A good target for most pages is to keep each content image **well under 200 KB**, and the whole page as light as you can. + +## Common Mistakes + +### Mistake 1: Using PNG for every photograph + +PNG files of photos can be several times larger than a good WebP or JPEG. + +### Mistake 2: Using JPEG for logos and text + +Lossy compression leaves fuzzy halos around sharp edges. Use SVG or PNG. + +### Mistake 3: Using a GIF for a long animation + +A short video is far lighter and sharper. + +### Mistake 4: Serving only AVIF or WebP with no fallback + +Some browsers may not display it. Use `<picture>` with a fallback. + +### Mistake 5: Re-saving a JPEG again and again + +Quality drops each time. Always export from the original. + +### Mistake 6: Keeping metadata + +It adds weight and can leak private information. + +### Mistake 7: Renaming a file to change its format + +Renaming `photo.png` to `photo.jpg` does not convert it. Use a proper export or conversion tool. + +### Mistake 8: Trusting an uploaded SVG + +Sanitize SVG files from visitors, or do not accept them. + +## Try It Yourself + +Here is a short project. + +1. Take one photo and save it as a JPEG at quality 90, 80, and 60. Compare their sizes and look at them side by side. +2. Convert the same photo to WebP and AVIF with Squoosh or a command-line tool. Note each file size. +3. Take a screenshot with text, and save it as PNG and as lossy JPEG. Zoom in on the text. Which looks cleaner? +4. Make or download a simple logo as SVG. Show it at three different sizes in an HTML page. Does it stay sharp? +5. Build a `<picture>` element that offers AVIF, WebP, and JPEG versions of your photo. +6. Check a photo's metadata with a tool such as `exiftool`, then strip it. +7. Write down which format you would choose for each image on a page of your own project, and why. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What is the difference between raster and vector images?</summary> + +Raster images are grids of pixels and get blurry when enlarged. Vector images are made of shapes and paths and stay sharp at any size. + +</details> + +<details> +<summary>2. What does lossy compression do?</summary> + +It permanently discards some detail that the eye barely notices, so files become much smaller. + +</details> + +<details> +<summary>3. Which format is best for logos and icons, and why?</summary> + +SVG, because it is a small vector format that scales to any size without losing sharpness. + +</details> + +<details> +<summary>4. Why offer a JPEG fallback when using AVIF or WebP?</summary> + +Some older browsers do not support the newer formats. The `<picture>` element lets each browser choose the best version it can display. + +</details> + +<details> +<summary>5. Why should you strip metadata from photos before publishing them?</summary> + +Metadata adds weight and can contain private details such as the exact location where a photo was taken. + +</details> + +## Key Takeaways + +- Use **SVG** for logos, icons, and simple graphics, and **AVIF or WebP** for photos, with a **JPEG** fallback. +- Use **PNG or lossless WebP** for screenshots and sharp text, and videos or animated WebP instead of GIF. +- Resize before you compress, compress sensibly, and strip metadata. +- Offer fallbacks with `<picture>` so every browser gets a format it understands. +- Lighter images make your site faster, cheaper, and kinder to visitors everywhere. + +Now you know which files to make. Next, learn how to make images fit every screen in [Responsive Images](./responsive-images). \ No newline at end of file diff --git a/tutorials/html/05-images/img-element.mdx b/tutorials/html/05-images/img-element.mdx index 7802ec308..e54fd158e 100644 --- a/tutorials/html/05-images/img-element.mdx +++ b/tutorials/html/05-images/img-element.mdx @@ -1,16 +1,419 @@ --- -id: img-element -title: "The HTML Image Element: Inserting Images" -sidebar_label: "Image Element (<img>)" +id: html-img-element +title: "The HTML img Element" +sidebar_label: "The img Element" sidebar_position: 2 slug: /html/images/img-element -description: "Learn the fundamentals of the HTML img tag, its void element syntax, inline display behavior, and basic usage on web pages." +description: "Learn how the HTML img element works. Understand how browsers load images, the core attributes, why images are inline, how to fix the small gap below an image, make images fit with CSS, handle broken images, and choose between img, picture, SVG, and CSS backgrounds on CodeHarborHub." keywords: + - HTML img element - HTML img tag - - image element HTML - - inserting web images - - void elements img + - HTML image tag + - add image to HTML + - responsive image max-width + - object-fit CSS + - broken image HTML + - HTML decoding async + - fetchpriority HTML + - img vs background-image + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, img-tag, markup, beginner] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, img, media, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +Think about what happens when you put a photograph on a wall. You have to decide which photograph, where to hang it, how big it should be, and what to write on the little label next to it for people who cannot see it. + +The `<img>` element is how you do all of that on a web page. It is one of the oldest and most used elements in HTML, and it looks simple. Behind that simplicity, there are details that decide whether your images load fast, fit the page, and work for everyone. This lesson shows you how `<img>` works, from the inside out. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- What the `<img>` element is, and why it is a "replaced" element +- What the browser does from the moment it finds an image +- The core attributes and some useful extras +- Why images are inline, and how to fix the small gap below them +- How to make images fit any screen with CSS +- What happens when an image fails, and how to prepare for it +- When to use `<img>`, and when to use something else + +## The Basics + +An image needs a source and a description. Everything else is a bonus. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="index.html" +<img + src="images/harbor.jpg" + alt="A small sailboat on blue waves under a bright sun" + width="240" + height="160" +/> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/index.html"> +<> +<img + src={sample} + alt="A small sailboat on blue waves under a bright sun" + width="240" + height="160" +/> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo uses a small drawing built into the page, since there are no image files here. In your project, `src` would be a file path like the one in the code. + +## A "Replaced" Element + +Most HTML elements contain their own content: a paragraph holds text, a list holds items. An `<img>` is different. It holds **nothing**. Its content comes from a **separate file** that the browser fetches and puts in its place. + +Because of this, `<img>` is called a **replaced element**, and it is also a **void element**: + +- It has **no closing tag**. Write `<img ... />` or `<img ...>`. +- It has **no children**. You cannot put text or other elements inside it. +- Its size comes from the file itself, unless you say otherwise. + +:::info In MDX, close it +In plain HTML, `<img ...>` is fine. In MDX and JSX, which this tutorial site uses, always write `<img ... />` with the closing slash. +::: + +## What the Browser Does With an Image + +Understanding this sequence explains many of the tips later in this section. + +1. **Reads the HTML** and finds the `<img>` element. +2. **Starts a request** for the file at `src`. This happens in parallel with other work, so the page keeps building. +3. **Reserves space,** if it knows the size from `width` and `height`. If not, the space is empty until the file arrives. +4. **Downloads the file** over the network. Big files take longer. +5. **Decodes the image,** turning the compressed file into pixels. +6. **Paints it** on the page. If the size was not reserved, the content below jumps to make room. + +This is why three habits matter so much: **small files** (steps 4 and 5), **`width` and `height`** (step 3), and **lazy loading** for images far down the page (step 2). You will learn each of them in this section. + +## The Core Attributes + +| Attribute | Purpose | Notes | +| :-- | :-- | :-- | +| `src` | The address of the image file | Required. See [Src and Alt](./src-and-alt) | +| `alt` | A text alternative | Required. Use `alt=""` for decoration | +| `width` | Width in pixels | Without `px`. Reserves space. See [Width and Height](./width-and-height) | +| `height` | Height in pixels | Same as above | +| `loading` | `eager` or `lazy` | See [Lazy Loading](./lazy-loading) | +| `srcset` | A list of image files at different sizes | See [Srcset and Sizes](./srcset-and-sizes) | +| `sizes` | How wide the image will be on screen | Works together with `srcset` | + +### A Few Extras Worth Knowing + +| Attribute | What it does | When to use it | +| :-- | :-- | :-- | +| `decoding="async"` | Lets the browser decode the image without blocking other work | Most content images | +| `fetchpriority="high"` | Hints that this image is very important | The main image at the top of a page, often called the "hero" | +| `crossorigin` | Controls how an image from another site is requested | When you draw it on a canvas, or use special security rules | +| `referrerpolicy` | Controls what is sent about your page | For privacy, as in [Link Security](/tutorials/html/links-and-navigation/link-security) | +| `title` | A tooltip | Use sparingly. Touch and keyboard users never see it | + +```html title="extras.html" +<!-- The big image at the top of the page: load first --> +<img + src="images/hero.jpg" + alt="Students learning to code together" + width="1200" + height="600" + fetchpriority="high" + decoding="async" +/> + +<!-- An image far down the page: load later --> +<img + src="images/team.jpg" + alt="The CodeHarborHub team on a video call" + width="600" + height="400" + loading="lazy" + decoding="async" +/> +``` + +:::tip Do not use `title` instead of `alt` +`alt` is for everyone who cannot see the image. `title` is only a tooltip that appears on mouse hover. They do different jobs, and `alt` is the one you must always write. +::: + +## Images Are Inline + +By default, an `<img>` behaves like a **letter in a sentence**, not like a paragraph. It sits on the same line as the text around it, and it lines up with the **baseline** of the text. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="inline.html" +<p> + A boat + <img src="images/boat-icon.png" alt="" width="24" height="24" /> + can sit right inside a sentence. +</p> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/inline.html"> +<> +<p> + A boat{' '} + <img src={sample} alt="" width="24" height="16" />{' '} + can sit right inside a sentence. +</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +That is perfect for small icons. For a large picture, you usually want it to stand alone as a block. + +### The Mysterious Gap + +If you put an image alone in a container, you may see a small **empty strip below it**. This is not a bug. The image sits on the text baseline, and the space under the baseline is reserved for letters like "g" and "y". + +There are two simple fixes. + +```css +/* Fix 1: make the image a block */ +img { + display: block; +} + +/* Fix 2: align it to the bottom of its line */ +img { + vertical-align: middle; +} +``` + +Many developers add one of these to every project. A common choice is `display: block` for large images and `vertical-align: middle` for icons beside text. + +## Making Images Fit: A Few Lines of CSS + +An image keeps its natural size unless told otherwise. A photograph that is 3000 pixels wide will overflow a phone screen. This short rule makes images shrink to fit their container, and never grow beyond their real size. + +```css title="images.css" +img { + max-width: 100%; + height: auto; +} +``` + +- `max-width: 100%` stops the image from being wider than its container. +- `height: auto` keeps the proportions, so the picture is not squashed. + +:::warning Keep `height: auto` with `width` and `height` attributes +When you set `width` and `height` in HTML **and** use `max-width: 100%`, add `height: auto` too. Without it, the image may stay tall while its width shrinks, and look stretched. +::: + +### Fitting an Image Into a Fixed Box + +Sometimes the box has a fixed shape, such as a square card. Use `object-fit` to decide how the picture fills it. + +| `object-fit` value | What happens | +| :-- | :-- | +| `fill` | Stretches to fill the box. Can distort the image | +| `contain` | Shows the whole image inside the box, with empty space if needed | +| `cover` | Fills the box and **crops** the extra. Best for cards and avatars | +| `none` | Keeps the original size | +| `scale-down` | Uses `none` or `contain`, whichever is smaller | + +```css title="card-image.css" +.card img { + width: 100%; + height: 200px; + object-fit: cover; + object-position: center; +} +``` + +### A Few More Handy Styles + +```css +.avatar { + width: 64px; + height: 64px; + border-radius: 50%; /* a circle */ + object-fit: cover; +} + +.framed { + border: 4px solid #e2e8f0; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(15, 23, 42, 0.15); +} +``` + +## When an Image Does Not Load + +Images fail more often than you might think: a typo in the path, a deleted file, a slow network, or a blocked request. The browser shows a **broken image icon**, and the `alt` text appears in its place. + +That is another reason `alt` matters: it is your fallback. + +```html +<img src="images/harbour.jpg" alt="Fishing boats resting in a calm harbor at sunrise" /> +<!-- If the file is named harbor.jpg, the path above is wrong. Visitors see the alt text. --> +``` + +You can also react in JavaScript, for example to show a default picture. + +```html title="fallback.html" +<img + id="profile" + src="images/users/amara.jpg" + alt="Profile photo of Amara" + width="64" + height="64" +/> + +<script> + const picture = document.getElementById("profile"); + picture.addEventListener("error", () => { + picture.src = "images/users/default.png"; + }, { once: true }); +</script> +``` + +The `{ once: true }` option makes sure the fallback runs only once, so a missing fallback file cannot cause an endless loop. + +### Quick Debugging Checklist + +1. **Check the path.** Is it relative to the right folder? See [Relative URLs](/tutorials/html/links-and-navigation/relative-urls). +2. **Check the spelling and case.** `Photo.JPG` is not `photo.jpg` on most servers. +3. **Check the file exists** and was uploaded. +4. **Open the browser's developer tools.** The Network tab shows failed requests in red. +5. **Check the file type.** A file that was renamed to `.jpg` but is really another format may fail to display. + +## Images That Are Links + +Wrap an `<img>` in an `<a>` to make it clickable. The `alt` text then becomes the link's name, so describe where the link goes. + +```html +<a href="/"> + <img src="images/logo.svg" alt="CodeHarborHub home" width="140" height="40" /> +</a> +``` + +## `img`, `picture`, SVG, or CSS Background? + +You have several ways to show an image. Each has a place. + +| Method | Best for | Notes | +| :-- | :-- | :-- | +| `<img>` | Almost all **content** images | Accessible, searchable, easy to lazy-load | +| `<picture>` | Different formats or crops for different screens | Contains an `<img>`. See [Picture Element](./picture-element) | +| Inline `<svg>` | Icons and graphics you want to style or animate | Part of the page's HTML | +| `<img src="file.svg">` | A logo or illustration as a separate file | Cacheable and simple | +| CSS `background-image` | **Decoration** that carries no meaning | Has no `alt`, so keep it for purely visual use | + +The rule of thumb: if the image **means something** to the reader, use `<img>`. If it is only decoration, a CSS background is fine. + +## Common Mistakes + +### Mistake 1: Forgetting `alt` + +Every `<img>` needs an `alt`. Use an empty one for decoration, never leave it out. + +### Mistake 2: Using a huge file for a tiny space + +A 4000-pixel photo shown at 300 pixels wastes data and time. Resize it first. + +### Mistake 3: Squashing an image with the wrong `width` and `height` + +Set values that match the image's real proportions, and use `height: auto` in CSS. + +### Mistake 4: Putting content inside `<img>` + +It is a void element. Text placed between `<img>` and `</img>` is invalid. + +### Mistake 5: Using a CSS background for an important picture + +Without `alt`, a screen reader skips it, and search engines may ignore it. + +### Mistake 6: Not testing on a slow connection + +Use the developer tools to slow the network down, then see how your page loads. + +### Mistake 7: Hot-linking someone else's image + +It uses their bandwidth, it can break without warning, and it may break copyright rules. Use your own copy, and only if you have the right to. + +## Try It Yourself + +Here is a short project. + +1. Create a folder `images` and put two pictures in it: one photo and one small icon. +2. Create `gallery.html` with an `<h1>` and add both images with `src`, `alt`, `width`, and `height`. +3. Add `img { max-width: 100%; height: auto; }` in a `<style>` block. Resize the browser window. What happens? +4. Put the photo alone in a `<div>`. Do you see a gap below it? Fix it with `display: block`. +5. Make a card with a fixed-height box and test the `object-fit` values `contain` and `cover`. +6. Break the `src` on purpose. What do you see? Check that the `alt` text makes sense on its own. +7. Wrap the icon in a link and write `alt` text that says where it goes. +8. Add `fetchpriority="high"` to the first image and `loading="lazy"` to the second. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. Why is `<img>` called a replaced element?</summary> + +Its content comes from an external file that the browser fetches and puts in its place. The element itself holds nothing. + +</details> + +<details> +<summary>2. Is `<img>` a block or an inline element by default?</summary> + +Inline. It sits in the flow of text, aligned to the text baseline. + +</details> + +<details> +<summary>3. What two CSS lines make images fit their container?</summary> + +`max-width: 100%;` and `height: auto;`. + +</details> + +<details> +<summary>4. What does `object-fit: cover` do?</summary> + +It makes the image fill its box completely and crops whatever does not fit, without distorting it. + +</details> + +<details> +<summary>5. When is a CSS background better than `<img>`?</summary> + +When the picture is only decoration and carries no meaning, because CSS backgrounds have no `alt` text. + +</details> + +## Key Takeaways + +- `<img>` is a void, inline, replaced element whose content comes from the file at `src`. +- Always provide `alt`, and add `width` and `height` to reserve space. +- Use `max-width: 100%` and `height: auto` so images fit any screen, and `object-fit` for fixed boxes. +- Use `display: block` or `vertical-align` to remove the small gap below an image. +- Choose `<img>` for meaningful content, and prepare for failure with good `alt` text and a clear debugging routine. + +Now you know how the element works. Next, learn how to point to the right file and describe it well in [Src and Alt](./src-and-alt). \ No newline at end of file diff --git a/tutorials/html/05-images/index.mdx b/tutorials/html/05-images/index.mdx index 9bc37f4d8..dad27f1ac 100644 --- a/tutorials/html/05-images/index.mdx +++ b/tutorials/html/05-images/index.mdx @@ -1,16 +1,250 @@ --- id: images-overview -title: "Working with Images in HTML" -sidebar_label: "Working with Images" +title: "HTML Images" +sidebar_label: "Images" sidebar_position: 1 slug: /html/images -description: "Master HTML image elements, responsive image techniques, performance optimizations, semantic figures, and image accessibility with CodeHarborHub." +description: "Learn how to add and manage images in HTML. Master the img element, src and alt, width and height, image formats, responsive images with srcset and the picture element, lazy loading, figure and figcaption, and accessible images with CodeHarborHub." keywords: - - HTML images overview - - HTML img tag tutorial - - responsive images HTML + - HTML images + - HTML img tag + - HTML alt text + - HTML image formats + - HTML responsive images + - HTML srcset and sizes + - HTML picture element + - HTML lazy loading images + - HTML figure and figcaption + - HTML accessible images - web image optimization + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, images, media, beginner] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, media, frontend] +--- + +A page with only text is like a book with no pictures. It can be great, but a photo of a harbor at sunrise, a chart that shows a trend, or a diagram that explains a machine can say in one second what takes a paragraph to describe. + +Images are also where web pages most often go wrong. They can make a page slow, break on small screens, shut out people who cannot see them, and cost visitors real money on mobile data. The good news is that every one of those problems has a simple, well-known solution in HTML. In this section, you will learn how to add images that look sharp, load fast, and work for everyone. + +<AdsComponent /> +<br /> + +## What You Will Learn + +In this section, you will be able to: + +- Add an image to a page with the **`<img>` element** +- Write a correct **`src`** and a meaningful **`alt`** text +- Set **`width` and `height`** so your page does not jump around while loading +- Pick the right **image format** for photos, graphics, and icons +- Serve the right size to every screen with **responsive images**, `srcset`, and `sizes` +- Choose formats and crops with the **`<picture>` element** +- Speed up your pages with **lazy loading** +- Add captions with **`<figure>` and `<figcaption>`** +- Make images **accessible** to people who cannot see them + +:::info Prerequisites +You should know how to write basic HTML elements and how file paths work. If you need a refresher, read [Relative URLs](/tutorials/html/links-and-navigation/relative-urls) first. +::: + +## Your First Image + +An image takes only one element. Here is the smallest useful version. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="index.html" +<img + src="images/harbor.jpg" + alt="Fishing boats resting in a calm harbor at sunrise" + width="300" + height="160" +/> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/index.html"> +<> +<img + src={"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 160'><rect width='300' height='160' fill='%23bfdbfe'/><circle cx='235' cy='48' r='22' fill='%23fbbf24'/><path d='M0 110 Q40 95 80 110 T160 110 T240 110 T300 110 V160 H0 Z' fill='%232563eb'/><path d='M0 130 Q40 118 80 130 T160 130 T240 130 T300 130 V160 H0 Z' fill='%231d4ed8'/><path d='M120 100 V55 L160 100 Z' fill='%23ffffff'/><rect x='112' y='100' width='56' height='8' rx='3' fill='%23334155'/></svg>"} + alt="A small sailboat on blue waves under a bright sun" + width="300" + height="160" +/> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo above uses a small drawing built right into the page, because this lesson has no image files to load. In your own project, `src` points to a real file such as `images/harbor.jpg`. + +## The Anatomy of an Image + +An `<img>` is a **void element**: it has no content and no closing tag, like `<br />` and `<hr />`. All the information lives in its attributes. + +```html +<img src="images/harbor.jpg" alt="Fishing boats at sunrise" width="300" height="160" /> +``` + +| Attribute | What it does | Required? | +| :-- | :-- | :-- | +| `src` | The **address** of the image file | Yes | +| `alt` | A **text alternative** for people and tools that cannot see the image | Yes, always | +| `width` and `height` | The image's **size in pixels**, so the browser can reserve space | Strongly recommended | +| `loading` | Whether to load the image right away or later (`lazy`) | Optional | +| `srcset` and `sizes` | Several versions of the image for different screens | Optional | + +## Three Questions to Ask About Every Image + +Before you add an image, ask yourself these three questions. They guide almost every decision in this section. + +| Question | Why it matters | Where you will learn it | +| :-- | :-- | :-- | +| **Does the image mean something?** | Meaningful images need helpful `alt` text. Decorative ones need an empty `alt` | [Src and Alt](./images/src-and-alt), [Accessible Images](./images/accessible-images) | +| **How big will it be on screen?** | A huge file on a small phone wastes data and time | [Responsive Images](./images/responsive-images), [Srcset and Sizes](./images/srcset-and-sizes) | +| **What is the best file type?** | A photo, a logo, and a chart each have a best format | [Image Formats](./images/image-formats) | + +## Choosing a Format at a Glance + +You will study formats in depth later. This quick map gets you started. + +| Your image is... | Good choice | Why | +| :-- | :-- | :-- | +| A photograph | JPEG, WebP, or AVIF | Small files for rich colors | +| A logo, icon, or simple illustration | SVG | Sharp at any size, and tiny | +| A screenshot or image with sharp text | PNG or WebP | Keeps edges crisp | +| A short animation | Animated WebP or video | Much smaller than a GIF | + +## Images and Page Speed + +Images are usually the **heaviest** part of a web page. On many sites, they make up more than half of everything a visitor has to download. A few habits make a big difference. + +1. **Resize before you upload.** Do not publish a 6000-pixel photo to show it at 600 pixels. +2. **Use modern formats** like WebP and AVIF when they fit. +3. **Give the browser sizes** with `width` and `height`, so the page does not jump. +4. **Offer several versions** with `srcset`, so phones download smaller files. +5. **Load later what is not visible yet** with `loading="lazy"`. + +Visitors around the world use slow connections and pay for each megabyte. Efficient images are not just a technical nicety. They make your page usable and affordable for everyone. + +## Images and Accessibility + +Some visitors cannot see your images. They may use a screen reader, have a very slow connection where images have not loaded, or use a text-only browser. The `alt` attribute is how your page speaks to them. + +<Tabs> +<TabItem value="bad" label="Not helpful" default> + +```html +<img src="chart.png" alt="chart" /> +<img src="photo1.jpg" alt="IMG_20261003_0457.jpg" /> +<img src="team.jpg" /> +``` + +</TabItem> +<TabItem value="good" label="Helpful"> + +```html +<img src="chart.png" alt="Bar chart: course sign-ups doubled between March and June" /> +<img src="photo1.jpg" alt="Students building a website together in a classroom" /> +<img src="divider.svg" alt="" /> +``` + +The last image is purely decorative, so its `alt` is intentionally empty. + +</TabItem> +</Tabs> + +:::tip The one-sentence test +Imagine reading the page aloud to a friend over the phone. What would you say in place of the picture? That sentence is your `alt` text. +::: + +## Your Learning Path + +Follow the lessons in order. Each one builds on the one before. + +<DocCardList /> + +## Common Beginner Mistakes + +Here are a few traps worth knowing about before you start. Each one has its own lesson later. + +| Mistake | What goes wrong | Where you will fix it | +| :-- | :-- | :-- | +| Leaving out `alt`, or writing "image" | Screen reader users get nothing, or noise | [Src and Alt](./images/src-and-alt) | +| A wrong file path | The image shows as a broken icon | [Src and Alt](./images/src-and-alt) | +| No `width` and `height` | The text jumps down when the image finally loads | [Width and Height](./images/width-and-height) | +| Using a huge photo for a small space | Slow pages and wasted data | [Responsive Images](./images/responsive-images) | +| Using PNG for every photo | Files several times bigger than needed | [Image Formats](./images/image-formats) | +| Loading every image at once | The page feels slow, even for images far below the fold | [Lazy Loading](./images/lazy-loading) | +| Putting important text inside an image | It cannot be searched, translated, or read aloud | [Accessible Images](./images/accessible-images) | +| Using someone else's picture without permission | Copyright trouble | See the tip below | + +:::warning Use images you have the right to use +Do not copy pictures from other websites. Use your own photos and drawings, or images with a license that allows reuse, and follow its rules for credit. When in doubt, ask or choose a different picture. +::: + +## Images for a Global Audience + +Your visitors come from many countries and cultures. A few thoughtful habits help. + +- **Write `alt` text in the language of the page,** and set the `lang` attribute. +- **Avoid text inside images.** It cannot be translated by browsers or read aloud. Put the words in HTML instead. +- **Choose pictures that many people can relate to.** Gestures, symbols, and clothing can mean different things in different places. +- **Think about data costs.** Smaller files are kinder to visitors on limited plans. +- **Show diverse people** when your pictures include people. + +<AdsComponent /> +<br /> + +## Quick Recap + +Test yourself. Click a question to reveal the answer. + +<details> +<summary>1. Which element adds an image, and does it need a closing tag?</summary> + +The `<img>` element. It is a void element, so it has no closing tag. + +</details> + +<details> +<summary>2. Which two attributes does every image need?</summary> + +`src`, the address of the file, and `alt`, a text alternative for people and tools that cannot see the image. + +</details> + +<details> +<summary>3. Why should you set `width` and `height`?</summary> + +They let the browser reserve space before the image loads, so the page does not jump. + +</details> + +<details> +<summary>4. What should the `alt` be for a purely decorative image?</summary> + +An empty value, `alt=""`, so screen readers skip it. + +</details> + +<details> +<summary>5. Name two ways to make images load faster.</summary> + +Resize them before uploading, use modern formats like WebP or AVIF, offer smaller versions with `srcset`, and use `loading="lazy"` for images below the fold. + +</details> + +## Key Takeaways + +- Add images with the `<img>` element, which needs `src` and `alt`. +- Write `alt` text that says what the image means. Use `alt=""` for decoration only. +- Set `width` and `height` to keep your layout steady while images load. +- Choose formats, sizes, and loading behavior with page speed and data costs in mind. +- Make every image work for everyone: describe it, caption it when it helps, and keep important text out of pictures. + +Ready to begin? Start with [The img Element](./images/img-element). \ No newline at end of file diff --git a/tutorials/html/05-images/lazy-loading.mdx b/tutorials/html/05-images/lazy-loading.mdx index a7b8e9e0f..a6336b515 100644 --- a/tutorials/html/05-images/lazy-loading.mdx +++ b/tutorials/html/05-images/lazy-loading.mdx @@ -1,16 +1,444 @@ --- -id: lazy-loading -title: "Optimizing Image Performance with Native Lazy Loading" +id: html-lazy-loading +title: "HTML Lazy Loading Images" sidebar_label: "Lazy Loading" sidebar_position: 9 slug: /html/images/lazy-loading -description: "Boost site load speed and save bandwidth by enabling native browser lazy loading using loading='lazy' on images below the fold." +description: "Learn how to lazy load images in HTML with the loading attribute. Understand which images to lazy load and which not to, protect your main image, reserve space with width and height, lazy load iframes, use IntersectionObserver, and measure the results on CodeHarborHub." keywords: - HTML lazy loading - loading lazy attribute - - page speed optimization - - image load performance + - lazy load images + - loading eager + - largest contentful paint LCP images + - fetchpriority high + - lazy load iframe + - IntersectionObserver lazy images + - image placeholder + - page speed images + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, performance, lazy-loading, web-vitals] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, lazy-loading, performance, frontend] +--- + +Imagine a restaurant that cooks every dish on its menu the moment you sit down, whether you order it or not. Dozens of plates would pile up, most would go cold, and your actual meal would arrive late. + +Browsers behave like that restaurant by default. When a page loads, they start downloading **every image**, including ones far down the page that the visitor may never scroll to. That wastes data, slows down the images that really matter, and makes the page feel heavy. + +**Lazy loading** fixes this. Images wait until the visitor is about to see them. Today it takes one attribute. In this lesson, you will learn how to use it, which images to leave out, and how to measure that it works. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- What lazy loading is, and why it helps +- How to use `loading="lazy"` and `loading="eager"` +- Which images to lazy load, and which **never** to lazy load +- Why `width` and `height` matter even more with lazy loading +- How to lazy load iframes and handle special cases +- A JavaScript fallback with `IntersectionObserver` +- How to check that it works +- Common mistakes, and how to avoid them + +## The One-Line Solution + +Add `loading="lazy"` to an image. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="lazy.html" +<img + src="images/team-photo.jpg" + alt="The CodeHarborHub team on a video call" + width="1200" + height="800" + loading="lazy" +/> +``` + +</TabItem> +<TabItem value="notes" label="What happens"> + +1. The page loads without downloading `team-photo.jpg`. +2. As the visitor scrolls, the browser notices the image is getting close to the screen. +3. The browser starts downloading it just before it comes into view. +4. By the time the visitor reaches it, the image is usually ready. + +</TabItem> +</Tabs> + +The browser, not you, decides **how early** to start. It begins loading when the image is within a certain distance of the visible area, and that distance can depend on the connection speed. On a fast connection, it loads closer to the moment of need. On a slow one, it starts earlier to leave time. + +## The `loading` Attribute + +| Value | What it does | +| :-- | :-- | +| `lazy` | Wait until the image is near the visible area, then load it | +| `eager` | Load right away. This is the **default** if you write nothing | + +```html +<img src="a.jpg" alt="..." loading="lazy" /> <!-- waits --> +<img src="b.jpg" alt="..." loading="eager" /> <!-- loads at once --> +<img src="c.jpg" alt="..." /> <!-- same as eager --> +``` + +You rarely need to write `eager`. It is useful only to override a lazy default set somewhere else. + +## Which Images Should Be Lazy? + +A page has a **visible area** when it first opens, often called **above the fold**. Everything beyond it is **below the fold**. + +```text +┌──────────────────────────┐ +│ Logo Menu │ ← above the fold +│ ┌────────────────────┐ │ Load these immediately +│ │ Hero image │ │ +│ └────────────────────┘ │ +│ Welcome to the site │ +├──────────────────────────┤ ← the fold +│ ┌─────┐ ┌─────┐ │ ← below the fold +│ │ pic │ │ pic │ │ Lazy load these +│ └─────┘ └─────┘ │ +│ ... │ +│ ┌────────────────────┐ │ +│ │ Footer picture │ │ +│ └────────────────────┘ │ +└──────────────────────────┘ +``` + +| Image | Lazy? | Why | +| :-- | :-- | :-- | +| The main image at the top of the page (hero) | **No** | It is the first thing visitors see. Delaying it hurts | +| The logo in the header | **No** | It is visible at once | +| Images in the first screen of content | **No** | They are needed immediately | +| Images in the middle and bottom of a long page | **Yes** | The visitor may never reach them | +| Images in a gallery below the first row | **Yes** | Most are off-screen | +| Thumbnails in a long list | **Yes** | Hundreds can be far off-screen | +| Images in tabs, accordions, and modals that start hidden | **Yes**, with care | They are not visible until opened | + +:::warning Never lazy load your main image +The largest image visible when the page opens is usually what search engines measure as **Largest Contentful Paint (LCP)**, the moment the page seems loaded. Lazy loading it makes the page look slow. Give it `fetchpriority="high"` instead. +::: + +### The Hero Image Done Right + +```html title="hero.html" +<img + src="images/hero.jpg" + alt="Students learning to code together" + width="1600" + height="800" + fetchpriority="high" + decoding="async" +/> +<!-- No loading="lazy" here --> +``` + +`fetchpriority="high"` tells the browser: "this one matters most, download it first." + +### A Simple Rule + +> **Eager and high priority for what is visible at the start. Lazy for everything else.** + +If you are not sure which images are above the fold, remember that screens differ. A tall desktop monitor shows more than a small phone. When in doubt, leave the first one or two images on the page as normal. + +## Always Set `width` and `height` + +With lazy loading, an image arrives long after the page was built. If the browser has not reserved space for it, the content below will **jump** when the image appears, just as in the example from [Width and Height](./width-and-height). + +Worse, without a size, the browser thinks every unloaded image is 0 pixels tall. It may then consider *all* the lazy images "close to the screen" and start loading them all at once. That cancels the benefit. + +<Tabs> +<TabItem value="bad" label="Problem" default> + +```html +<img src="a.jpg" alt="..." loading="lazy" /> +<!-- No size: no space reserved, and the page jumps --> +``` + +</TabItem> +<TabItem value="good" label="Good"> + +```html +<img src="a.jpg" alt="..." width="800" height="600" loading="lazy" /> +<style> + img { max-width: 100%; height: auto; } +</style> +``` + +</TabItem> +</Tabs> + +## A Complete Gallery Example + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="gallery.html" +<h1>Harbor Gallery</h1> + +<!-- The first picture is in the first screen: load normally --> +<img + src="images/harbor-1.jpg" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1200" + height="800" + fetchpriority="high" +/> + +<!-- The rest are below the fold: lazy --> +<img src="images/harbor-2.jpg" alt="Nets drying on a pier" width="1200" height="800" loading="lazy" /> +<img src="images/harbor-3.jpg" alt="A lighthouse at dusk" width="1200" height="800" loading="lazy" /> +<img src="images/harbor-4.jpg" alt="Waves breaking on dark rocks" width="1200" height="800" loading="lazy" /> +``` + +</TabItem> +<TabItem value="notes" label="What loads when"> + +| Moment | What downloads | +| :-- | :-- | +| Page opens | `harbor-1.jpg` (high priority) | +| Visitor scrolls near picture 2 | `harbor-2.jpg` | +| Visitor scrolls near picture 3 | `harbor-3.jpg` | +| Visitor never scrolls to picture 4 | `harbor-4.jpg` is never downloaded | + +</TabItem> +</Tabs> + +If the visitor leaves after the first screen, three images were never downloaded. That is data saved for them, and bandwidth saved for you. + +## Lazy Loading With `srcset` and `<picture>` + +Lazy loading works with everything you have learned. Put `loading` on the final `<img>`. + +```html title="lazy-picture.html" +<picture> + <source type="image/avif" srcset="images/team-800.avif 800w, images/team-1600.avif 1600w" sizes="100vw" /> + <source type="image/webp" srcset="images/team-800.webp 800w, images/team-1600.webp 1600w" sizes="100vw" /> + <img + src="images/team-800.jpg" + srcset="images/team-800.jpg 800w, images/team-1600.jpg 1600w" + sizes="100vw" + alt="The CodeHarborHub team on a video call" + width="1600" + height="1067" + loading="lazy" + decoding="async" + /> +</picture> +``` + +`decoding="async"` is a good companion: it lets the browser decode the image off the main thread so scrolling stays smooth. + +## Lazy Loading Iframes + +`loading="lazy"` also works on `<iframe>`, which is helpful for embedded videos and maps that are heavy to load. + +```html title="lazy-iframe.html" +<iframe + src="https://www.youtube-nocookie.com/embed/VIDEO_ID" + title="Course introduction video" + width="560" + height="315" + loading="lazy" + allowfullscreen> +</iframe> +``` + +`VIDEO_ID` is a placeholder. Replace it with the real ID of the video you are embedding. Always give an iframe a descriptive `title`, and keep in mind that an embedded frame from another site can load scripts, so embed only sources you trust. + +## Placeholders: Something to Look at While Waiting + +Between the page opening and the image arriving, the reserved space is empty. A calm placeholder makes the wait feel smoother. + +```css title="placeholder.css" +.photo { + background: #e2e8f0; /* a soft color while loading */ + aspect-ratio: 3 / 2; +} +``` + +Other ideas, from simple to advanced: + +| Technique | Description | +| :-- | :-- | +| **Solid color** | A neutral color or the picture's average color | +| **Low-quality preview** | A tiny, blurred version that is replaced by the sharp one | +| **Gradient** | A soft gradient that matches the picture's tones | +| **Skeleton** | A gray shape that matches the layout | + +Keep placeholders subtle. Flashing or moving effects can bother some visitors, so respect `prefers-reduced-motion` if you animate anything. + +## A JavaScript Fallback With `IntersectionObserver` + +Native lazy loading is supported by all current major browsers. If you need more control, such as for CSS background images or custom timing, you can build your own with `IntersectionObserver`, which tells you when an element enters the screen. + +```html title="observer.html" +<img + class="lazy" + src="images/placeholder.svg" + data-src="images/team-photo.jpg" + alt="The CodeHarborHub team on a video call" + width="1200" + height="800" +/> +``` + +```js title="observer.js" +const images = document.querySelectorAll("img.lazy"); + +if ("IntersectionObserver" in window) { + const observer = new IntersectionObserver((entries, obs) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + const img = entry.target; + img.src = img.dataset.src; // start the real download + img.classList.remove("lazy"); + obs.unobserve(img); // stop watching this one + }); + }, { rootMargin: "200px 0px" }); // start 200px before it appears + + images.forEach((img) => observer.observe(img)); +} else { + // Very old browsers: just load everything + images.forEach((img) => { img.src = img.dataset.src; }); +} +``` + +:::info Prefer the native attribute +The native `loading="lazy"` needs no JavaScript, works even if scripts fail, and lets the browser use what it knows about the network. Reach for `IntersectionObserver` only when you truly need it. If you write your own, keep a `<noscript>` fallback so visitors without JavaScript still see the image. +::: + +## Special Cases and Cautions + +- **Images in carousels.** Slides that are not visible yet can be lazy. Make sure the next slide loads before the visitor arrives, or it will flash in empty. +- **Images in hidden tabs or accordions.** Browsers may not load images inside hidden elements until they are shown. Test that they appear quickly when opened. +- **Printing.** A page printed before the visitor scrolled may show empty spaces for unloaded images. Many browsers handle this, but test if printing matters for your page. +- **Search engines.** Modern search engines understand `loading="lazy"`. Avoid hiding important images behind scroll-only JavaScript tricks that crawlers cannot trigger. +- **Screen readers.** The `alt` text is available even before the image loads, so write it carefully. See [Accessible Images](./accessible-images). +- **Very small images.** Lazy loading a 1 KB icon saves almost nothing, and the extra scheduling work is not worth it. + +## Measuring the Result + +Do not guess. Check. + +1. **Open the Network tab** in your browser's developer tools and filter by **Img**. +2. **Reload without scrolling.** Which images were downloaded? Only the ones near the top should appear. +3. **Scroll slowly.** Watch new images appear in the list just before they come into view. +4. **Compare totals.** Note the "transferred" size with and without `loading="lazy"`. +5. **Run Lighthouse** or **PageSpeed Insights.** Look at the LCP, CLS, and total page weight. +6. **Throttle the connection** to "Slow 3G" and see how the first screen behaves. + +| Check | What a good result looks like | +| :-- | :-- | +| First screen images | Load first and fast | +| Off-screen images | Not downloaded until you scroll near them | +| Layout | No jumps as images appear | +| LCP image | Not lazy, and with high priority | + +## Lazy Loading for a Global Audience + +For visitors on limited data plans, lazy loading can save a large share of what a page costs. Pages with long galleries, blogs with many pictures, and shops with many thumbnails benefit most. It also helps people with older phones, since fewer images are decoded at once. + +Pair it with the other ideas in this section: modern formats, correctly sized files with `srcset`, and `width` and `height`. Together, they make a page that is quick and affordable everywhere. + +## Common Mistakes + +### Mistake 1: Lazy loading the main image + +It delays the most important image and makes the page look slow. Leave it eager, and add `fetchpriority="high"`. + +### Mistake 2: Lazy loading every image on the page + +The first-screen images should load normally. + +### Mistake 3: Forgetting `width` and `height` + +You get layout jumps, and the browser may load all lazy images early. + +### Mistake 4: Lazy loading tiny icons + +The saving is negligible, and the delay may be visible. + +### Mistake 5: Relying on a script with no fallback + +If JavaScript fails, the image never appears. Prefer native lazy loading, or provide `<noscript>`. + +### Mistake 6: Hiding important images from crawlers + +Do not make content images appear only after custom scroll events that search engines cannot trigger. + +### Mistake 7: Not testing + +Check the Network tab and a real phone. Behavior changes with screen size and connection speed. + +### Mistake 8: Skipping `alt` + +Lazy images still need good `alt` text. + +## Try It Yourself + +Here is a short project. + +1. Build a page with a hero image and at least ten pictures in a long gallery. +2. Give every image `width` and `height`, and the standard `max-width: 100%; height: auto;` CSS. +3. Open the Network tab, filter by Img, and reload. Note how many images download and their total size. +4. Add `loading="lazy"` to every image except the hero, and add `fetchpriority="high"` to the hero. Reload and compare. +5. Scroll slowly and watch images appear in the Network tab. +6. Set the connection to "Slow 3G" and compare again. +7. Add a soft background color to the image boxes, and notice how it looks while waiting. +8. Bonus: write an `IntersectionObserver` version for one image, with a `<noscript>` fallback. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What does `loading="lazy"` do?</summary> + +It tells the browser to wait and load the image only when it is near the visible area, instead of at page load. + +</details> + +<details> +<summary>2. Which images should you never lazy load?</summary> + +Images visible when the page opens, especially the main (hero) image that often determines Largest Contentful Paint. Give that one `fetchpriority="high"`. + +</details> + +<details> +<summary>3. Why are `width` and `height` especially important with lazy loading?</summary> + +They reserve space so the page does not jump when the image arrives, and they stop the browser from thinking all unloaded images are close to the screen. + +</details> + +<details> +<summary>4. Does lazy loading work on iframes?</summary> + +Yes. `loading="lazy"` can also be used on `<iframe>`, which helps with heavy embeds like videos and maps. + +</details> + +<details> +<summary>5. When would you use `IntersectionObserver` instead of the native attribute?</summary> + +When you need more control, such as for CSS background images or custom loading timing. Otherwise, native lazy loading is simpler and more robust. + +</details> + +## Key Takeaways + +- Lazy loading delays off-screen images, saving data and making the first screen faster. +- Add `loading="lazy"` to images below the fold, and never to the main image at the top. +- Give the main image `fetchpriority="high"`, and every image `width` and `height`. +- Use calm placeholders, and consider `IntersectionObserver` only when you need extra control. +- Measure with the Network tab and Lighthouse, and test on slow connections. + +Your images now load when they are needed. Next, learn how to add captions that belong with their images in [Figure and Figcaption](./figure-and-figcaption). \ No newline at end of file diff --git a/tutorials/html/05-images/picture-element.mdx b/tutorials/html/05-images/picture-element.mdx index 2425f295e..1139349a4 100644 --- a/tutorials/html/05-images/picture-element.mdx +++ b/tutorials/html/05-images/picture-element.mdx @@ -1,16 +1,439 @@ --- -id: picture-element -title: "Art Direction with the HTML picture Element" -sidebar_label: "Picture Element (<picture>)" -sidebar_position: 6 +id: html-picture-element +title: "The HTML picture Element" +sidebar_label: "Picture Element" +sidebar_position: 8 slug: /html/images/picture-element -description: "Master the picture element to provide fallback image formats, media query conditioning, and advanced art direction for various device viewports." +description: "Learn how the HTML picture element works. Use source and img together to switch image formats with fallbacks, art direction with media queries, combine srcset and sizes, serve dark-mode images, and avoid common mistakes with AVIF, WebP and JPEG on CodeHarborHub." keywords: - HTML picture element - - picture vs img - - art direction web design - - WebP AVIF fallback + - HTML source element + - picture AVIF WebP fallback + - art direction images + - picture media query + - prefers-color-scheme picture + - picture srcset sizes + - responsive images picture + - image type attribute + - dark mode images HTML + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, picture-tag, responsive-design, media] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, picture, responsive, frontend] +--- + +export const wide = "data:image/svg+xml;utf8," + encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 120'><rect width='240' height='120' fill='#dbeafe'/><circle cx='200' cy='30' r='14' fill='#fbbf24'/><path d='M0 90 Q30 78 60 90 T120 90 T180 90 T240 90 V120 H0 Z' fill='#2563eb'/><path d='M100 82 V40 L135 82 Z' fill='#ffffff'/><rect x='94' y='82' width='48' height='7' rx='3' fill='#334155'/></svg>"); + +export const crop = "data:image/svg+xml;utf8," + encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 120'><rect width='120' height='120' fill='#dbeafe'/><circle cx='95' cy='25' r='10' fill='#fbbf24'/><path d='M0 90 Q15 78 30 90 T60 90 T90 90 T120 90 V120 H0 Z' fill='#2563eb'/><path d='M40 82 V30 L82 82 Z' fill='#ffffff'/><rect x='32' y='82' width='58' height='8' rx='3' fill='#334155'/></svg>"); + +Most of the time, a single `<img>` is all you need. But sometimes the browser needs a **choice** that you want to control yourself: use this file format if you understand it, otherwise that one; show this crop on a phone and that crop on a desktop; show a light logo in a dark theme. + +The `<picture>` element is the tool for these jobs. It wraps one or more `<source>` elements and a final `<img>`. The browser goes through the sources from top to bottom, and takes the **first one that matches**. If none matches, it uses the `<img>`. It is a small element with a lot of power, and in this lesson, you will see its three main uses. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- The structure of `<picture>`, and the role of each part +- How the browser decides which `<source>` to use +- How to offer **modern formats** with a safe fallback +- How to do **art direction** with different crops for different screens +- How to combine `<picture>` with `srcset` and `sizes` +- How to serve different images for **light and dark mode** +- Common mistakes, and how to avoid them + +## The Structure + +```html title="structure.html" +<picture> + <source ... /> <!-- zero or more sources, checked in order --> + <source ... /> + <img ... /> <!-- required: the fallback, and the real image --> +</picture> +``` + +| Part | Its job | +| :-- | :-- | +| `<picture>` | A container. It does not display anything itself | +| `<source>` | A candidate. It says "use this file **if** these conditions are true" | +| `<img>` | The **required** last child. It is the fallback and also holds `alt`, `width`, `height`, `loading`, and styling | + +:::warning The `<img>` is not optional +Without a final `<img>`, nothing is displayed. The `<img>` is also where `alt`, `width`, and `height` belong. Never put `alt` on a `<source>`. +::: + +### What a `<source>` Can Say + +| Attribute | Meaning | Example | +| :-- | :-- | :-- | +| `srcset` | The file (or files) to use | `srcset="images/harbor.webp"` | +| `type` | The file's MIME type. The browser skips the source if it cannot display that type | `type="image/avif"` | +| `media` | A media condition. The source applies only when it is true | `media="(min-width: 60rem)"` | +| `sizes` | The display width, as in `<img sizes>` | `sizes="100vw"` | +| `width` and `height` | Dimensions of the file, to reserve space | `width="800" height="800"` | + +### How the Browser Chooses + +1. Look at the first `<source>`. Does its `media` condition match? Does the browser support its `type`? +2. If **yes**, use it and stop looking. +3. If **no**, move to the next `<source>`. +4. If none matches, use the `<img>`'s own `src` and `srcset`. + +The browser stops at the **first match**, so the **order is important**. + +## Use 1: Modern Formats With a Fallback + +Newer formats like AVIF and WebP are smaller, but older browsers may not understand them. `<picture>` lets you offer them safely. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="formats.html" +<picture> + <source srcset="images/harbor.avif" type="image/avif" /> + <source srcset="images/harbor.webp" type="image/webp" /> + <img + src="images/harbor.jpg" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1200" + height="800" + /> +</picture> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/formats.html"> +<> +<picture> + <img + src={wide} + alt="Fishing boats resting in a calm harbor at sunrise" + width="240" + height="120" + style={{maxWidth: '100%', height: 'auto'}} + /> +</picture> +<p>Here the picture holds only an image, since the demo has no AVIF or WebP files to try.</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +What each browser does with that code: + +| Browser | Result | +| :-- | :-- | +| Understands AVIF | Uses `harbor.avif`, the smallest file | +| Does not understand AVIF, understands WebP | Skips the first source, uses `harbor.webp` | +| Understands neither | Uses `harbor.jpg` from the `<img>` | + +Put the **best and newest** format first, the next best second, and the universal fallback last in the `<img>`. + +:::tip Why the `type` attribute matters +Without `type`, the browser would have to download the file to find out whether it can show it. With `type`, it knows at once and skips sources it cannot use without any wasted download. +::: + +### Common MIME Types + +| Format | `type` value | +| :-- | :-- | +| AVIF | `image/avif` | +| WebP | `image/webp` | +| JPEG | `image/jpeg` | +| PNG | `image/png` | +| SVG | `image/svg+xml` | +| GIF | `image/gif` | + +## Use 2: Art Direction + +**Art direction** means showing a different *picture* depending on the situation, not just a different size of the same one. + +Imagine a wide photograph of a harbor. On a desktop, it is lovely. On a narrow phone, it shrinks until the sailboat is a speck. A tighter, square crop around the boat would work far better. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="art-direction.html" +<picture> + <!-- On narrow screens, use the tight square crop --> + <source + media="(max-width: 40rem)" + srcset="images/harbor-square.jpg" + width="800" + height="800" + /> + <!-- Otherwise, use the wide picture --> + <img + src="images/harbor-wide.jpg" + alt="A white sailboat on blue waves under a bright sun" + width="1600" + height="800" + /> +</picture> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/art-direction.html"> +<> +<picture> + <source media="(max-width: 40rem)" srcSet={crop} width="120" height="120" /> + <img + src={wide} + alt="A white sailboat on blue waves under a bright sun" + width="240" + height="120" + style={{maxWidth: '100%', height: 'auto'}} + /> +</picture> +<p>On a screen narrower than 40rem, this shows a tight square crop. On a wider screen, it shows the wide picture.</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +This demo is live. If you are reading on a phone, you see the square crop. On a computer, you see the wide version. Make your browser window narrower to watch it change. + +### Several Breakpoints + +You can add as many sources as you need. Order them from the **most specific** (usually the smallest screen) to the least. + +```html title="breakpoints.html" +<picture> + <source media="(max-width: 30rem)" srcset="images/hero-portrait.jpg" /> + <source media="(max-width: 60rem)" srcset="images/hero-square.jpg" /> + <img src="images/hero-wide.jpg" alt="Students learning to code together" width="1600" height="800" /> +</picture> +``` + +### Remember: Same Meaning, Different Crop + +All the versions must convey the **same information** to match the single `alt` text. If the wide version shows a whole classroom and the narrow version shows only one student, the `alt` may be wrong for one of them. Choose crops that keep the main subject. + +## Use 3: Combining With `srcset` and `sizes` + +Each `<source>` can have its own `srcset` and `sizes`, so you can offer several **sizes** of each **format**. This is the full power of responsive images. + +```html title="full-example.html" +<picture> + <source + type="image/avif" + srcset=" + images/harbor-400.avif 400w, + images/harbor-800.avif 800w, + images/harbor-1600.avif 1600w + " + sizes="(min-width: 60rem) 50vw, 100vw" + /> + <source + type="image/webp" + srcset=" + images/harbor-400.webp 400w, + images/harbor-800.webp 800w, + images/harbor-1600.webp 1600w + " + sizes="(min-width: 60rem) 50vw, 100vw" + /> + <img + src="images/harbor-800.jpg" + srcset=" + images/harbor-400.jpg 400w, + images/harbor-800.jpg 800w, + images/harbor-1600.jpg 1600w + " + sizes="(min-width: 60rem) 50vw, 100vw" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1600" + height="1067" + loading="lazy" + decoding="async" + /> +</picture> +``` + +This looks long, but it is straightforward: three formats, each with three sizes. The browser first picks the best format it understands, then the best size from that format's list. + +Build tools and image services can generate this markup for you, so you rarely need to write it by hand for a whole site. + +## Use 4: Light and Dark Mode + +The `media` attribute can test the visitor's color theme. This is useful for logos and diagrams that need a different version on dark backgrounds. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="dark-mode.html" +<picture> + <source srcset="images/logo-light.svg" media="(prefers-color-scheme: dark)" /> + <img src="images/logo-dark.svg" alt="CodeHarborHub" width="160" height="48" /> +</picture> +``` + +</TabItem> +<TabItem value="notes" label="How it reads"> + +If the visitor's system is set to dark mode, the browser uses `logo-light.svg`, a light-colored logo that stands out on a dark background. Otherwise, it uses `logo-dark.svg`, a dark logo for light backgrounds. + +</TabItem> +</Tabs> + +If your page has its own theme switch that does not follow the system setting, the media query will not know about it. In that case, use CSS classes and swap the images with JavaScript or CSS. + +### Other Useful Media Conditions + +| Condition | Matches when | +| :-- | :-- | +| `(orientation: portrait)` | The window is taller than wide | +| `(min-resolution: 2dppx)` | The screen is high-density | +| `(prefers-reduced-motion: reduce)` | The visitor prefers less motion (useful for choosing a still image over an animation) | +| `print` | The page is being printed | + +```html title="print.html" +<picture> + <source media="print" srcset="images/diagram-high-contrast.png" /> + <img src="images/diagram-color.png" alt="Diagram of how a browser loads an image" width="800" height="500" /> +</picture> +``` + +## Styling a `<picture>` + +The `<picture>` element is only a wrapper. The visible image is the `<img>` inside, so **style the `<img>`**. + +```css title="picture.css" +picture img { + max-width: 100%; + height: auto; + display: block; + border-radius: 8px; +} +``` + +Styles written for `picture` itself, such as `border-radius` or `width`, affect the invisible wrapper and may not do what you expect. Put the CSS on the `<img>`. + +## Choosing Between `<img srcset>` and `<picture>` + +| You want to... | Use | +| :-- | :-- | +| Offer several **sizes** of the same picture and let the browser choose | `<img>` with `srcset` and `sizes` | +| Offer several **formats** with a fallback | `<picture>` with `type` | +| Show a different **crop or composition** on different screens | `<picture>` with `media` | +| Swap images for **dark mode** or **print** | `<picture>` with `media` | +| Do all of these | `<picture>` with sources that also have `srcset` and `sizes` | + +Remember: with `srcset` the browser *decides*. With `<picture>` and `media`, *you* decide, and the browser follows your rules. Use the simplest tool that does the job. + +## Accessibility and Global Audiences + +- **One `alt`, on the `<img>`.** Every source shares it, so write text that fits all versions. +- **Keep the content equal.** A crop that removes important information is an accessibility problem. +- **Do not put text in the images.** Different crops may cut it off, and translators cannot reach it. +- **Think about data costs.** A format fallback chain lets visitors with newer browsers download less. Visitors in places where data is expensive benefit the most. +- **Respect preferences.** Dark mode, reduced motion, and print are real needs, and `<picture>` lets you honor them. + +## Common Mistakes + +### Mistake 1: Forgetting the `<img>` + +Without it, nothing shows, and there is nowhere for `alt` to go. + +### Mistake 2: Putting `alt` on `<source>` + +Only the `<img>` takes `alt`, `width`, and `height`. + +### Mistake 3: Putting the fallback format first + +Browsers stop at the first match. If JPEG is first, they never reach the AVIF. + +### Mistake 4: Leaving out `type` on format sources + +The browser may download files it cannot use or make a worse choice. + +### Mistake 5: Wrong order of media conditions + +The first matching source wins. List narrower conditions first, so a wider condition does not catch everything. + +### Mistake 6: Using `<picture>` when `srcset` is enough + +If you only change **sizes**, an `<img>` with `srcset` and `sizes` is simpler, and the browser can adapt to the network. + +### Mistake 7: Styling the `<picture>` instead of the `<img>` + +The visible image is the `<img>`. + +### Mistake 8: Different crops that change the meaning + +The single `alt` must fit them all. + +### Mistake 9: Forgetting `width` and `height` + +They prevent layout shift, as you learned in [Width and Height](./width-and-height). When crops have different shapes, set the dimensions on each `<source>` too. + +## Try It Yourself + +Here is a short project. + +1. Take a wide photo and make three versions: AVIF, WebP, and JPEG. Compare their file sizes. +2. Build a `<picture>` with two `<source>` elements (AVIF and WebP, each with `type`) and a JPEG `<img>` with `alt`, `width`, and `height`. +3. Open the Network tab. Which file does your browser download? +4. Make a tight square crop of the same photo. Add a `<source media="(max-width: 40rem)">` for it. +5. Resize your browser or use the device toolbar. Does the crop change at the right width? +6. Add `srcset` and `sizes` to the sources, using two sizes of each file. +7. Make a light and a dark version of a simple logo, and swap them with `prefers-color-scheme`. +8. Style `picture img` with `max-width: 100%`, `height: auto`, and a rounded corner. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What are the required parts of a `<picture>` element?</summary> + +A `<picture>` wrapper and a final `<img>`. The `<source>` elements are optional, but they are what makes `<picture>` useful. + +</details> + +<details> +<summary>2. How does the browser choose between several `<source>` elements?</summary> + +It checks them from top to bottom and uses the first one whose `media` condition matches and whose `type` it supports. If none match, it uses the `<img>`. + +</details> + +<details> +<summary>3. Why add a `type` attribute to a format source?</summary> + +So the browser can skip formats it does not support without downloading anything. + +</details> + +<details> +<summary>4. What is art direction?</summary> + +Showing a different crop or composition of an image for different situations, such as a tight square on small screens and a wide picture on large ones. + +</details> + +<details> +<summary>5. Where do `alt`, `width`, and `height` belong in a `<picture>`?</summary> + +On the final `<img>` element, never on the `<source>` elements (except that `<source>` may carry `width` and `height` for its own file). + +</details> + +## Key Takeaways + +- `<picture>` holds `<source>` elements and a required `<img>`, and the browser uses the first matching source. +- Use `type` to offer AVIF and WebP with a JPEG fallback, and `media` for different crops, dark mode, or print. +- Sources can have their own `srcset` and `sizes`, so you can offer sizes for each format. +- Put `alt`, `width`, `height`, and `loading` on the `<img>`, and style the `<img>` rather than the `<picture>`. +- Choose the simplest tool: `srcset` for sizes, `<picture>` when you need to control the format or the crop. + +Now you can control exactly which image each visitor gets. Next, learn how to delay loading images that are not yet visible with [Lazy Loading](./lazy-loading). \ No newline at end of file diff --git a/tutorials/html/05-images/responsive-images.mdx b/tutorials/html/05-images/responsive-images.mdx index c76f11e58..7d8f187c7 100644 --- a/tutorials/html/05-images/responsive-images.mdx +++ b/tutorials/html/05-images/responsive-images.mdx @@ -1,16 +1,393 @@ --- -id: responsive-images -title: "Introduction to Responsive Images in HTML" +id: html-responsive-images +title: "Responsive Images in HTML" sidebar_label: "Responsive Images" -sidebar_position: 5 +sidebar_position: 6 slug: /html/images/responsive-images -description: "Discover core responsive image concepts, device pixel ratios, viewport switching, art direction, and serving screen-optimized visuals." +description: "Learn the big picture of responsive images in HTML. Understand screen sizes and pixel density, flexible images with CSS, resolution switching with srcset, art direction with the picture element, fluid galleries with CSS grid, and how to test what the browser downloads on CodeHarborHub." keywords: - responsive images HTML - - high DPI screens images + - responsive images CSS - device pixel ratio - - art direction HTML + - CSS pixels vs device pixels + - fluid image gallery CSS grid + - srcset and picture overview + - art direction images + - resolution switching + - img currentSrc + - mobile first images + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, responsive-design, images, css] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, responsive, performance, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +Your page will be seen on a tiny phone held in one hand, on a tablet on a kitchen table, on a laptop, on a huge monitor in an office, and on a television across a room. The screens differ in size by a factor of ten, in sharpness by a factor of three, and the internet connections feeding them differ even more. + +If you serve the same single image to all of them, somebody loses. The phone downloads far more than it can show. The big monitor gets a blurry, stretched picture. **Responsive images** are the set of tools HTML and CSS give you so that every visitor gets an image that fits their screen, looks sharp, and does not waste their data. This lesson is the map. The next lessons walk each road in detail. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- Why one image file cannot suit every device +- The difference between **CSS pixels** and **device pixels** +- The three problems responsive images solve +- How to make images flexible with CSS, and build a fluid gallery +- A first look at `srcset`, `sizes`, and `<picture>` +- How to check which file the browser actually chose +- A simple plan for choosing the right technique + +## Why One File Is Not Enough + +Picture a 2400-pixel-wide photograph, sized for a large desktop. + +| Visitor | What goes wrong with the single big file | +| :-- | :-- | +| A phone on a slow network | Downloads about 1 MB when a 100 KB version would look the same on a small screen | +| A tablet | Wastes data, and decodes a huge image for a small display | +| A very large, sharp monitor | Might actually need that size, and a smaller file would look soft | +| Someone on a limited data plan | Pays for pixels they can never see | + +Now imagine the opposite: a 400-pixel image for everyone. It loads quickly, but it looks blurry on large and sharp screens. **Neither extreme is good for everyone.** The answer is to offer a choice and let the browser pick. + +## A Short Lesson in Pixels + +To understand responsive images, you need to know two kinds of pixels. + +| Kind | What it is | +| :-- | :-- | +| **CSS pixel** | The unit you write in HTML and CSS, such as `width="300"`. It is a *logical* unit | +| **Device pixel** | A physical dot on the screen | + +On older screens, one CSS pixel was one device pixel. On modern **high-density** screens, one CSS pixel is covered by two, three, or even more device pixels. The ratio is called the **device pixel ratio (DPR)**. + +| Screen | Typical DPR | A 300 CSS-pixel-wide image needs about... | +| :-- | :-- | :-- | +| Older or budget monitors | 1 | 300 pixels of image data | +| Many laptops and phones | 2 | 600 pixels | +| Some high-end phones | 3 | 900 pixels | + +This is why a photo that looks crisp on one device can look soft on another, and why "just make everything big" and "just make everything small" both fail. + +## Three Problems, Three Tools + +Responsive images solve three different problems. Knowing which one you have tells you which tool to use. + +| Problem | What you need | Tool | Lesson | +| :-- | :-- | :-- | :-- | +| **1. The image should fit its space** | A flexible image that never overflows | CSS: `max-width`, `width`, `aspect-ratio`, `object-fit` | This lesson | +| **2. The right size for each device** | The same picture in several sizes, so each device downloads what it needs | `srcset` and `sizes` on `<img>` | [Srcset and Sizes](./srcset-and-sizes) | +| **3. The right picture for each situation** | A different crop, shape, or file format | The `<picture>` element | [Picture Element](./picture-element) | + +The first problem is about **layout**. The second is about **resolution** (called *resolution switching*). The third is about **content** (called *art direction*) or **format**. Many pages need all three. + +## Tool 1: Flexible Images With CSS + +You met these rules in [The img Element](./img-element) and [Width and Height](./width-and-height). + +```css title="images.css" +img { + max-width: 100%; + height: auto; +} +``` + +With them, an image never overflows its container, keeps its shape, and shrinks smoothly as the window narrows. Put the real `width` and `height` in the HTML, so the browser reserves the right space. + +### A Fluid Gallery With CSS Grid + +For a set of pictures, CSS Grid can adjust the number of columns to the available space with no media queries at all. + +<Tabs> +<TabItem value="code" label="HTML + CSS" default> + +```html title="gallery.html" +<style> + .gallery { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 0.75rem; + } + .gallery img { + width: 100%; + aspect-ratio: 3 / 2; + object-fit: cover; + display: block; + } +</style> + +<div class="gallery"> + <img src="images/a.jpg" alt="Sailboat at sunrise" width="600" height="400" /> + <img src="images/b.jpg" alt="Fishing nets drying on a pier" width="600" height="400" /> + <img src="images/c.jpg" alt="A lighthouse at dusk" width="600" height="400" /> + <img src="images/d.jpg" alt="Waves breaking on rocks" width="600" height="400" /> +</div> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/gallery.html"> +<> +<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))', gap: '0.75rem'}}> + <img src={sample} alt="Sailboat at sunrise" width="240" height="160" style={{width: '100%', aspectRatio: '3 / 2', objectFit: 'cover', display: 'block'}} /> + <img src={sample} alt="Sailboat at midday" width="240" height="160" style={{width: '100%', aspectRatio: '3 / 2', objectFit: 'cover', display: 'block'}} /> + <img src={sample} alt="Sailboat in the afternoon" width="240" height="160" style={{width: '100%', aspectRatio: '3 / 2', objectFit: 'cover', display: 'block'}} /> + <img src={sample} alt="Sailboat at dusk" width="240" height="160" style={{width: '100%', aspectRatio: '3 / 2', objectFit: 'cover', display: 'block'}} /> +</div> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +Resize the window and the grid reflows: four columns on a wide screen, two or one on a narrow one. The `aspect-ratio` and `object-fit: cover` keep every tile the same shape. + +## Tool 2: A Taste of `srcset` and `sizes` + +Flexible CSS fixes **layout**, but the browser still downloads one file. To let each device download a **different size**, you give the browser a menu. + +```html title="srcset-preview.html" +<img + src="images/harbor-800.jpg" + srcset=" + images/harbor-400.jpg 400w, + images/harbor-800.jpg 800w, + images/harbor-1600.jpg 1600w + " + sizes="(min-width: 60rem) 50vw, 100vw" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1600" + height="1067" +/> +``` + +In plain words: + +- `srcset` lists the available files, with each file's real width in pixels (the `w` number). +- `sizes` tells the browser how wide the image will be on screen: half the window on wide screens, the full window otherwise. +- The browser knows its own screen size, pixel density, and often its network conditions. It picks the best file from the menu. +- `src` is the fallback for browsers that do not understand `srcset`. + +You do not choose the file. You **describe the options**, and the browser decides. The details come in [Srcset and Sizes](./srcset-and-sizes). + +## Tool 3: A Taste of `<picture>` + +Sometimes you do not want the browser to choose a size. You want to choose **which picture** or **which format**. + +### Art Direction: Different Crops + +A wide landscape photo works on a desktop. On a narrow phone screen, the same photo shrinks until the main subject is tiny. A tighter crop would work much better. + +```html title="art-direction-preview.html" +<picture> + <source media="(max-width: 40rem)" srcset="images/harbor-crop-square.jpg" /> + <img + src="images/harbor-wide.jpg" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1600" + height="900" + /> +</picture> +``` + +### Format Switching + +```html title="format-preview.html" +<picture> + <source srcset="images/harbor.avif" type="image/avif" /> + <source srcset="images/harbor.webp" type="image/webp" /> + <img src="images/harbor.jpg" alt="Fishing boats at sunrise" width="1200" height="800" /> +</picture> +``` + +You will practice both in [Picture Element](./picture-element). + +## Comparing the Three + +| | CSS only | `srcset` and `sizes` | `<picture>` | +| :-- | :-- | :-- | :-- | +| Who decides which file loads? | You (one file) | The **browser** | You set rules, the browser follows the **first match** | +| Solves | Fitting the layout | Right size for each screen and density | Right crop or right format | +| Same picture? | Yes | Yes, in several sizes | Can be different pictures | +| Extra files needed? | No | Yes, several sizes | Yes, several crops or formats | +| Complexity | Low | Medium | Medium to high | + +## Mobile First: A Good Habit + +Build for the smallest screen first, then enhance for bigger ones. For images, this means: + +1. **Start with a small, light default** in `src`. A visitor on a weak connection still gets something good, fast. +2. **Offer larger versions** through `srcset` for screens that can use them. +3. **Use `<picture>`** only where a different crop or format is really worth the extra work. + +This way, nobody downloads more than they need, and the worst-case experience is still a good one. + +## What About CSS Background Images? + +Background images defined in CSS can also be responsive. They do not have `alt` text, so keep them for decoration only. + +```css title="background.css" +.hero { + background-image: url("images/hero-800.jpg"); + background-size: cover; + background-position: center; +} + +@media (min-width: 60rem) { + .hero { background-image: url("images/hero-1600.jpg"); } +} + +/* Different files for different pixel densities */ +@media (min-resolution: 2dppx) { + .hero { background-image: url("images/hero-1600.jpg"); } +} +``` + +Content images that carry meaning should stay in `<img>`, where `alt`, `srcset`, and `<picture>` are available. + +## How to See What the Browser Chose + +With `srcset` and `<picture>`, the browser picks a file. You can find out which one. + +### In the Browser Tools + +1. Open your page and open the **developer tools**. +2. Go to the **Network** tab and filter by **Img**. +3. Reload the page and note which files were downloaded. +4. Use the **device toolbar** to pretend to be a phone, change the screen size, and set a slow connection. Reload again and compare. + +### With JavaScript + +```js title="current-src.js" +const pictures = document.querySelectorAll("img"); +pictures.forEach((img) => { + console.log(img.alt, "→", img.currentSrc, `(${img.naturalWidth} px wide)`); +}); +``` + +`currentSrc` is the file the browser is using right now. `naturalWidth` is that file's real width in pixels. + +:::tip Test like your visitors +Test on a real phone as well as in the device toolbar, on mobile data, if you can. Pay attention to how fast the first screen appears, and whether images look sharp. +::: + +## A Simple Plan + +Use this checklist the next time you add an image. + +1. **Is it decoration?** Consider a CSS background, or `alt=""`. +2. **Set `width` and `height`,** and use `max-width: 100%; height: auto;`. +3. **Resize and compress** a sensible set of sizes, such as 400, 800, and 1600 pixels wide. +4. **Add `srcset` and `sizes`** so each device can pick its size. +5. **Do the crops differ on small screens?** Use `<picture>` with `media`. +6. **Do you want modern formats?** Use `<picture>` with `type` and a JPEG fallback. +7. **Is the image far down the page?** Add `loading="lazy"`. +8. **Test** on a small and a large screen. + +## Responsive Images and Global Audiences + +Responsive images matter most to people with the fewest resources. + +- **Data is expensive** in many regions. A well-sized image can cost a tenth as much as an oversized one. +- **Networks vary widely,** even within a city. Light defaults make your page usable on weak connections. +- **Devices vary widely.** A budget phone struggles to decode a giant image. +- **Do not put text inside images,** since a scaled-down image can make the text unreadable. Keep words in HTML, where they adapt to the screen and can be translated. + +## Common Mistakes + +### Mistake 1: One huge file for everyone + +It wastes data and slows pages. Offer several sizes. + +### Mistake 2: Forgetting `max-width: 100%` + +Large images overflow narrow screens and force sideways scrolling. + +### Mistake 3: `srcset` without `sizes` + +Without `sizes`, the browser assumes the image fills the whole window, and may download too large a file. You will learn the right way in the next lesson. + +### Mistake 4: Using `<picture>` when `srcset` is enough + +If you only need different sizes of the **same** picture, `srcset` is simpler and lets the browser decide. + +### Mistake 5: Not testing + +What you see on a fast laptop is not what visitors see on a slow phone. + +### Mistake 6: Hiding images with CSS instead of not loading them + +`display: none` on an image may still download it. Use `<picture>` or lazy loading to avoid unneeded downloads. + +### Mistake 7: Missing `alt` text on the inner `<img>` + +In a `<picture>`, only the `<img>` carries `alt`, `width`, and `height`. Never leave them out. + +## Try It Yourself + +Here is a short project. + +1. Choose one photo and export it at 400, 800, and 1600 pixels wide. +2. Add the 800-pixel version with `width`, `height`, and `alt`, and the standard CSS rules. +3. Build the fluid gallery with CSS Grid, using four pictures, and resize your window. +4. Add the `srcset` preview from this lesson to one image, and open the Network tab to see which file is chosen at different window sizes. +5. Change the device toolbar to a phone and reload. Which file loads now? +6. Log `currentSrc` and `naturalWidth` for each image with the JavaScript snippet. +7. Make a tighter crop of your photo and use `<picture>` with a `media` condition so phones receive it. +8. Write one sentence for each image on your page: which of the three problems does it solve? + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. Why can't one image file suit every device?</summary> + +Screens differ in size, pixel density, and network speed. A large file wastes data on small screens, and a small file looks blurry on large, sharp ones. + +</details> + +<details> +<summary>2. What is the difference between a CSS pixel and a device pixel?</summary> + +A CSS pixel is a logical unit used in code. A device pixel is a physical dot on the screen. On high-density screens, one CSS pixel can cover several device pixels. + +</details> + +<details> +<summary>3. Which tool solves "right size for each device"?</summary> + +`srcset` with `sizes`, which lets the browser choose from several sizes of the same image. + +</details> + +<details> +<summary>4. When do you need `<picture>` instead of `srcset`?</summary> + +When you want a different crop for different screens (art direction), or you want to offer different file formats with fallbacks. + +</details> + +<details> +<summary>5. How can you tell which file the browser actually loaded?</summary> + +Look at the Network tab in developer tools, or read the image's `currentSrc` in JavaScript. + +</details> + +## Key Takeaways + +- Responsive images give every visitor an image that fits their screen, looks sharp, and does not waste data. +- CSS makes images **flexible**. `srcset` and `sizes` offer the **right size**. `<picture>` offers the **right crop or format**. +- High-density screens need more pixels in the file than the CSS size suggests. +- Think mobile first: a light default, with larger files for screens that can use them. +- Always test with developer tools and on real devices. + +Now you can see the whole picture. Next, learn how to give the browser a menu of sizes in [Srcset and Sizes](./srcset-and-sizes). \ No newline at end of file diff --git a/tutorials/html/05-images/src-and-alt.mdx b/tutorials/html/05-images/src-and-alt.mdx index 9d3a0dd90..0ef1ec0cb 100644 --- a/tutorials/html/05-images/src-and-alt.mdx +++ b/tutorials/html/05-images/src-and-alt.mdx @@ -1,16 +1,447 @@ --- -id: src-and-alt -title: "Image Sources and Alt Text: src and alt Attributes" -sidebar_label: "src & alt Attributes" +id: html-src-and-alt +title: "HTML Image src and alt Attributes" +sidebar_label: "Src and Alt" sidebar_position: 3 slug: /html/images/src-and-alt -description: "Understand the critical role of src paths and descriptive alt text for image rendering, screen readers, fallback handling, and image SEO." +description: "Learn how to write the src and alt attributes of an HTML image. Point to the right file with relative, root-relative and absolute paths, name files well, and write alt text for photos, icons, charts, logos, linked images and decorative graphics in any language on CodeHarborHub." keywords: - - HTML image src - - alt attribute accessibility - - descriptive alt text - - image fallback text + - HTML src attribute + - HTML alt attribute + - HTML image alt text + - how to write alt text + - empty alt decorative image + - HTML image path + - image file naming SEO + - alt text for charts + - alt text for linked images + - alt text best practices + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, accessibility, seo, attributes] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, src, alt, accessibility, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +Two small attributes decide whether an image works at all: **`src`** tells the browser *where* the picture is, and **`alt`** tells everyone *what* it is when they cannot see it. + +One is about the machine, the other is about people. Both are easy to get wrong, and both are worth getting right. A wrong `src` gives your visitors a broken icon. A missing or lazy `alt` shuts out anyone who uses a screen reader, and it quietly hurts your page in search results too. This lesson makes both attributes simple. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- How `src` works, with relative, root-relative, and absolute paths +- How to name and organize image files +- What `alt` text is, and who relies on it +- How to write great `alt` text for photos, icons, charts, logos, and linked images +- When to use an **empty** `alt` +- How `alt` works in different languages +- Common mistakes, and how to test your images + +## Part 1: The `src` Attribute + +`src` stands for **source**. Its value is the address of the image file. It follows the same rules as any other URL, so everything you learned in [Relative URLs](/html/links-and-navigation/relative-urls) and [Absolute URLs](/html/links-and-navigation/absolute-urls) applies here. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="index.html" +<img src="images/harbor.jpg" alt="Fishing boats at sunrise" width="240" height="160" /> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/index.html"> +<> +<img src={sample} alt="A small sailboat on blue waves under a bright sun" width="240" height="160" /> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo uses a small drawing built into the page. In your project, `src` points to a real file. + +### Four Ways to Write a Path + +Imagine this project. + +```text +my-website/ +├── index.html +├── images/ +│ ├── logo.svg +│ └── team/ +│ └── photo.jpg +└── blog/ + └── first-post.html +``` + +| Kind | Example | Where it is measured from | +| :-- | :-- | :-- | +| **Relative to the page** | `images/logo.svg` | The folder of the current page | +| **Going up a folder** | `../images/logo.svg` | One folder above the current page | +| **Root-relative** | `/images/logo.svg` | The root of the website | +| **Absolute** | `https://example.com/images/logo.svg` | Nowhere. It is complete | + +In `index.html`, you write `images/team/photo.jpg`. In `blog/first-post.html`, the same file is `../images/team/photo.jpg`. + +:::tip Pick one habit and keep it +Relative paths work everywhere, including on your own computer. Root-relative paths are tidy but need the site to live at the top of a domain. Absolute paths are for images hosted somewhere else, such as a content delivery network (CDN) you control. +::: + +### Name Your Files Well + +A good file name helps you, your teammates, and search engines. + +| Weak | Better | Why | +| :-- | :-- | :-- | +| `IMG_4521.JPG` | `students-coding-workshop.jpg` | Says what the picture shows | +| `Final Logo (2).png` | `codeharborhub-logo.png` | No spaces, brackets, or "final" | +| `Photo.JPG` | `photo.jpg` | Lowercase avoids case problems on servers | +| `café-münchen.jpg` | `cafe-munchen.jpg` | Plain letters work everywhere | + +Rules to follow: + +1. **Use lowercase letters, numbers, and hyphens.** +2. **Describe the content,** with a few words. +3. **Avoid spaces and special characters.** If a space is unavoidable, it must be written as `%20` in the URL. +4. **Keep the extension honest.** A `.jpg` should be a real JPEG. + +### Images From Another Site + +You can point `src` to a picture on another website. + +```html +<img src="https://images.example.com/photos/sunrise.jpg" alt="Sunrise over a harbor" width="600" height="400" /> +``` + +Do this only with permission, or for files that a service clearly offers for embedding. Otherwise you use their bandwidth, the file may change or vanish, and you may break copyright rules. Always prefer a copy that you control. Use `https` so browsers do not block the image on a secure page. + +### Data URIs: Images Inside the Code + +A `data:` URI places the whole image inside the `src` text. It needs no separate file, but it makes the HTML long. It is useful only for very small images, such as the tiny drawings in this tutorial. + +```html +<img + src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><circle cx='5' cy='5' r='4' fill='%232563eb'/></svg>" + alt="" + width="24" + height="24" +/> +``` + +For anything bigger, use a normal file, so the browser can cache it. + +## Part 2: The `alt` Attribute + +`alt` stands for **alternative text**. It is a short description that stands in for the image when the picture cannot be seen or shown. + +### Who Uses `alt` Text? + +| Who | How they meet `alt` | +| :-- | :-- | +| **Screen reader users** | Their software reads the `alt` aloud | +| **People on slow or failed connections** | The browser shows `alt` while the image loads, or if it fails | +| **People who turned images off** | To save data, or for focus | +| **Search engines** | They read `alt` to understand and index the image | +| **Text-only and reader-mode tools** | They show `alt` instead of the picture | +| **Voice assistants and translation tools** | They use `alt` to describe a page | + +Roughly speaking, `alt` is not an extra. It is the **version of the image** for everyone who cannot see it. + +### The Golden Rule + +> Write the `alt` text that would give the visitor the same information or the same function as the image. + +Ask: **what is this image doing here?** + +- Is it giving **information**? Say that information. +- Is it a **link or button**? Say where it goes or what it does. +- Is it **decoration**? Leave `alt` empty. + +## How to Write Good `alt` Text + +### 1. Be Specific and Concise + +Describe what matters, in a short phrase or sentence. Aim for around 125 characters or fewer as a guide, not a strict rule. + +<Tabs> +<TabItem value="weak" label="Weak" default> + +```html +<img src="boats.jpg" alt="boats" /> +<img src="boats.jpg" alt="image" /> +<img src="boats.jpg" alt="boats.jpg" /> +<img src="boats.jpg" alt="harbor sunrise boats water sea fishing photo best cheap" /> +``` + +</TabItem> +<TabItem value="strong" label="Strong"> + +```html +<img src="boats.jpg" alt="Fishing boats resting in a calm harbor at sunrise" /> +``` + +</TabItem> +</Tabs> + +### 2. Do Not Start With "Image of" or "Picture of" + +Screen readers already announce "image" or "graphic." Starting with those words repeats it. + +| Instead of | Write | +| :-- | :-- | +| "Image of a girl reading a book" | "A girl reading a book under a tree" | +| "Photo of our office" | "Our office, with a long table and large windows" | + +### 3. Match the Image to the Context + +The same picture can need different `alt` text on different pages. + +| Page | Picture of a lighthouse | Good `alt` | +| :-- | :-- | :-- | +| Travel guide | A lighthouse at dusk | "A white lighthouse glowing at dusk on a rocky coast" | +| Article on architecture | The same photo | "The lighthouse's spiral stone tower, built in 1850" | +| Company logo area | A lighthouse logo | "Beacon Books home" | + +### 4. Do Not Stuff Keywords + +Search engines recognize it, visitors find it annoying, and screen reader users have to listen to it. Write for people. + +### 5. Use Normal Sentences and Punctuation + +A final period helps screen readers pause naturally, and it is optional. What matters is that the text reads smoothly aloud. + +## Writing `alt` for Different Kinds of Images + +| Type of image | What to write | Example | +| :-- | :-- | :-- | +| **Photo that supports an article** | What is shown, and why it matters | `alt="Students on a video call, sharing their code on a screen"` | +| **Logo** | The organization's name, and where it goes if linked | `alt="CodeHarborHub"` or `alt="CodeHarborHub home"` | +| **Icon with a label next to it** | Empty, since the label already says it | `alt=""` | +| **Icon alone, in a button or link** | The **action** or destination | `alt="Search"`, `alt="Download the PDF"` | +| **Decorative divider or background shape** | Empty | `alt=""` | +| **Photo of a person** | Who, and what they are doing, if it matters | `alt="Amara Okafor, course instructor, smiling at a whiteboard"` | +| **Chart or graph** | The main conclusion, and give the data elsewhere | `alt="Bar chart: course sign-ups doubled between March and June"` | +| **Screenshot** | What it shows, and the key details | `alt="Browser window showing the page with a blue Sign Up button"` | +| **Image of text** | The same words | `alt="Sale ends Sunday"` | +| **Map** | Where, and what the reader needs from it | `alt="Map: the school is two blocks north of the train station"` | + +### Linked Images + +When an image is the only thing inside a link, the `alt` text **is** the link text. Describe the destination. + +```html +<a href="/"> + <img src="images/logo.svg" alt="CodeHarborHub home" width="140" height="40" /> +</a> +``` + +### Charts and Complex Images + +A short `alt` cannot hold all the data in a chart. Give a brief conclusion in `alt`, and put the full information next to the image as text, in a table, or in a longer description. + +```html +<figure> + <img + src="images/signups.png" + alt="Bar chart: course sign-ups doubled between March and June" + width="600" + height="360" + /> + <figcaption> + Sign-ups grew from 120 in March to 250 in June. + <a href="#signups-table">See the full data table.</a> + </figcaption> +</figure> +``` + +You will see how `<figure>` and `<figcaption>` work in [Figure and Figcaption](./figure-and-figcaption), and go deeper on these cases in [Accessible Images](./accessible-images). + +## Part 3: The Empty `alt` + +Some images do not add anything for a person who cannot see them. Examples are decorative lines, background swirls, and icons that repeat the text next to them. For these, write an **empty** `alt`. + +```html +<img src="images/divider.svg" alt="" width="300" height="12" /> +``` + +A screen reader **skips** an image with `alt=""`. That is exactly what you want. + +### Empty vs Missing: A Big Difference + +| What you write | What a screen reader may do | +| :-- | :-- | +| `alt=""` | Skips the image completely. Correct for decoration | +| `alt` left out entirely | May read the file name, such as "IMG underscore 4521 dot jpg," or announce "image" with no explanation | +| `alt="decorative image"` | Reads those words aloud, which is just noise | + +:::warning Never leave `alt` out +An `<img>` without `alt` is invalid HTML, and it is a real barrier. If the image is decorative, write `alt=""`. If it is meaningful, write a description. +::: + +### Is It Decoration? Test It + +Ask: **if I remove this image, does the page lose any information or function?** + +- If **no**, it is decoration. Use `alt=""`, or put it in CSS as a background. +- If **yes**, describe what would be lost. + +## `alt`, Captions, and `title` + +These three are different tools. + +| | `alt` | Caption (`<figcaption>`) | `title` | +| :-- | :-- | :-- | :-- | +| Seen by | Mostly people who cannot see the image | Everyone | Mouse users on hover | +| Purpose | A replacement for the image | Extra information about the image | A tooltip | +| Required? | Always | Optional | Optional, use rarely | + +Do not copy the same text into both `alt` and the caption. If a caption already describes the image well, the `alt` can be shorter or focus on what the caption leaves out. + +## `alt` for a Global Audience + +- **Write `alt` in the language of the page.** A Hindi page needs Hindi `alt` text, so Hindi screen readers pronounce it properly. +- **Mark text in another language** with `lang` on the image, for example `<img ... alt="Bonjour" lang="fr" />`. +- **Avoid slang and idioms,** which translate badly in automatic tools. +- **Use plain, clear words.** Many visitors read in their second or third language. +- **Spell out names** with their usual spelling, and avoid abbreviations people may not know. +- **Do not hide key information only in the picture.** Translation tools cannot translate text inside an image. + +<Tabs> +<TabItem value="en" label="English" default> + +```html +<img src="images/library.jpg" alt="Students reading quietly in the school library" /> +``` + +</TabItem> +<TabItem value="es" label="Español"> + +```html +<img src="images/library.jpg" alt="Estudiantes leyendo en silencio en la biblioteca de la escuela" /> +``` + +</TabItem> +<TabItem value="hi" label="हिन्दी"> + +```html +<img src="images/library.jpg" alt="स्कूल के पुस्तकालय में शांति से पढ़ते विद्यार्थी" /> +``` + +</TabItem> +</Tabs> + +## Testing Your Images + +Do not guess. Check. + +1. **Turn off images** in your browser settings, or break a `src` on purpose. Does the page still make sense with only the `alt` text? +2. **Use a screen reader** for a minute: VoiceOver on Apple devices, TalkBack on Android, or a free one such as NVDA on Windows. +3. **Run an accessibility checker.** Browser developer tools and extensions flag missing `alt`. +4. **Read all your `alt` text in a row.** Do the descriptions sound useful, or repetitive? +5. **Ask someone else** what they understand from the `alt` alone. + +## Common Mistakes + +### Mistake 1: A wrong path + +A typo, a wrong folder, or a capital letter breaks the image. Check against your folder map. + +### Mistake 2: Missing `alt` + +Always include it, even if empty. + +### Mistake 3: Useless `alt` such as "image" or the file name + +It adds noise and no information. + +### Mistake 4: Keyword stuffing + +It harms accessibility and trust. + +### Mistake 5: Describing too much + +A paragraph in `alt` is hard to listen to. Put long details in the page text. + +### Mistake 6: Describing decoration + +If the image adds nothing, use `alt=""`, and do not make visitors listen to it. + +### Mistake 7: Describing the look instead of the function + +A search icon inside a button should say "Search," not "magnifying glass." + +### Mistake 8: Important words inside the image only + +Repeat the text in the `alt`, or better, put it in HTML. + +## Try It Yourself + +Here is a short project. + +1. Create a folder `images` with at least five pictures of different kinds: a photo, a logo, an icon, a decorative shape, and a chart or screenshot. +2. Rename every file with a clear, lowercase, hyphenated name. +3. Create `alt-practice.html` and add each image with a correct `src`. +4. Write a thoughtful `alt` for each one, using the table in this lesson. +5. Make the logo a link to the home page, with `alt` that describes the destination. +6. Mark the decorative shape with `alt=""`. +7. Break one `src` on purpose and check that the page still makes sense. +8. Turn on a screen reader and listen to the page. Rewrite any `alt` that sounds odd. +9. Bonus: write the same `alt` texts in a second language. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What does the `src` attribute contain?</summary> + +The address of the image file, as a relative, root-relative, or absolute URL. + +</details> + +<details> +<summary>2. Why are lowercase, hyphenated file names recommended?</summary> + +Many servers are case-sensitive, and spaces or special characters can break URLs. Clear names also help people and search engines. + +</details> + +<details> +<summary>3. What is the main purpose of `alt` text?</summary> + +To give the same information or function as the image to anyone who cannot see it. + +</details> + +<details> +<summary>4. When should `alt` be empty?</summary> + +When the image is decorative or its meaning is already given by nearby text, so that a screen reader skips it. + +</details> + +<details> +<summary>5. What should `alt` say for an image that is the only content of a link?</summary> + +Where the link goes, such as "CodeHarborHub home," because the `alt` text becomes the link's name. + +</details> + +## Key Takeaways + +- `src` points to the file. Use correct relative paths, simple lowercase file names, and `https` for outside images. +- `alt` is the image's text version. Write it for the visitor who cannot see the picture. +- Match the `alt` to the image's job: information, function, or decoration. +- Use `alt=""` for decoration, never leave `alt` out, and never write "image of." +- Write `alt` in the page's language, keep it concise, and test with images turned off and a screen reader. + +You can now point to your images and describe them well. Next, learn how to stop your page from jumping while images load with [Width and Height](./width-and-height). \ No newline at end of file diff --git a/tutorials/html/05-images/srcset-and-sizes.mdx b/tutorials/html/05-images/srcset-and-sizes.mdx index 0b096a796..a5d780248 100644 --- a/tutorials/html/05-images/srcset-and-sizes.mdx +++ b/tutorials/html/05-images/srcset-and-sizes.mdx @@ -1,16 +1,448 @@ --- -id: srcset-and-sizes -title: "Resolution Switching with srcset and sizes Attributes" -sidebar_label: "srcset & sizes Attributes" +id: html-srcset-and-sizes +title: "HTML srcset and sizes" +sidebar_label: "Srcset and Sizes" sidebar_position: 7 slug: /html/images/srcset-and-sizes -description: "Learn how to use srcset with pixel density descriptors and width descriptors alongside sizes attributes to deliver optimal images per screen size." +description: "Learn how srcset and sizes work in HTML. Understand width descriptors and pixel density descriptors, how to write the sizes attribute with media conditions and calc, how browsers choose a file, how to plan image widths, test results, and avoid common mistakes on CodeHarborHub." keywords: - - HTML srcset attribute - - image sizes attribute - - width descriptors w - - resolution switching + - HTML srcset + - HTML sizes attribute + - srcset width descriptor + - srcset pixel density x descriptor + - responsive images srcset sizes + - how browser chooses srcset image + - sizes attribute calc vw + - resolution switching images + - img currentSrc + - retina images srcset + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, srcset, responsive-images, performance] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, srcset, sizes, responsive, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +Think of ordering a coffee. You do not say, "Give me exactly 237 milliliters." You look at the menu, which lists small, medium, and large, and the barista hands you the one that suits you. + +`srcset` and `sizes` work the same way. You do not tell the browser which image file to download. You hand it a **menu** of the files you have made, and a note about **how large the picture will appear**. The browser knows things you cannot: the visitor's screen size, how sharp their screen is, and sometimes how fast their connection is. It picks the best file for that visitor. In this lesson, you will learn to write the menu and the note. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- What `srcset` is, and the two ways to describe your files +- How the **`w` descriptor** and the **`sizes`** attribute work together +- How the **`x` descriptor** works for fixed-size images +- How to write `sizes` for real page layouts +- How the browser chooses, and how to check its choice +- How to plan which widths to create +- Common mistakes, and how to avoid them + +## The Idea + +An `<img>` normally has one file in `src`. With `srcset`, it also has a list of alternatives. + +```html title="idea.html" +<img + src="images/harbor-800.jpg" + srcset="images/harbor-400.jpg 400w, images/harbor-800.jpg 800w, images/harbor-1600.jpg 1600w" + sizes="100vw" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1600" + height="1067" +/> +``` + +| Attribute | Its job | +| :-- | :-- | +| `srcset` | The **menu**: files you offer, each with its description | +| `sizes` | The **note**: how wide the image will be on screen | +| `src` | The **fallback**: used by browsers that do not understand `srcset`, and the default choice | +| `alt`, `width`, `height` | Still required, as always | + +There are two ways to write the menu. We will look at the simpler one first. + +## Way 1: Pixel Density (`x` Descriptors) + +Use `x` descriptors when the image is shown at a **fixed size**, such as a logo or an avatar that is always 100 CSS pixels wide. You say how many device pixels you have per CSS pixel. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="x-descriptor.html" +<img + src="images/avatar-100.jpg" + srcset=" + images/avatar-100.jpg 1x, + images/avatar-200.jpg 2x, + images/avatar-300.jpg 3x + " + alt="Profile photo of Amara" + width="100" + height="100" +/> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/x-descriptor.html"> +<> +<img + src={sample} + alt="Profile photo of Amara" + width="100" + height="67" +/> +<p>The picture is always 100 CSS pixels wide. Screens with higher density use a larger file, so it stays sharp.</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo uses one small drawing, since there are no image files here. In your project, each descriptor points to a different file. + +- `1x` is for normal screens: a 100-pixel-wide file. +- `2x` is for sharp screens, where each CSS pixel is two device pixels: a 200-pixel-wide file. +- `3x` is for very sharp screens: a 300-pixel-wide file. + +The display size stays at **100 CSS pixels** (set by `width="100"`). Only the file changes. Notice that **you do not need `sizes`** for `x` descriptors, because the image size does not change. + +:::info Use `x` for fixed sizes, `w` for fluid ones +If the image is always the same size, `x` descriptors are the simplest solution. If the image grows and shrinks with the layout, use `w` descriptors with `sizes`. +::: + +## Way 2: Width Descriptors (`w`) and `sizes` + +Most content images are **fluid**: wider on a big screen, narrower on a phone. The browser needs two facts to choose well. + +1. **How wide is each file?** You provide this with a `w` descriptor. `800w` means "this file is 800 pixels wide." +2. **How wide will the image appear on the page?** You provide this with `sizes`. + +With those facts, the browser does the arithmetic. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="w-descriptor.html" +<img + src="images/harbor-800.jpg" + srcset=" + images/harbor-400.jpg 400w, + images/harbor-800.jpg 800w, + images/harbor-1200.jpg 1200w, + images/harbor-1600.jpg 1600w + " + sizes="(min-width: 60rem) 50vw, 100vw" + alt="Fishing boats resting in a calm harbor at sunrise" + width="1600" + height="1067" +/> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/w-descriptor.html"> +<> +<img + src={sample} + alt="Fishing boats resting in a calm harbor at sunrise" + width="240" + height="160" + style={{maxWidth: '100%', height: 'auto'}} +/> +<p>In your project, the browser would download one of four files here, depending on the screen.</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +### The `w` Descriptor + +Each entry in `srcset` is a file address, a space, and a number followed by `w`. + +- The number is the file's **real width in pixels**. It is not a CSS size. +- Separate entries with commas. +- Every entry in one `srcset` must use the **same kind** of descriptor, either all `w` or all `x`. Do not mix them. + +### The `sizes` Attribute + +`sizes` is a list of **conditions and widths**, separated by commas. The browser reads it from left to right and uses the **first condition that matches**. The last entry has no condition and is the default. + +```text +sizes="(min-width: 60rem) 50vw, 100vw" + └──── condition ───┘ └width┘ └default┘ +``` + +In words: "If the window is at least 60rem wide, the image takes up half the window. Otherwise, it takes up the full window." + +#### What Can Go in `sizes` + +| Unit | Meaning | Example | +| :-- | :-- | :-- | +| `vw` | Percent of the **window** width | `50vw` is half the window | +| `px` | Fixed CSS pixels | `300px` | +| `rem`, `em` | Based on font size | `20rem` | +| `calc()` | A mix of units | `calc(100vw - 2rem)` | + +:::warning No percentages in `sizes` +`sizes="50%"` is not valid. A percentage needs a parent to measure from, and the browser must pick the file before the layout exists. Use `vw` instead. +::: + +#### Media Conditions + +The conditions use the same syntax as CSS media queries. + +| Condition | Matches when | +| :-- | :-- | +| `(min-width: 60rem)` | The window is at least 60rem wide | +| `(max-width: 40rem)` | The window is at most 40rem wide | +| `(min-width: 40rem) and (max-width: 60rem)` | Between the two widths | +| `(orientation: landscape)` | The window is wider than tall | + +## How the Browser Chooses + +The browser follows a simple recipe. + +1. **Read `sizes`** and find the first condition that matches. That gives the **display width** in CSS pixels. +2. **Multiply by the device pixel ratio.** This gives the number of pixels the picture needs to look sharp. +3. **Look at the `srcset` menu** and pick a file that is at least that wide, usually the smallest one that is big enough. + +### A Worked Example + +Using the `sizes` and `srcset` above: + +| Visitor | Window | Matching condition | Display width | DPR | Pixels needed | File picked | +| :-- | :-- | :-- | :-- | :-- | :-- | :-- | +| Budget phone | 360 px | none, so `100vw` | 360 px | 2 | 720 | `harbor-800.jpg` | +| Large phone | 430 px | none, so `100vw` | 430 px | 3 | 1290 | `harbor-1600.jpg` | +| Laptop | 1280 px | `50vw` | 640 px | 1 | 640 | `harbor-800.jpg` | +| Sharp laptop | 1280 px | `50vw` | 640 px | 2 | 1280 | `harbor-1600.jpg` | +| Large monitor | 1920 px | `50vw` | 960 px | 1 | 960 | `harbor-1200.jpg` | + +:::info The browser has the final say +The recipe is a guide, not a promise. A browser may pick a larger file if it is already cached, or a smaller one on a slow connection or when a data-saving mode is on. That is a feature: the browser can use information you do not have. +::: + +## Writing `sizes` for Real Layouts + +The hardest part of `sizes` is describing your own layout correctly. Look at your CSS, and describe how wide the image really is. + +### Case 1: Full-Width Image + +The image always spans the window. + +```html +sizes="100vw" +``` + +### Case 2: Image With Page Margins + +The page has 1rem of padding on each side. + +```html +sizes="calc(100vw - 2rem)" +``` + +### Case 3: Two Columns on Wide Screens + +Half the window on wide screens, full width otherwise, with a small gap. + +```html +sizes="(min-width: 60rem) calc(50vw - 1.5rem), 100vw" +``` + +### Case 4: A Content Column With a Maximum Width + +The article column never grows beyond 40rem (about 640 pixels). + +```html +sizes="(min-width: 42rem) 40rem, 100vw" +``` + +### Case 5: A Card Grid + +Four columns on large screens, two on medium, one on small. + +```html +sizes="(min-width: 70rem) 25vw, (min-width: 40rem) 50vw, 100vw" +``` + +Conditions go from the **largest** screens to the smallest, because the first match wins. If you put `100vw` with no condition first, the browser would always use it. + +### Matching `sizes` With Your CSS + +The values in `sizes` should agree with the real layout. If your CSS says an image is 50% of a 1200-pixel container, but `sizes` says `100vw`, the browser will download a file twice as large as necessary. + +```css +/* The layout */ +.article img { width: 100%; max-width: 40rem; } +``` + +```html +<!-- The matching description --> +<img ... sizes="(min-width: 42rem) 40rem, 100vw" /> +``` + +## Which Widths Should You Create? + +You do not need dozens of files. A handful of widths covers most devices. + +| Width | Good for | +| :-- | :-- | +| 400 | Small phones at normal density | +| 800 | Large phones, small tablets, small slots on laptops | +| 1200 | Tablets, laptops, and sharp phones | +| 1600 | Sharp laptops, large layouts | +| 2400 | Very large or very sharp screens (only if needed) | + +Some tips: + +- **Aim for steps of about 1.5 to 2 times.** Files that are too close to each other add work with little benefit. +- **Do not create sizes bigger than the original.** Enlarging only makes blurry, heavy files. +- **Generate them automatically.** Build tools, image services, and content systems can produce all the sizes for you. +- **Keep the same aspect ratio** across the set, and put the largest file's dimensions in `width` and `height`. + +```bash title="terminal" +# One way to make the set with ImageMagick +for w in 400 800 1200 1600; do + magick harbor-original.jpg -resize ${w}x -quality 80 harbor-$w.jpg +done +``` + +## Checking the Result + +1. **Open developer tools,** go to the Network tab, filter by Img, and reload. +2. **Use the device toolbar** to switch between phone and desktop sizes, and reload each time. +3. **Read the real choice in JavaScript.** + +```js title="check.js" +const img = document.querySelector("img"); +console.log("Chosen file:", img.currentSrc); +console.log("File is", img.naturalWidth, "px wide"); +console.log("Shown at", img.clientWidth, "CSS px, density", window.devicePixelRatio); +``` + +If `naturalWidth` is much larger than `clientWidth × devicePixelRatio`, your `sizes` may be too generous. If it is smaller, the image may look soft. + +## `srcset` With Other Features + +### With `width` and `height` + +Always set `width` and `height` to the **largest** file's dimensions (or any pair with the same ratio). The browser uses them to reserve space, as you learned in [Width and Height](./width-and-height). + +### With Lazy Loading + +`loading="lazy"` works with `srcset`. For lazy images far down the page, the browser can only choose a file once it knows the layout size, and it does so when the image is about to appear. You will see more in [Lazy Loading](./lazy-loading). Some newer browsers also allow `sizes="auto"` on lazy images so they measure the real layout width. Support is still growing, so check current browser tables before relying on it. + +### With `<picture>` + +When you need different crops or formats, put `srcset` and `sizes` inside the `<source>` elements of a `<picture>`, as you will learn in [Picture Element](./picture-element). + +## Common Mistakes + +### Mistake 1: `w` descriptors without `sizes` + +The browser then assumes `100vw`, the full window width. For an image that is only half as wide, it will pick a file that is too large. + +### Mistake 2: Wrong `w` numbers + +The number must be the file's **real** pixel width. A wrong number misleads the browser into a bad choice. + +### Mistake 3: Mixing `w` and `x` in one `srcset` + +It is invalid. Use one kind per image. + +### Mistake 4: Percentages in `sizes` + +Use `vw`, `px`, `rem`, or `calc()`. + +### Mistake 5: Conditions in the wrong order + +The first matching condition wins. List the largest screens first, and put the unconditional default last. + +### Mistake 6: A `sizes` value that does not match the layout + +If the CSS and `sizes` disagree, the choice will not be efficient. + +### Mistake 7: Using `srcset` for art direction + +`srcset` lets the browser choose a **size**, not a different picture. If you need a different crop, use `<picture>`. + +### Mistake 8: Forgetting the `src` fallback + +Always provide `src`, usually a mid-sized file, for browsers and tools that do not use `srcset`. + +### Mistake 9: Expecting the browser to choose the exact file you imagine + +The browser may pick differently because of cache, connection, or data-saving settings. That is expected. + +## Try It Yourself + +Here is a short project. + +1. Choose a photo and create four widths: 400, 800, 1200, and 1600 pixels. +2. Build an `<img>` with `src`, `srcset` using `w` descriptors, `sizes="100vw"`, `alt`, `width`, and `height`. +3. Open the Network tab, reload at different device sizes, and write down which file loads each time. +4. Change the layout so the image takes half the window on wide screens. Update `sizes` to match and test again. Did the chosen file get smaller? +5. Build a small avatar using `x` descriptors with `1x`, `2x`, and `3x` files. +6. Use the JavaScript snippet to compare `naturalWidth` with `clientWidth × devicePixelRatio`. +7. Deliberately remove `sizes`. What does the browser choose now? +8. Bonus: create a three-column card grid and write a `sizes` value for it. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What does `srcset` contain?</summary> + +A comma-separated list of image files, each followed by a descriptor (`w` for the file's width or `x` for pixel density). + +</details> + +<details> +<summary>2. What does the `sizes` attribute tell the browser?</summary> + +How wide the image will be on the page, with optional media conditions, so the browser can choose a suitable file. + +</details> + +<details> +<summary>3. When should you use `x` descriptors instead of `w`?</summary> + +When the image is displayed at a fixed size, such as a logo or avatar. Then you only need to provide larger files for denser screens. + +</details> + +<details> +<summary>4. Why must the `w` number match the file's real width?</summary> + +The browser uses it to calculate which file is big enough. A wrong number leads to a wrong choice. + +</details> + +<details> +<summary>5. In `sizes`, what happens when several conditions match?</summary> + +The first matching condition wins, so list the largest screens first and put the unconditional default last. + +</details> + +## Key Takeaways + +- `srcset` is a menu of files, and `sizes` describes how big the image will be. The browser chooses. +- Use `x` descriptors for fixed-size images and `w` descriptors with `sizes` for fluid ones. +- Write `sizes` from your real CSS layout: use `vw`, `px`, `rem`, or `calc()`, never percentages. +- Create a handful of widths, such as 400, 800, 1200, and 1600, and always keep a `src` fallback. +- Check the browser's choice with the Network tab or `currentSrc`. + +Now you can offer the right size to every screen. Next, learn how to offer different crops and formats with the [Picture Element](./picture-element). \ No newline at end of file diff --git a/tutorials/html/05-images/width-and-height.mdx b/tutorials/html/05-images/width-and-height.mdx index e5f9c626b..fd01cd2e6 100644 --- a/tutorials/html/05-images/width-and-height.mdx +++ b/tutorials/html/05-images/width-and-height.mdx @@ -1,16 +1,402 @@ --- -id: width-and-height -title: "Setting Image Dimensions: width and height Attributes" -sidebar_label: "Width & Height" +id: html-width-and-height +title: "HTML Image Width and Height" +sidebar_label: "Width and Height" sidebar_position: 4 slug: /html/images/width-and-height -description: "Learn how setting aspect ratio, explicit width, and height attributes prevents Cumulative Layout Shift (CLS) and speeds up browser rendering." +description: "Learn how the width and height attributes stop layout shift in HTML. Understand aspect ratio, how browsers reserve space, responsive sizing with CSS, the aspect-ratio property, high-density screens, and Cumulative Layout Shift on CodeHarborHub." keywords: - - image width and height - - prevent layout shifts - - image aspect ratio HTML - - core web vitals images + - HTML image width and height + - cumulative layout shift images + - CLS fix images + - HTML aspect ratio images + - CSS aspect-ratio + - responsive images max-width height auto + - image dimensions HTML + - retina images 2x + - prevent layout jump + - Core Web Vitals images + - learn HTML images - CodeHarborHub HTML -authors: [ajay-dhangar] -tags: [html, performance, layout, web-vitals] ---- \ No newline at end of file +tags: [html, web-development, beginner, images, width, height, performance, frontend] +--- + +export const sample = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 160'><rect width='240' height='160' fill='%23dbeafe'/><circle cx='170' cy='50' r='24' fill='%23fbbf24'/><path d='M0 120 Q40 100 80 120 T160 120 T240 120 V160 H0 Z' fill='%232563eb'/><path d='M70 110 V62 L112 110 Z' fill='%23ffffff'/><rect x='62' y='110' width='58' height='8' rx='3' fill='%23334155'/></svg>"; + +You start reading an article on your phone. A paragraph catches your eye, and you move your thumb to scroll. Then, with no warning, the text **jumps down** the screen. A picture above it has just finished loading and pushed everything aside. You lose your place. Worse, you tap a button just as it moves, and you tap the wrong thing. + +Almost everyone has felt this, and it is annoying enough that search engines measure it. The cure is two small attributes you may already have noticed: `width` and `height`. In this lesson, you will learn why they work, how to set them correctly, and how to combine them with CSS so your images stay steady **and** flexible. + +<AdsComponent /> +<br /> + +## What You Will Learn + +- What causes the "jumping page," and what it is called +- How `width` and `height` let the browser reserve space +- How to find and write the right values +- How to make images responsive while keeping the benefit +- How to use the CSS `aspect-ratio` property for boxes and placeholders +- How high-density screens fit in +- How to measure the problem and confirm the fix +- Common mistakes, and how to avoid them + +## The Problem: Layout Shift + +When a browser reads your HTML, it often finds an image **before it has downloaded the file**. It does not know how big the picture is yet, so it gives the image no space. The text after it sits right up against the previous content. Then the file arrives, and the browser makes room by pushing everything down. + +That sudden movement is called a **layout shift**. Search engines add up all the shifts on a page into a score called **Cumulative Layout Shift (CLS)**. A lower score means a steadier page. + +| CLS score | What it means | +| :-- | :-- | +| 0.1 or less | Good. The page is stable | +| 0.1 to 0.25 | Needs improvement | +| More than 0.25 | Poor. Visitors will notice jumps | + +Images without dimensions are one of the most common causes, and one of the easiest to fix. + +## The Fix: `width` and `height` + +Tell the browser the image's size **in the HTML**, so it can save the right amount of space before the file arrives. + +<Tabs> +<TabItem value="code" label="HTML Code" default> + +```html title="index.html" +<img + src="images/harbor.jpg" + alt="A small sailboat on blue waves under a bright sun" + width="240" + height="160" +/> +<p>This paragraph stays put, because the space above it is already reserved.</p> +``` + +</TabItem> +<TabItem value="output" label="Browser Output"> + +<BrowserWindow url="http://127.0.0.1:5500/index.html"> +<> +<img + src={sample} + alt="A small sailboat on blue waves under a bright sun" + width="240" + height="160" +/> +<p>This paragraph stays put, because the space above it is already reserved.</p> +</> +</BrowserWindow> + +</TabItem> +</Tabs> + +The demo uses a small drawing built into the page. In your project, `src` points to a real file. + +### The Rules + +- Write the values as **plain numbers**. They mean **pixels**, but you do not write `px`. +- `width="240"` is correct. `width="240px"` and `width="50%"` are not valid in HTML. For percentages, use CSS. +- Use the image's **real dimensions** (or the same proportions), not made-up numbers. + +```html +<!-- Correct --> +<img src="photo.jpg" alt="..." width="600" height="400" /> + +<!-- Not valid in HTML --> +<img src="photo.jpg" alt="..." width="600px" height="400px" /> +<img src="photo.jpg" alt="..." width="100%" height="auto" /> +``` + +## How It Works Today + +Modern browsers do something clever with these two numbers. They calculate the **aspect ratio** (the proportion of width to height) and reserve space with exactly that shape, **even when CSS later changes the displayed size**. + +For example, `width="600" height="400"` is a ratio of 3 to 2. If CSS makes the image 300 pixels wide on a phone, the browser still knows the height should be 200, and it reserves that space before the image loads. + +That is why the best practice is: + +1. Put the image's **real pixel width and height** in the HTML. +2. Use **CSS** to control the displayed size. + +## Combining With CSS: Steady and Flexible + +The next rule gives you images that never overflow, never stretch, and never cause a jump. + +```css title="images.css" +img { + max-width: 100%; + height: auto; +} +``` + +Here is what each part does. + +| Part | What it does | +| :-- | :-- | +| `width="600"` and `height="400"` in HTML | Tell the browser the proportions so it can reserve space | +| `max-width: 100%` in CSS | Prevents the image from being wider than its container | +| `height: auto` in CSS | Keeps the proportions when the width changes | + +<Tabs> +<TabItem value="bad" label="Distorted" default> + +```css +/* The HTML says height="400", and CSS keeps it fixed. + When the width shrinks, the image is stretched tall. */ +img { + max-width: 100%; +} +``` + +</TabItem> +<TabItem value="good" label="Correct"> + +```css +img { + max-width: 100%; + height: auto; /* height follows the width and the ratio */ +} +``` + +</TabItem> +</Tabs> + +<BrowserWindow url="http://127.0.0.1:5500/responsive.html"> +<> +<div style={{maxWidth: '180px', border: '1px dashed #94a3b8', padding: '4px'}}> + <img + src={sample} + alt="A small sailboat on blue waves under a bright sun" + width="240" + height="160" + style={{maxWidth: '100%', height: 'auto'}} + /> +</div> +<p>The picture shrinks to fit its 180-pixel box and keeps its proportions.</p> +</> +</BrowserWindow> + +:::warning Never forget `height: auto` +If you set a CSS `width` on an image but leave out `height: auto`, the HTML `height` attribute still applies. The picture can come out stretched or squashed. +::: + +## How to Find the Right Numbers + +You need the image's **natural size** in pixels. + +| Where | How | +| :-- | :-- | +| **Your computer** | Right-click the file and open its properties or info | +| **An image editor** | Check the image size or canvas size | +| **Command line** | Use a tool such as `file photo.jpg` on many systems | +| **Browser** | Open the image in its own tab. Developer tools show its natural size | +| **Your build tool or CMS** | Many generate the dimensions automatically | + +If you resize a photo before publishing, as you should, use the **resized** dimensions in your HTML. + +### Calculating a Missing Value + +If you know the ratio and one number, you can find the other. + +```text +height = width × (original height ÷ original width) + +Original: 1200 × 800 (ratio 3:2) +You want a width of 600 → height = 600 × (800 ÷ 1200) = 400 +``` + +### Common Aspect Ratios + +| Ratio | Looks like | Common uses | +| :-- | :-- | :-- | +| 1 : 1 | Square | Avatars, product tiles | +| 4 : 3 | Slightly wide | Older photos, presentations | +| 3 : 2 | Wide | Camera photos | +| 16 : 9 | Widescreen | Video, banners | +| 9 : 16 | Tall | Phone stories | + +## The CSS `aspect-ratio` Property + +Sometimes you need to reserve space for something that is **not** an `<img>`, such as a video box, a map, or a card whose image has not loaded yet. For those, CSS has the `aspect-ratio` property. + +```css title="aspect-ratio.css" +.video-box { + width: 100%; + aspect-ratio: 16 / 9; + background: #e2e8f0; /* a calm placeholder color */ +} + +.avatar { + width: 64px; + aspect-ratio: 1; /* same as 1 / 1: a square */ + border-radius: 50%; + object-fit: cover; +} +``` + +<BrowserWindow url="http://127.0.0.1:5500/aspect.html"> +<> +<div style={{color: '#333', width: '100%', maxWidth: '320px', aspectRatio: '16 / 9', background: '#e2e8f0', display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: '6px'}}> + Reserved 16:9 space +</div> +</> +</BrowserWindow> + +The box holds its 16 to 9 shape even when it is empty, so nothing jumps when the content arrives. A soft background color also gives visitors something calm to look at instead of a blank hole. + +## Images That Fill a Box + +When a design needs an image to fill a fixed shape, combine the box's ratio with `object-fit`, as you learned in [The img Element](./img-element). + +```css title="card.css" +.card-image { + width: 100%; + aspect-ratio: 4 / 3; + object-fit: cover; +} +``` + +Every card then has the same shape, whatever the original photos look like. + +## Dimensions and Sharpness + +The `width` and `height` in your HTML describe the image's **real pixel size**. They do not make the picture sharper or blurrier by themselves. But the relationship between the **file size in pixels** and the **size on screen** matters. + +| Situation | Result | +| :-- | :-- | +| File is **smaller** than the display size | The browser stretches it, and it looks blurry | +| File is **the same** as the display size | Sharp on normal screens | +| File is **twice** the display size | Sharp on high-density ("retina") screens, but costs more data | +| File is **much larger** than needed | Sharp, but slow and wasteful | + +High-density screens pack two or three device pixels into each CSS pixel. To look crisp on them, an image shown at 300 CSS pixels wide needs a file about 600 pixels wide. You do not want to send that big file to everyone, which is why you will learn `srcset` in [Srcset and Sizes](./srcset-and-sizes). It lets each device download the size it needs. + +:::tip A simple starting rule +For a single image file, make it about **twice** the largest size it will be shown at, then compress it well. When you learn `srcset`, you can offer several sizes instead. +::: + +## Special Cases + +### SVG Images + +SVG graphics scale without losing quality, so they have no "natural" pixel size. Still, set `width` and `height` to reserve space and avoid shifts. + +```html +<img src="images/logo.svg" alt="CodeHarborHub home" width="140" height="40" /> +``` + +### Images That Change Shape + +If you show **different crops** on different screens with `<picture>`, set `width` and `height` on the `<img>` and, where the shapes differ, on each `<source>` too. You will see this in [Picture Element](./picture-element). + +### Images Loaded Later + +For lazy-loaded images, `width` and `height` are even more important. The image arrives long after the page is built, and without reserved space, the jump is certain. Read more in [Lazy Loading](./lazy-loading). + +## Checking the Result + +You can measure whether your fix worked. + +1. **Open your browser's developer tools.** Many have a Performance panel that highlights layout shifts. +2. **Run Lighthouse** (built into Chrome-based browsers) or the free **PageSpeed Insights** service. Look at the CLS score and the list of "images without explicit dimensions." +3. **Throttle the network.** Set the connection to "Slow 3G" and reload. Watch whether the content moves as images appear. +4. **Test on a real phone.** Scroll while the page is still loading. + +## Common Mistakes + +### Mistake 1: Leaving out `width` and `height` + +The most common cause of jumping images. Add both to every `<img>`. + +### Mistake 2: Writing units or percentages + +`width="300px"` and `width="50%"` are invalid. Write `width="300"`, and use CSS for percentages. + +### Mistake 3: Using made-up proportions + +Numbers that do not match the real image shape reserve the wrong amount of space, so the page still jumps a little, and your picture may look squashed. + +### Mistake 4: Forgetting `height: auto` + +With a CSS `width` or `max-width` and no `height: auto`, the image is distorted. + +### Mistake 5: Stretching a small image to look big + +Enlarging a small file makes it blurry. Start with a file large enough. + +### Mistake 6: Sending enormous files and shrinking them with HTML + +`width="300"` on a 5000-pixel photo downloads all 5000 pixels. Resize the file itself. + +### Mistake 7: Forgetting space for non-image content + +Ads, videos, and embeds need reserved space too. Use `aspect-ratio` or fixed-size boxes. + +### Mistake 8: Squashing a logo with `width` and `height` that do not match + +Keep a logo's proportions, or it will look wrong. + +## Try It Yourself + +Here is a short project. + +1. Create `steady.html` with three pictures of different shapes: square, wide, and tall. +2. Find the real width and height of each one and write them in the HTML. +3. Add `img { max-width: 100%; height: auto; }` and resize your browser window. Do the images keep their shapes? +4. Remove `height: auto` and test again. What changes? +5. In developer tools, set the network to "Slow 3G" and reload. Remove the `width` and `height` from one image and compare how the page moves. +6. Create a `.video-box` with `aspect-ratio: 16 / 9` and a soft background color. +7. Make a row of four cards with `aspect-ratio: 4 / 3` and `object-fit: cover`. +8. Run Lighthouse and note your CLS score. + +<AdsComponent /> +<br /> + +## Quick Recap + +Click a question to check your answer. + +<details> +<summary>1. What does Cumulative Layout Shift measure?</summary> + +How much page content moves around unexpectedly while the page loads. Lower scores mean a steadier page. + +</details> + +<details> +<summary>2. How do `width` and `height` in HTML prevent layout jumps?</summary> + +They let the browser work out the image's aspect ratio, so it can reserve the right amount of space before the file arrives. + +</details> + +<details> +<summary>3. Should you write `width="300px"`?</summary> + +No. The attributes take plain numbers that mean pixels. Use CSS for units and percentages. + +</details> + +<details> +<summary>4. What two CSS lines make images responsive without distortion?</summary> + +`max-width: 100%;` and `height: auto;`. + +</details> + +<details> +<summary>5. When would you use the CSS `aspect-ratio` property?</summary> + +To reserve a box of a certain shape for content that is not an `<img>`, such as a video, a map, or an image placeholder. + +</details> + +## Key Takeaways + +- Missing image sizes cause layout shift, which annoys visitors and lowers your page-quality scores. +- Write `width` and `height` in HTML as plain numbers, using the image's real proportions. +- Add `max-width: 100%` and `height: auto` in CSS so images are flexible without distortion. +- Use `aspect-ratio` to reserve space for boxes, videos, and placeholders. +- Resize files to the right size, and measure your result with developer tools or Lighthouse. + +Your images now hold their place. Next, learn which file types to choose in [Image Formats](./image-formats). \ No newline at end of file From 31ba8f9ff884f5c5369fd62d09503eb477cf9e8e Mon Sep 17 00:00:00 2001 From: Ajay Dhangar <ajaydhangar49@gmail.com> Date: Sun, 4 Oct 2026 22:10:03 +0530 Subject: [PATCH 2/2] Fixed issue --- tutorials/html/05-images/figure-and-figcaption.mdx | 4 ++-- tutorials/html/05-images/src-and-alt.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tutorials/html/05-images/figure-and-figcaption.mdx b/tutorials/html/05-images/figure-and-figcaption.mdx index e51de1b60..d28d6ccf5 100644 --- a/tutorials/html/05-images/figure-and-figcaption.mdx +++ b/tutorials/html/05-images/figure-and-figcaption.mdx @@ -177,7 +177,7 @@ If the caption fully conveys the picture's meaning, a short `alt` is fine, or ev </figure> ``` -You saw this pattern in [Quotations](/html/text-content/quotations). +You saw this pattern in [Quotations](/tutorials/html/text-content/quotations). </TabItem> <TabItem value="table" label="Data"> @@ -254,7 +254,7 @@ figcaption::before { </figure> ``` -The caption now begins with "Figure 1." automatically. The `id` on the figure lets other parts of the page link to it, as you learned in [Internal Links](/html/links-and-navigation/internal-links). +The caption now begins with "Figure 1." automatically. The `id` on the figure lets other parts of the page link to it, as you learned in [Internal Links](/tutorials/html/links-and-navigation/internal-links). :::info Text added by CSS Words added with `content` in CSS may not be announced by every screen reader, and they cannot be selected or translated like normal text. If the numbers matter, write "Figure 1." directly in the HTML. Use CSS counters for convenience, not for essential information. diff --git a/tutorials/html/05-images/src-and-alt.mdx b/tutorials/html/05-images/src-and-alt.mdx index 0ef1ec0cb..6c8766a60 100644 --- a/tutorials/html/05-images/src-and-alt.mdx +++ b/tutorials/html/05-images/src-and-alt.mdx @@ -42,7 +42,7 @@ One is about the machine, the other is about people. Both are easy to get wrong, ## Part 1: The `src` Attribute -`src` stands for **source**. Its value is the address of the image file. It follows the same rules as any other URL, so everything you learned in [Relative URLs](/html/links-and-navigation/relative-urls) and [Absolute URLs](/html/links-and-navigation/absolute-urls) applies here. +`src` stands for **source**. Its value is the address of the image file. It follows the same rules as any other URL, so everything you learned in [Relative URLs](/tutorials/html/links-and-navigation/relative-urls) and [Absolute URLs](/tutorials/html/links-and-navigation/absolute-urls) applies here. <Tabs> <TabItem value="code" label="HTML Code" default>