ワンクリックで
responsive-images
Modern responsive image techniques using picture element, srcset, sizes, and modern formats. Use when adding images that need to adapt to different screen sizes, resolutions, or support modern image formats.
メニュー
Modern responsive image techniques using picture element, srcset, sizes, and modern formats. Use when adding images that need to adapt to different screen sizes, resolutions, or support modern image formats.
Generate standardized static site structures. Use when creating new websites, setting up demos, or need consistent site structure with SEO, PWA, and accessibility foundations.
Write Node.js CLI tools with zero dependencies. Use when creating command-line tools, argument parsing, colored output, or interactive prompts.
Modern CSS organization with native @import, @layer cascade control, CSS nesting, design tokens, and element-focused selectors. AUTO-INVOKED when editing .css files.
Define and use custom HTML elements. Use when creating new components, defining custom tags, or using project-specific elements beyond standard HTML5.
Umbrella coordinator for image handling. Coordinates responsive-images, placeholder-images, and automation scripts. Use when adding images to any page, optimizing existing images, or setting up image pipelines.
Generate SVG placeholder images for prototypes. Use when adding placeholder images for layouts, mockups, or development. Supports simple, labeled, and brand-aware types.
| name | responsive-images |
| description | Modern responsive image techniques using picture element, srcset, sizes, and modern formats. Use when adding images that need to adapt to different screen sizes, resolutions, or support modern image formats. |
| allowed-tools | Read, Write, Edit |
This skill covers modern responsive image techniques: resolution switching with srcset and sizes, art direction with <picture>, and modern format support with graceful fallbacks.
Images should:
Every image should have appropriate loading attributes:
<img src="photo.jpg"
alt="Descriptive text"
loading="lazy"
decoding="async"
fetchpriority="auto"/>
| Attribute | Values | Purpose |
|---|---|---|
loading | eager, lazy | When to load the image |
decoding | sync, async, auto | How to decode the image |
fetchpriority | high, low, auto | Network priority hint |
| Image Type | loading | fetchpriority | decoding |
|---|---|---|---|
| Hero/LCP image | eager | high | async |
| Above fold | eager | auto | async |
| Below fold | lazy | auto | async |
| Thumbnails | lazy | low | async |
| Background decorative | lazy | low | async |
srcset and sizesA single image file can't serve all contexts:
srcset and sizes<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w,
photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
alt="Product photograph"
loading="lazy"
decoding="async"/>
srcset lists available image files with their widths (w descriptor)sizes tells the browser how wide the image will displaysrc provides fallback for browsers without srcset supportsizes Attributesizes uses media conditions to describe rendered width:
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px"
This means:
sizes Patterns| Context | sizes Value |
|---|---|
| Full-width hero | 100vw |
| Content image (max 800px) | (max-width: 800px) 100vw, 800px |
| Two-column grid | (max-width: 600px) 100vw, 50vw |
| Three-column grid | (max-width: 600px) 100vw, (max-width: 900px) 50vw, 33vw |
| Card thumbnail | (max-width: 600px) 100vw, 300px |
| Gallery thumbnail | (max-width: 600px) 50vw, 220px |
<picture><picture>Use <picture> when you need different images for different contexts:
<picture>
<source media="(max-width: 600px)"
srcset="photo-mobile.jpg"/>
<source media="(max-width: 1200px)"
srcset="photo-tablet.jpg"/>
<img src="photo-desktop.jpg"
alt="Product photograph"
loading="lazy"
decoding="async"/>
</picture>
srcsetCombine art direction with resolution switching:
<picture>
<!-- Mobile: portrait crop -->
<source media="(max-width: 600px)"
srcset="photo-mobile-400.jpg 400w,
photo-mobile-600.jpg 600w"
sizes="100vw"/>
<!-- Tablet: square crop -->
<source media="(max-width: 1200px)"
srcset="photo-tablet-600.jpg 600w,
photo-tablet-900.jpg 900w"
sizes="50vw"/>
<!-- Desktop: landscape crop -->
<img src="photo-desktop-800.jpg"
srcset="photo-desktop-800.jpg 800w,
photo-desktop-1200.jpg 1200w,
photo-desktop-1600.jpg 1600w"
sizes="800px"
alt="Product photograph"
loading="lazy"
decoding="async"/>
</picture>
| Format | Compression | Browser Support | Use Case |
|---|---|---|---|
| AVIF | Best (50% smaller than JPEG) | Chrome, Firefox, Safari 16+ | Primary modern format |
| WebP | Very good (25-35% smaller) | All modern browsers | Fallback for AVIF |
| JPEG | Good | Universal | Final fallback |
| PNG | Lossless | Universal | Transparency, screenshots |
<picture>
<source srcset="photo.avif" type="image/avif"/>
<source srcset="photo.webp" type="image/webp"/>
<img src="photo.jpg"
alt="Descriptive text"
loading="lazy"
decoding="async"/>
</picture>
<picture>
<!-- Mobile: AVIF -->
<source media="(max-width: 600px)"
type="image/avif"
srcset="photo-mobile-400.avif 400w,
photo-mobile-600.avif 600w"
sizes="100vw"/>
<!-- Mobile: WebP -->
<source media="(max-width: 600px)"
type="image/webp"
srcset="photo-mobile-400.webp 400w,
photo-mobile-600.webp 600w"
sizes="100vw"/>
<!-- Mobile: JPEG -->
<source media="(max-width: 600px)"
srcset="photo-mobile-400.jpg 400w,
photo-mobile-600.jpg 600w"
sizes="100vw"/>
<!-- Desktop: AVIF -->
<source type="image/avif"
srcset="photo-800.avif 800w,
photo-1200.avif 1200w"
sizes="(max-width: 1200px) 50vw, 800px"/>
<!-- Desktop: WebP -->
<source type="image/webp"
srcset="photo-800.webp 800w,
photo-1200.webp 1200w"
sizes="(max-width: 1200px) 50vw, 800px"/>
<!-- Desktop: JPEG fallback -->
<img src="photo-800.jpg"
srcset="photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 1200px) 50vw, 800px"
alt="Descriptive text"
loading="lazy"
decoding="async"/>
</picture>
<picture>
<source type="image/avif"
srcset="hero-800.avif 800w,
hero-1200.avif 1200w,
hero-1920.avif 1920w"
sizes="100vw"/>
<source type="image/webp"
srcset="hero-800.webp 800w,
hero-1200.webp 1200w,
hero-1920.webp 1920w"
sizes="100vw"/>
<img src="hero-1200.jpg"
srcset="hero-800.jpg 800w,
hero-1200.jpg 1200w,
hero-1920.jpg 1920w"
sizes="100vw"
alt="Hero image description"
loading="eager"
fetchpriority="high"
decoding="async"/>
</picture>
<picture>
<source type="image/avif"
srcset="content-400.avif 400w,
content-800.avif 800w,
content-1200.avif 1200w"
sizes="(max-width: 800px) 100vw, 800px"/>
<source type="image/webp"
srcset="content-400.webp 400w,
content-800.webp 800w,
content-1200.webp 1200w"
sizes="(max-width: 800px) 100vw, 800px"/>
<img src="content-800.jpg"
srcset="content-400.jpg 400w,
content-800.jpg 800w,
content-1200.jpg 1200w"
sizes="(max-width: 800px) 100vw, 800px"
alt="Content image description"
loading="lazy"
decoding="async"/>
</picture>
<picture>
<source type="image/avif"
srcset="thumb-300.avif 300w,
thumb-450.avif 450w"
sizes="(max-width: 600px) 100vw, 300px"/>
<source type="image/webp"
srcset="thumb-300.webp 300w,
thumb-450.webp 450w"
sizes="(max-width: 600px) 100vw, 300px"/>
<img src="thumb-300.jpg"
srcset="thumb-300.jpg 300w,
thumb-450.jpg 450w"
sizes="(max-width: 600px) 100vw, 300px"
alt="Card thumbnail description"
loading="lazy"
decoding="async"/>
</picture>
<picture>
<source type="image/avif"
srcset="gallery-220.avif 220w,
gallery-330.avif 330w,
gallery-440.avif 440w"
sizes="(max-width: 600px) 50vw, 220px"/>
<source type="image/webp"
srcset="gallery-220.webp 220w,
gallery-330.webp 330w,
gallery-440.webp 440w"
sizes="(max-width: 600px) 50vw, 220px"/>
<img src="gallery-220.jpg"
srcset="gallery-220.jpg 220w,
gallery-330.jpg 330w,
gallery-440.jpg 440w"
sizes="(max-width: 600px) 50vw, 220px"
alt="Gallery image description"
loading="lazy"
decoding="async"/>
</picture>
<picture> Is OverkillFor simpler cases, srcset alone may suffice:
<!-- Resolution switching only, no format variants -->
<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Description"
loading="lazy"
decoding="async"/>
At minimum, always include:
<img src="photo.jpg"
alt="Descriptive text"
loading="lazy"
decoding="async"
width="800"
height="600"/>
The width and height attributes prevent layout shift.
The HTML sizes attribute uses viewport media queries, not container queries. For images inside container-queried components, the sizes may not accurately describe rendered width.
Strategies:
sizes estimation - Provide srcset that covers the full range:<!-- Inside a container-queried card that could be 300-800px wide -->
<img srcset="photo-300.jpg 300w,
photo-450.jpg 450w,
photo-600.jpg 600w,
photo-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 800px"
alt="Product photo"/>
@layer components {
product-card {
container-type: inline-size;
}
product-card img {
width: 100%;
height: auto;
aspect-ratio: 4/3;
object-fit: cover;
}
@container (min-width: 500px) {
product-card img {
width: 40%;
}
}
}
The browser still selects from srcset based on rendered size after CSS is applied.
object-fit with container units for fluid sizing:product-card img {
width: min(100%, 20cqi);
aspect-ratio: 1;
object-fit: cover;
}
Note: Future CSS may support container-based image selection, but for now, provide a robust srcset range.
srcsetGenerate images at these widths to cover common scenarios:
| Width | Use Case |
|---|---|
| 400w | Mobile thumbnails |
| 600w | Mobile full-width |
| 800w | Tablet/small desktop |
| 1200w | Desktop content |
| 1600w | Large desktop/retina |
| 1920w | Full-width heroes |
sizesvw) for fluid imagesEvery image needs meaningful alt text:
<!-- Informative: describe the content -->
<img alt="Team members collaborating around a whiteboard"/>
<!-- Decorative: empty alt -->
<img alt="" role="presentation"/>
<!-- Functional: describe the action -->
<img alt="Search"/>
<!-- Bad: redundant with adjacent text -->
<figure>
<img alt="Photo of our office building"/>
<figcaption>Our office building in Seattle</figcaption>
</figure>
<!-- Good: complementary description -->
<figure>
<img alt="Modern glass-walled building with green roof"/>
<figcaption>Our office building in Seattle</figcaption>
</figure>
When adding images:
alt attribute (descriptive or empty for decorative)loading attribute (eager for LCP, lazy for others)decoding="async" for all imagesfetchpriority="high" for LCP/hero imageswidth and height to prevent layout shiftsrcset for resolution switching when image > 400pxsizes based on rendered width<picture> for format fallbacks (AVIF > WebP > JPEG)<picture> for art direction (different crops)