Command Palette

Search for a command to run...

Hectal
PHASE 9Intermediate ~27 min· topic 5 of 7

Topic 9.5

Responsive Images and Media in CSS

In one line

Images and video are fixed-size by nature, so responsive pages tame them with CSS: max-width: 100%; height: auto stops overflow while keeping the shape, aspect-ratio reserves the right space, and object-fit/object-position decide how a picture fills a box of a different shape.

Think of it like this

Photos in frames. You have a wide holiday photo and a tall, narrow frame. You can squash the photo to fit (everyone looks thin), shrink it until it fits with empty bands above and below, or crop it so it fills the frame and some edges are cut off, choosing which part to keep (the faces). CSS gives you exactly those three choices for images, plus a rule that a photo must never be bigger than the wall it hangs on.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Intrinsic size
An image's natural width and height, from the file itself.
Aspect ratio
Width divided by height, like 16:9 or 3:2. It describes the shape.
`max-width: 100%`
"Never wider than my container": the image can shrink but never overflow.
Layout shift (CLS)
Content jumping as images load. CLS (Cumulative Layout Shift) is the browser's score for it.
Replaced element
An element whose content comes from outside CSS, such as <img>, <video>, <iframe> or <canvas>.
`object-fit`
How a replaced element's content fills its box: fill, contain, cover, none or scale-down.
`object-position`
Which part of the image stays in view, or where it sits inside its box.
Letterboxing
Empty bands around a picture that has been shrunk to fit a box of another shape.

Step by step

01Stop images overflowing

This rule belongs in every stylesheet. Images shrink to fit narrow containers and keep their shape; on wide screens they never grow beyond their real size.

style.csswhole filecss
img, video {
  max-width: 100%;
  height: auto;
  display: block; /* no gap under the image */
}

02Reserve the space with width and height

Put the real size in the HTML. The browser computes the ratio and reserves the right height before the file arrives, even though CSS makes the image fluid.

index.htmlwhole filehtml
<img src="lake.jpg" width="1200" height="800"
     alt="A still lake at sunrise with hills behind">

03Give video embeds a shape

An <iframe> from a video site has no ratio CSS knows about. aspect-ratio makes it full width with the right height.

style.csswhole filecss
.video {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
}

04Same-shape thumbnails with cover

Photos come in every shape. Force one shape with aspect-ratio, then let object-fit: cover fill it and crop the edges, and object-position choose what to keep.

style.csswhole filecss
.thumb {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 30%; /* keep faces, a bit above centre */
}

05Choosing an object-fit value

Pick based on whether you can lose edges (cover) or must show everything (contain).

Choosing an object-fit valuediagram
Rendering diagram…

Try it yourself

  1. 1

    Remove height: auto

    In the first example, delete height: auto. Predict the drawn size (the height="400" attribute now wins: 240 × 400, a squashed image). Run and check, then put it back.

  2. 2

    Change the box shape

    In the object-fit example, change the images to width: 150px; height: 60px. Predict which values now crop and which show bands.

  3. 3

    A different ratio

    In the last example, change the video to aspect-ratio: 4 / 3. Predict the height for a 240px width (180px) and check the console.

Code & diagrams

max-width: 100% and height: auto New tab

The image file is 600 × 400, but its column is 240px. `max-width: 100%` shrinks it to 240px and `height: auto` keeps the 3:2 shape, so it's 160px tall. The `aspect-ratio` comes from the `width` and `height` attributes.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

width attribute: 600
drawn size: 240 x 160
aspect-ratio: auto 600 / 400
The five object-fit values New tab

Each box is 100 × 100; the picture is 200 × 100. `fill` squashes the face; `contain` shows everything with grey bands; `cover` fills the box and crops the sides; `none` shows the middle at real size; `scale-down` here acts like `contain` because that gives the smaller picture.

Preview

Press Run to see the page.

Console

Nothing logged yet.
object-position keeps the subject in view New tab

Both images crop a wide picture to a square. Centred, the face on the left is cut off; `object-position: left` keeps it. The computed value is always written as two percentages or lengths.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

50% 50%
0% 50%
aspect-ratio for embeds and placeholders New tab

Only the width is known (240px); `aspect-ratio` works out the height. A real video `<iframe>` gets the same rule plus `width: 100%`. `aspect-ratio: 1` is the same as `1 / 1`.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

video: 240 x 135
square: 240 x 240

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

max-width without height: auto

Write img { max-width: 100%; } on an image that has width="1200" height="800" attributes, inside a 300px column.

terminal
$ Page
── what you'll see ──
The image is 300px wide but still 800px tall: it looks stretched vertically.

Break #2

A strip under every card image

Put an <img> in a card with a border and no other styles.

terminal
$ Page
── what you'll see ──
A thin gap of about 4px appears between the bottom of the image and the card's border.

Myth vs fact

Myth

width: 100% is the same as max-width: 100% for images.

Fact

width: 100% stretches small images up to fill the container, making them blurry. max-width: 100% only shrinks large ones and leaves small ones at their real size.

Myth

Setting width and height attributes makes images non-responsive.

Fact

With height: auto (and max-width: 100%) in CSS, the image stays fluid, and the attributes give the browser the ratio to prevent layout shift.

Myth

object-fit works on any element.

Fact

It works on replaced elements like <img>, <video> and <iframe>. For a <div> with a background image, use background-size: cover instead.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Width and height attributes became the source of a default aspect-ratio: auto w / h in 2019–2021 across browsers, after work by the CSS working group and web performance advocates. The auto means "use the image's real ratio once it has loaded, and this one until then".

  • ▸

    object-fit: cover crops visually, but the full image is still downloaded and decoded. For big savings, serve the right size with srcset/sizes (HTML) and modern formats (AVIF, WebP); CSS cropping is only presentation.

  • ▸

    aspect-ratio sets a preferred ratio. If both width and height are set, it's ignored. With min-height: auto (the default for most boxes), content that doesn't fit makes the box taller instead of overflowing.

  • ▸

    For iframes like maps or videos, aspect-ratio replaced the old "padding hack" (padding-top: 56.25% on a wrapper with an absolutely positioned iframe). You'll still see the hack in old code; it works because vertical padding percentages are based on the containing block's width.

Remember this

  1. 1

    An image has an intrinsic size: its natural width and height in pixels, for example 1200 × 800. Its aspect ratio is width divided by height, here 3:2 (1.5). By default an <img> is drawn at its intrinsic size, so a 1200px photo on a 390px phone sticks out and makes the page scroll sideways. The fix is two lines: img { max-width: 100%; height: auto; }. max-width: 100% means "never wider than my container" (it can still be smaller), and height: auto recalculates the height from the aspect ratio, so the image shrinks without being squashed.

  2. 2

    Always write width and height attributes in the HTML (<img src="…" width="1200" height="800" alt="…">). Browsers turn them into a default aspect-ratio: auto 1200 / 800, so they can reserve the right amount of space before the image downloads. Combined with height: auto in CSS, the image is still fluid, and the text below doesn't jump when it loads. That jump is called layout shift, measured as CLS (Cumulative Layout Shift), one of Google's Core Web Vitals.

  3. 3

    Images are inline elements by default (Phase 5, Topic 5.4), so they sit on the text baseline and leave a few pixels of gap below them for letter descenders (the tails of g, p, y). Inside cards this shows as a mysterious strip under the picture. A common reset adds display: block to images, which removes the gap; vertical-align: middle also works.

  4. 4

    The aspect-ratio property (Phase 5, Topic 5.5) gives any box a shape: aspect-ratio: 16 / 9 with width: 100% makes the height follow the width. It's perfect for video embeds and <iframe>s, which don't have an intrinsic ratio CSS knows about, for placeholders, and for making every card thumbnail the same shape. If the content is taller than the ratio allows, a normal box grows to fit it, because its min-height is auto; set overflow: hidden or min-height: 0 if you want the ratio to win.

  5. 5

    When an image's box has a different shape from the image itself, object-fit decides how the picture fills it. fill (the default) stretches it to the box, squashing it. contain shrinks it to fit entirely inside, leaving empty bands (letterboxing). cover fills the whole box and crops what sticks out. none keeps the intrinsic size and crops. scale-down uses whichever of none or contain gives the smaller picture. object-position chooses which part is kept when cropping or where the image sits: the default is 50% 50% (centre); top or 30% 20% keeps a face in view. These work on <img>, <video> and other replaced elements (elements whose content comes from outside the CSS, such as images, video and canvas).

  6. 6

    CSS can't choose which file to download for a screen; that is HTML's job with srcset, sizes and <picture> (see the /html course, Phase 5). CSS only controls how a downloaded image is displayed. For CSS background images, background-size: cover is the background equivalent of object-fit: cover (Phase 5, Topic 5.8), and image-set() offers resolution choices. Use <img> for meaningful pictures (they get alt text and lazy loading) and backgrounds for decoration.

Explain it without notes

01

Why do max-width: 100% and height: auto make images responsive?

02

How do the HTML width and height attributes help with layout shift, even for fluid images?

03

Compare object-fit: contain, cover and fill.

04

How would you make a YouTube <iframe> embed responsive?

Practice

01

Write CSS so every image and video on a page is fluid, keeps its shape and has no gap underneath.

02

Make a gallery of square thumbnails from photos of any shape, keeping the top of each photo (people's heads) in view.

03

Make a map <iframe> that is full width and always 4:3.

Trade-offs

  • ↔

    object-fit: cover gives tidy, same-shape grids but can crop important content; contain shows everything but leaves uneven bands.

  • ↔

    A display: block reset for images removes the baseline gap everywhere, but images that should sit inside a line of text (like small icons) then need display: inline back.

Done when you can

  • I add max-width: 100%; height: auto to images and video.

  • I keep width and height attributes to prevent layout shift.

  • I can use aspect-ratio for embeds, placeholders and thumbnails.

  • I can choose between fill, contain, cover, none and scale-down.

  • I can keep the subject in view with object-position.

  • I know that choosing which image file to load is HTML's job (srcset).