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,noneorscale-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.
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.
<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.
.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.
.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).
Try it yourself
- 1
Remove height: auto
In the first example, delete
height: auto. Predict the drawn size (theheight="400"attribute now wins: 240 × 400, a squashed image). Run and check, then put it back. - 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
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
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
Console
Nothing logged yet.Expected console output
width attribute: 600
drawn size: 240 x 160
aspect-ratio: auto 600 / 400Each 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
Console
Nothing logged yet.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
Console
Nothing logged yet.Expected console output
50% 50%
0% 50%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
Console
Nothing logged yet.Expected console output
video: 240 x 135
square: 240 x 240Break 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.
Break #2
A strip under every card image
Put an <img> in a card with a border and no other styles.
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 / hin 2019–2021 across browsers, after work by the CSS working group and web performance advocates. Theautomeans "use the image's real ratio once it has loaded, and this one until then". - ▸
object-fit: covercrops visually, but the full image is still downloaded and decoded. For big savings, serve the right size withsrcset/sizes(HTML) and modern formats (AVIF, WebP); CSS cropping is only presentation. - ▸
aspect-ratiosets a preferred ratio. If bothwidthandheightare set, it's ignored. Withmin-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-ratioreplaced 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
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), andheight: autorecalculates the height from the aspect ratio, so the image shrinks without being squashed. - 2
Always write
widthandheightattributes in the HTML (<img src="…" width="1200" height="800" alt="…">). Browsers turn them into a defaultaspect-ratio: auto 1200 / 800, so they can reserve the right amount of space before the image downloads. Combined withheight: autoin 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
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: blockto images, which removes the gap;vertical-align: middlealso works. - 4
The
aspect-ratioproperty (Phase 5, Topic 5.5) gives any box a shape:aspect-ratio: 16 / 9withwidth: 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 itsmin-heightisauto; setoverflow: hiddenormin-height: 0if you want the ratio to win. - 5
When an image's box has a different shape from the image itself,
object-fitdecides how the picture fills it.fill(the default) stretches it to the box, squashing it.containshrinks it to fit entirely inside, leaving empty bands (letterboxing).coverfills the whole box and crops what sticks out.nonekeeps the intrinsic size and crops.scale-downuses whichever ofnoneorcontaingives the smaller picture.object-positionchooses which part is kept when cropping or where the image sits: the default is50% 50%(centre);topor30% 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
CSS can't choose which file to download for a screen; that is HTML's job with
srcset,sizesand<picture>(see the/htmlcourse, Phase 5). CSS only controls how a downloaded image is displayed. For CSS background images,background-size: coveris the background equivalent ofobject-fit: cover(Phase 5, Topic 5.8), andimage-set()offers resolution choices. Use<img>for meaningful pictures (they getalttext and lazy loading) and backgrounds for decoration.
Explain it without notes
Why do max-width: 100% and height: auto make images responsive?
How do the HTML width and height attributes help with layout shift, even for fluid images?
Compare object-fit: contain, cover and fill.
How would you make a YouTube <iframe> embed responsive?
Practice
Write CSS so every image and video on a page is fluid, keeps its shape and has no gap underneath.
Make a gallery of square thumbnails from photos of any shape, keeping the top of each photo (people's heads) in view.
Make a map <iframe> that is full width and always 4:3.
Trade-offs
- ↔
object-fit: covergives tidy, same-shape grids but can crop important content;containshows everything but leaves uneven bands. - ↔
A
display: blockreset for images removes the baseline gap everywhere, but images that should sit inside a line of text (like small icons) then needdisplay: inlineback.
Done when you can
I add
max-width: 100%; height: autoto images and video.I keep
widthandheightattributes to prevent layout shift.I can use
aspect-ratiofor embeds, placeholders and thumbnails.I can choose between
fill,contain,cover,noneandscale-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).