Responsive Images CSS
CSS techniques for responsive images — max-width, object-fit, art-direction hooks, and how CSS pairs with srcset and sizes.
- css
- responsive-images
- images
Responsive images are a HTML + CSS partnership. HTML (srcset, sizes, <picture>) picks which file to download. CSS decides how the chosen image paints in the layout. Confusing the two causes either huge downloads or broken crops.
Docs: MDN responsive images, object-fit, web.dev images.
Never overflow the container
img,
video {
max-width: 100%;
height: auto;
display: block; /* remove inline baseline gap */
}
This is the baseline. Intrinsic width attributes still help CLS; CSS prevents flex/grid blowouts.
Fit the slot
.card__media {
aspect-ratio: 16 / 9;
overflow: hidden;
background: var(--surface-2);
}
.card__media img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top; /* keep faces */
}
Use contain for product logos that must not crop; cover for photography.
Pairing with sizes (conceptual)
<img
src="/hero-800.jpg"
srcset="/hero-400.jpg 400w, /hero-800.jpg 800w, /hero-1200.jpg 1200w"
sizes="(min-width: 48rem) 50vw, 100vw"
width="1200"
height="675"
alt=""
/>
sizes must match layout CSS. If CSS eventually shows the image at full viewport on desktop, lying with 50vw downloads a too-small file (blur) or wastes bandwidth the other way. When you change grid breakpoints, update sizes.
Background images vs content images
.hero {
background-image: image-set(
url("/hero.avif") type("image/avif"),
url("/hero.webp") type("image/webp"),
url("/hero.jpg") type("image/jpeg")
);
background-size: cover;
background-position: center;
}
Use content <img> when the image is meaningful (alt text, SEO). Use CSS backgrounds for pure decoration. Backgrounds don’t get srcset selection the same way — image-set() helps resolution, not full art direction.
Art direction is HTML
CSS object-position can re-crop slightly; swapping a vertical crop for mobile vs wide landscape is <picture> + media attributes, not a media query on content: url() for primary content.
<picture>
<source media="(max-width: 40rem)" srcset="/hero-mobile.jpg" />
<img src="/hero-desktop.jpg" alt="Conference hall" />
</picture>
Performance-minded CSS
.below-fold img {
content-visibility: auto; /* where appropriate */
}
img[loading="lazy"] {
/* browser lazy-loads; still reserve aspect-ratio */
aspect-ratio: attr(width type(<number>)) / attr(height type(<number>)); /* limited support — prefer width/height attrs + CSS ratio */
}
Prefer explicit aspect-ratio matching the asset.
Interview out-loud
“CSS makes images fluid with max-width: 100% and controls cropping with object-fit and aspect-ratio. File selection is HTML srcset/sizes/picture. I keep sizes honest to the CSS layout, use content images for meaningful media, and backgrounds for decoration only.”
Footguns
height: automissing → stretched images.sizeslying after a redesign.- Heavy CSS filters on large heroes (decode + paint cost).
- Using background-image for captions/SEO content.
- Fixed pixel widths fighting fluid grids.
LCP hero checklist
- Right format (AV1/AVIF/WebP/JPEG chain).
- Honest
sizes+ adequatesrcset. width/heightor CSSaspect-ratio.- Do not lazy-load the LCP image.
- Optional
fetchpriority="high"on the LCPimg. - CSS
object-fitonly after the resource is chosen correctly.
<img
src="/hero-1200.jpg"
srcset="/hero-800.jpg 800w, /hero-1200.jpg 1200w, /hero-1600.jpg 1600w"
sizes="100vw"
width="1600"
height="900"
alt="…"
fetchpriority="high"
decoding="async"
/>
CSS cannot fix a 3MB hero. Optimize assets first; crop second; style third.
Density and art direction split
Use srcset density descriptors for fixed icons; use width descriptors for fluid photos; use <picture> when the crop changes. CSS image-set() helps with background resolution switching but still lacks the full sizes negotiation of content images. Keep the decision tree in the component docs so designers request the right asset package (one crop vs many).
Related
- object-fit and aspect-ratio
- picture and srcset
- Images alt and decorative
- Media queries modern approach
Further reading
Related guides
- Accent Color and Form ControlsUse accent-color to theme native checkboxes, radios, ranges, and progress — what it paints, what it skips, and when to custom-style instead.
- Auto-fit vs Auto-fillauto-fit collapses empty tracks; auto-fill keeps them. Use both with minmax for responsive card grids without media-query soup.
- BEM Naming MethodologyBlock, Element, Modifier naming for CSS — how it limits specificity wars, what to name, and when utility or CSS modules beat strict BEM.
- blend-mode Basicsmix-blend-mode vs background-blend-mode — how pixels combine, isolation, and the stacking/readability traps in product UI.
- box-sizing border-boxWhy border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.