Fit, Fill or Stretch: Three Ways to Resize Into a Box

Contain, cover and distort: the exact math behind fit/fill/stretch scaling, when each is right, and how to predict bars, crops and distortion before you export.

Published 2026-10-02

Every resize into a fixed-size box reduces to one decision: what do you do when the aspect ratios don’t match? There are exactly three honest answers, and every image tool, CSS property and video player implements some spelling of them.

The setup: one source, one box

You have a source sw × sh and a target box bw × bh. Two scale factors exist:

  • sx = bw ÷ sw — what the width wants
  • sy = bh ÷ sh — what the height wants

When sx = sy the source and box share an aspect ratio and every mode does the same thing. Everything interesting happens when they differ.

Fit (contain): the smaller factor wins

s = min(sx, sy)
W' = sw × s,  H' = sh × s

Using the smaller factor guarantees the scaled image stays inside the box on both axes — one axis touches the box exactly, the other falls short and leaves empty space: letterbox bars (top/bottom) or pillarbox bars (left/right). Nothing is cropped, nothing is distorted.

Example: a 1920×1080 video fitted into a 1080×1080 Instagram square. sx = 0.5625, sy = 1.0s = 0.56251080×607, with ~236 px bars top and bottom. That’s exactly what Instagram does to landscape posts if you don’t crop.

Fit is the right mode for product photos, documents, screenshots — anywhere losing content is worse than showing empty space.

Fill (cover): the bigger factor wins

s = max(sx, sy)
W' = sw × s,  H' = sh × s

Using the larger factor guarantees the box is completely covered — one axis matches exactly, the other overflows and gets cropped (usually symmetrically, sometimes anchored to a side or to a detected focal point). No bars ever; data is thrown away on one axis.

Same 1920×1080 source filled into the square box: sx = 1080÷1920 = 0.5625, sy = 1080÷1080 = 1.0s = 1.0 → the image stays 1920×1080, and the box crops (1920 − 1080) ÷ 2 = 420 px off each side. Nearly half the frame disappears; the square shows only the central slice — which is why fill demands a source with safe margins.

Fill is the right mode for hero images, video feeds and thumbnails — anywhere a hole is uglier than a crop.

Stretch: no factor at all

W' = bw,  H' = bh

Each axis takes its own factor. If sx ≠ sy the image distorts — the distortion ratio is max(sx÷sy, sy÷sx). A 16:9 frame stretched into 4:3 compresses the width to 75%: faces go noticeably thin. The same frame stretched into 1.91:1 only skews ~7%, which is why mildly-wrong aspect slips into production so often — it’s just subtle enough to miss.

Stretch is right almost never — but it has two legitimate uses: graphics designed for the target aspect being re-rendered at other sizes (SVG-ish workflows), and deliberately anamorphic pipelines (3840×2160 carrying squeezed 2.39:1 cinema content that a projector un-squeezes). For ordinary imagery, treat any stretch that isn’t ~1.00 as a bug.

Which mode does my software use?

Tool Fit Fill Stretch
CSS object-fit contain cover fill
CSS background-size contain cover 100% 100%
FFmpeg scale+pad scale=w:h:force_original_aspect_ratio=decrease then pad ...=increase then crop plain scale=bw:bh
Video players “letterbox” / default “zoom” / “fill” “stretch”
Photoshop / GIMP export “resize to fit” crop-then-resize unchecking the chain icon

Two edge cases worth checking

  • Upscale needs headroom on both axes. Fit enlarges only when the box beats the source on width and height — min(sx, sy) can exceed 1 only if both factors do. A wider-but-shorter box (a 4:3 source into a 16:9 banner) still downscales, because the short axis caps min below 1; growing past the short side is fill’s move. Where fit does upscale: 1200×900 into a 1920×1080 box → min(1.6, 1.2) = ×1.2 → 1440×1080. Watch the ×factor, not just the dims; the scaler flags any result above ×1.
  • Fractional results. sw × s is rarely an integer. Rounding to the nearest pixel is standard; rounding to even matters only when the output feeds a video codec (odd dims fail encoders outright). Both behaviors are on the calculator page — the ladder mode always rounds to even.

The one-line summary: fit preserves everything and may pad; fill covers everything and must crop; stretch gives you the exact box and takes your aspect ratio hostage.

Frequently asked questions

Which mode should I pick for a website hero image?

Fill (cover), almost always. Heroes need the whole slot painted edge-to-edge — design the source so the important content survives a crop on either axis, and keep the subject centered. Fit would leave unpainted bands; stretch would skew your photography.

Is 'fit' the same as 'letterbox'?

Fit is the operation; letterboxing is a possible side-effect. Fit only produces bars when the source and box aspects differ — scale a 16:9 image into a 16:9 box and fit produces zero bars. The bars themselves are computed in the letterbox guide.

Can fill lose important parts of my image?

Yes — fill crops whatever overflows the box, symmetrically by default (most tools center-crop). If a face sits near the top edge, a top-aligned crop is safer; most software lets you pick the crop anchor. The scaler's fill readout tells you exactly how many pixels get trimmed before you commit.

Why does my stretch look subtly wrong even though it 'worked'?

Because the distortion is proportional, not absolute. A 16:9 image stretched into a 4:5 box squeezes the width to 45% — unmistakable. But 16:9 into a 1.91:1 Facebook box is only a 7% squash: easy to miss in a preview, visible to anyone who knows the original. The distortion readout (×axis-ratio) catches even small skews.

What about 'scale down only' flags in CMSes and CSS?

That's fit with a cap: s = min(1, min(boxW÷srcW, boxH÷srcH)) — never upscale, shrink only if needed. CSS expresses it as max-width:100% without fixed dimensions. It exists precisely because upscaling invents pixels; why direction matters covers that.