The picture Element for Art Direction: srcset, sizes, and Container Query Alternatives

Use the picture element when the image itself must change at different sizes; use CSS object-fit and container queries when a single image adapts to its container.

Art Direction Versus Container Queries

You have an image that must show a different crop at different sizes. You have heard that container queries can do it in CSS alone, so you wonder whether the picture element is dead. It is not. The picture element is the correct tool when the image itself needs to change. Different crop, different subject, different aspect ratio. It selects a separate source file at the network layer. Container queries, object-fit, and object-position handle how a single image fits its container, not which image the client downloads. That distinction is the whole decision. A portrait of a person becomes a landscape crop on a wide card. The picture element with media attributes is the art-direction pattern that actually ships. The CSS-only version is a compromise. Take it only when you control the source image tightly.

The picture element media attribute fallback works because the img element is the fallback

The picture element media attribute fallback is built into the HTML specification, not bolted on. The client parses the <picture> element, walks its <source> children in document order, and uses the first source whose media attribute matches the current viewport and whose type attribute is supported. If no source matches, or if the engine does not support <picture> at all, it falls back to the <img> element inside. That <img> is mandatory. It is the element that renders the image, carries the alt text, and provides the width and height properties that reserve layout space. Without it, nothing renders. The pattern is simple enough to write from memory.

<picture>
  <source media="(min-width: 800px)" srcset="large.jpg">
  <source media="(min-width: 480px)" srcset="medium.jpg">
  <img src="small.jpg" alt="A hiker on a ridge at sunset">
</picture>

That snippet is art direction. Each source serves a different file with a different crop, and the engine chooses based on viewport width. The media attribute on a <source> inside <picture> is not the same as a media query in CSS. The CSS media query changes styles. The picture source media attribute changes the resource itself. The client downloads only the matched source. A phone never fetches the 2000-pixel-wide hero file. That is the performance win that CSS object-fit cannot match, because object-fit operates on a single downloaded image.

Picture element srcset sizes production pattern for resolution switching

When the crop stays the same but the screen density varies, the picture element srcset sizes production pattern uses the srcset attribute with width descriptors and a sizes attribute. This tells the client how large the image will render. The client then picks the best file from the candidates based on its viewport width, its device pixel ratio, and its bandwidth estimate. This is resolution switching, not art direction. It does not need the picture element at all. You can put srcset and sizes directly on the img tag. The picture element adds value only when you also need different crops or different formats.

<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w, image-800.jpg 800w, image-1600.jpg 1600w"
  sizes="(min-width: 1200px) 800px, 100vw"
  alt="A coastal town at golden hour"
  width="800"
  height="600">

The width descriptor (the 400w, 800w, 1600w values) tells the client the intrinsic width of each candidate file. The sizes attribute tells the client the layout width of the image in CSS pixels at each viewport breakpoint. The client combines those two pieces of information. It computes the effective pixel density of each candidate and chooses the one closest to the device pixel ratio. In Chromium, it also accounts for network conditions. This production pattern prevents cumulative layout shift when you pair it with explicit width and height attributes. The engine can reserve the correct aspect ratio before the image loads. The aspect-ratio derived from width and height is not a guess. It is a spec-mandated calculation that the client uses to allocate space.

Container queries responsive images replacement: the CSS-only art direction pattern

How The Container Query Technique Works

The container queries responsive images replacement is a real technique, but it has a hard limit. You declare a container with container-type: inline-size. Inside that container you use a container query with object-fit and object-position to change how a single image fills its box. This changes the crop visually without changing the downloaded file. It works well when the source image is large enough to serve every crop with acceptable quality and the subject stays centred enough that object-position can keep it in frame.

.card {
  container-type: inline-size;
  container-name: card;
}

.card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

@container card (min-width: 600px) {
  .card img {
    object-position: 20% center;
  }
}

@container card (min-width: 900px) {
  .card img {
    object-fit: contain;
    object-position: center;
  }
}

This HTML is a complete, runnable sample:

<div class="card">
  <img src="wide-landscape.jpg" alt="A mountain lake with a cabin on the left" width="1600" height="900">
  <p>Card content</p>
</div>

Where The Technique Falls Short

The container query changes object-fit and object-position. The same wide-landscape.jpg file gets cropped differently at different container widths. The client downloads one file, and the CSS re-frames it. That is efficient in bandwidth but limited in quality. If the wide crop must become a tight portrait on a tall card, object-fit: cover will zoom in on a tiny slice of the wide image, and the result will be blurry. object-position can shift the crop within the bounds of the source image. It cannot invent new pixels. The container query pattern is the right call for a background texture, a decorative banner, or a subject that stays central across all breakpoints. It is the wrong call for a product photo that must be framed differently at each size.

When the case actually calls for the picture element

Put the two patterns side by side and the decision is clear. The container query version changes the presentation of one file. The picture element changes the file itself. For art direction, the picture element wins whenever the crop change is drastic, the subject must be re-framed, or the file size would be wasted on a crop that uses only a fraction of the pixels. A hero image that shows a full landscape on desktop, a centred portrait on tablet, and a tight face crop on mobile is a picture element job. Each source can be a different file with its own aspect ratio, its own compression, and its own pixel dimensions. The client downloads only the one that matches the viewport. The mobile file can be a proper portrait rather than a wide landscape that gets cropped down.

The container query version suits the opposite case. The image is a fixed asset that must adapt to a fluid container, and the crop shifts are subtle. A card component in a grid where the image is always a wide banner but the focal point moves slightly left or right is a container query job. The single file is large enough to handle the shifts. The CSS keeps the layout responsive without duplicating assets. The failure case is a designer specifying a portrait crop for a narrow column and a landscape crop for a wide column from the same source image. The source cannot be both. object-fit will letterbox or crop destructively. The picture element solves that by serving two files, each authored for its crop.

How cumulative layout shift prevention changes the choice

Cumulative layout shift prevention is the reason you must put explicit width and height attributes on the img element, regardless of which pattern you choose. The client reserves space for an img with width and height using the aspect-ratio that the two properties imply. Without them, the client reserves zero space, and the page jumps when the image loads. The picture element does not change that rule. The img child still needs the attributes. In the container query pattern, the img also needs width and height, because the client uses them to compute the intrinsic aspect ratio before CSS object-fit applies. Setting height: 100% inside a container query works only if the container has a defined height. Otherwise the image collapses to zero height and object-fit has nothing to fit.

<picture>
  <source media="(min-width: 800px)" srcset="hero-wide.jpg">
  <img src="hero-tall.jpg" alt="A bridge spanning a river" width="1200" height="800">
</picture>

In this sample, the width and height describe the fallback hero-tall.jpg, a 3:2 portrait. The client reserves space for a 3:2 box before any source is chosen. When the client picks hero-wide.jpg, a 16:9 landscape, the reserved space is still 3:2. The wide image will be cropped by object-fit or stretched unless you also change the aspect-ratio via CSS. The picture element does not automatically adjust the reserved space to match the chosen source. To prevent cumulative layout shift with art direction, set the aspect-ratio on the img to match the source that will render at that breakpoint. Use a media query or a container query on the img itself. That is a subtle interaction. The picture element changes the source, but the layout box is owned by the img. The img's intrinsic size comes from its attributes, not from the chosen source. The practical fix: set aspect-ratio: 3 / 2 on the img and override it inside a media query that matches each source's media condition.

Art direction responsive images CSS with object-fit and object-position

The Object-Fit Fallback

The art direction responsive images CSS approach uses object-fit and object-position to reframe a single image. It is a legitimate fallback when the picture element feels like overkill. The image-set() function, usable in CSS background-image, does resolution and format switching. It cannot do art direction. image-set() accepts a list of image candidates with density descriptors or type descriptors. The client picks one based on device pixel ratio and format support. It does not accept media conditions. It cannot switch between different crops at different viewport widths. For art direction, image-set() is the wrong tool.

A Complete Container Query Sample

Here is a runnable sample of the object-fit and object-position art direction pattern, using a container query to drive the crop:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Art direction with container query</title>
  <style>
    .frame {
      container-type: inline-size;
      width: 100%;
      max-width: 1200px;
      margin: 0 auto;
    }
    .frame img {
      display: block;
      width: 100%;
      height: auto;
      aspect-ratio: 16 / 9;
      object-fit: cover;
      object-position: center;
    }
    @container (min-width: 700px) {
      .frame img {
        object-position: 30% center;
      }
    }
  </style>
</head>
<body>
  <div class="frame">
    <img src="city-skyline.jpg" alt="A city skyline with a prominent tower" width="1600" height="900">
  </div>
</body>
</html>

This sample downloads one file and re-frames it. The aspect-ratio property reserves 16:9 space before the image loads, so cumulative layout shift is zero. The object-position shifts the visible portion as the container grows. The limitation: the source must be high-resolution enough to survive the zoom that object-fit: cover applies when the container is tall or narrow. A wide image cropped to a square uses only a fraction of its pixels, so the effective resolution is poor. The picture element version would serve a dedicated square file that looks sharp. The trade is between simplicity and quality.

Format switching with type and the picture element srcset sizes production pattern

The picture element also handles format switching: serving WebP or AVIF to clients that support them while falling back to JPEG for older engines. The type attribute on a source element declares the MIME type. The client uses the first source whose type it can decode. This is separate from art direction. A source can have both a media attribute and a type attribute. Both must match for the client to select it. The syntax is straightforward.

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="A mountain valley in autumn" width="1200" height="800">
</picture>

A client that supports AVIF downloads image.avif. That file is smaller than WebP and much smaller than JPEG for the same visual quality. A client that only supports JPEG downloads image.jpg. The img element is the fallback and the rendering element. It must always be present with a valid src, even if every source matches. The img provides the alt text, the width and height, and the intrinsic size. A common mistake is placing the type or media attribute on the picture element itself. Those belong on the source children, not on the picture or on the img. The picture element has no attributes of its own beyond the global ones. It is a pure wrapper. Another common mistake is forgetting the src on the img. That results in a broken image icon even when a source matches, because the img is the element that actually fetches and renders.

Common pitfalls and the failure case for each pattern

The most frequent failure in the picture element is the media attribute on the wrong element. The source elements inside picture each carry their own media attribute. They are evaluated in document order. The first matching source wins, so order matters. Put the most specific or the largest breakpoint first, and the fallback last. A wide breakpoint after a narrow one never fires. The narrow one matches first. Another pitfall is using the same srcset on multiple sources without changing the media conditions. That defeats the purpose and serves the same file twice. The failure case for the container query pattern is forgetting container-type on the container element. Without container-type: inline-size, the container query has nothing to measure. The @container rule is ignored entirely. The failure case for the srcset and sizes pattern is omitting the sizes attribute. The client defaults to a 100vw guess that may be wildly wrong. It downloads an image far larger than the rendered size, destroying the performance benefit. The failure case for cumulative layout shift prevention is setting width and height that do not match the actual aspect ratio of the source. That causes a shift when the client swaps from the reserved box to the real image. Keep the width and height consistent with the fallback source. Override aspect-ratio in CSS when the selected source has a different shape.

Baseline widely available and progressive enhancement in practice

What Baseline Means For These Patterns

The picture element is Baseline widely available. It has been supported in all major engines without a prefix since 2017. The img element with srcset and sizes is similarly Baseline. Container queries achieved Baseline widely available in 2023, with the caveat that older Safari versions had interop bugs with container units like cqw and cqh that shipped before the full feature set. For art direction, the picture element is the safest choice. It has been stable for nearly a decade, and the fallback is inherent. An engine that does not understand picture uses the img child. That is progressive enhancement at its cleanest. You do not need a JavaScript polyfill. You do not need to duplicate the image in a background-image.

The Working Pattern

The picture element is the destination for art direction. Container queries are the detour you take only when the source image is a shared asset. Write the picture element with media attributes for the crops. Pair it with width and height on the img to prevent cumulative layout shift. For resolution switching within a single crop, use srcset and sizes on the img directly. For format switching, use source with type. For re-framing a single image inside a fluid container, use object-fit and object-position inside a container query. Ask one question: does the client need to download a different file? If yes, picture. If no, CSS. That rule keeps the page fast and the layout stable.

A complete production example combining all three patterns

Here is a single, runnable HTML page that combines art direction with media attributes, resolution switching with srcset and sizes, format switching with type, and cumulative layout shift prevention with width, height, and aspect-ratio. Drop this production pattern into a real site and adapt it.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Art direction with picture and container fallback</title>
  <style>
    .hero {
      width: 100%;
      max-width: 1400px;
      margin: 0 auto;
    }
    .hero img {
      display: block;
      width: 100%;
      height: auto;
      aspect-ratio: 16 / 9;
    }
    @media (min-width: 800px) {
      .hero img {
        aspect-ratio: 21 / 9;
      }
    }
  </style>
</head>
<body>
  <picture>
    <source media="(min-width: 800px)" srcset="hero-wide.avif" type="image/avif">
    <source media="(min-width: 800px)" srcset="hero-wide.webp" type="image/webp">
    <source media="(min-width: 800px)" srcset="hero-wide.jpg">
    <source srcset="hero-narrow.avif" type="image/avif">
    <source srcset="hero-narrow.webp" type="image/webp">
    <img src="hero-narrow.jpg" alt="A winding road through alpine meadows" width="1600" height="900">
  </picture>
</body>
</html>

This example serves a 21:9 wide crop on viewports 800px and up, and a 16:9 narrow crop below 800px. Each crop is available in AVIF, WebP, and JPEG. The img element has width and height that describe the narrow fallback. The CSS media query overrides aspect-ratio to 21:9 on wide viewports, so the layout box matches the wide source and no shift occurs. The picture element with media attributes is the primary mechanism. The CSS aspect-ratio override is the supporting detail that keeps the layout stable. Use this pattern for any hero image, product card, or editorial lead where the crop must change with the viewport.

What the picture element does not solve, and who should skip it

Problems Outside The Picture Element's Scope

The picture element does not solve the problem of a single image that must fit a container of unknown size without cropping. For that, you want object-fit with cover or contain, or a background-image with background-size: cover. The picture element does not solve lazy loading. That is the loading attribute on the img element. It does not solve responsive video posters or iframe aspect ratios. Those have their own patterns. If your only need is to serve a smaller file to a phone and a larger file to a desktop with the same crop, do not use picture. Put srcset and sizes directly on the img and skip the extra markup. If your only need is to serve WebP or AVIF to modern clients and JPEG to old ones, use source with type, but remember the img fallback.

Who Should Use Each Pattern

The picture element suits the traveller who needs to change the destination. The hero image that must be a different subject at different sizes. The product photo that must frame the item differently on a mobile card versus a desktop splash. The editorial image that must be a portrait on a phone and a landscape on a monitor. The container query with object-fit suits the traveller who is happy staying in one place. The same image re-framed by CSS, accepting the quality trade for the sake of a single asset. Learn the picture element first if you are building a design system with shared image assets across many components. It gives the most control and the best performance. Start with object-fit and container queries if you are retrofitting an existing site with fluid cards and lack the asset budget to author multiple crops. Migrate to picture when the layout becomes art-directed. Skip the picture element entirely if your images are purely decorative and the crop never changes. A single img with srcset and sizes and a fixed aspect-ratio is all the machinery you need.