How to Change an Image’s Aspect Ratio with CSS and Tools
Change an image’s displayed or saved aspect ratio without unwanted distortion. Use CSS for layout and an editor when you need a new cropped file.
To change an image’s aspect ratio, first decide whether you are changing its display on a webpage or creating a new image file. CSS changes the element’s box and how the existing pixels fit inside it. An image editor changes the crop or canvas and saves a new asset.
- Use
width: 100%; height: autowhen the image should keep its natural ratio responsively. - Use a wrapper with
aspect-ratioandobject-fitwhen several images must fit a fixed frame. - Use
object-fit: coverto fill a frame and crop overflow,containto show every pixel with possible empty space, orfillonly when stretching is acceptable. - Use an editor when the changed crop must be saved, downloaded, uploaded, or reused outside the browser.
Choose the result you need
| Goal | Use | What happens to pixels |
|---|---|---|
| Responsive image with no distortion | width: 100%; height: auto |
All pixels remain visible and the height follows the source ratio. |
| Uniform cards or thumbnails | aspect-ratio plus object-fit: cover |
The frame is fixed; edges may be cropped. |
| Show the complete image in a fixed frame | object-fit: contain |
All pixels remain visible; bars or empty space can appear. |
| Create a new file at another ratio | Image editor or image-processing pipeline | The crop or canvas is saved as a separate asset. |
The CSS aspect-ratio property sets a preferred width-to-height ratio for an element’s box. Its value is width divided by height, such as 16 / 9 or 1 / 1. At least one dimension must remain automatic for the preferred ratio to affect sizing. See the MDN aspect-ratio reference.
Keep an image’s natural aspect ratio with CSS
For a fluid image that should never be squashed, set one dimension and let the other be calculated:
<img class="responsive-image" src="photo.jpg" alt="A mountain lake">
<style>
.responsive-image {
display: block;
width: 100%;
height: auto;
max-width: 100%;
}
</style>
This scales the image to its container while preserving the intrinsic ratio. The same pattern works with a fixed width:
.photo {
width: 640px;
height: auto;
}
Avoid assigning unrelated explicit values to both width and height. If the dimensions do not have the same ratio as the source, the browser can distort the image.
Fit an image into a fixed-ratio frame
Create the ratio on a wrapper, then make the image fill that wrapper:
<figure class="image-frame image-frame--wide">
<img src="photo.jpg" alt="A mountain lake">
</figure>
<style>
.image-frame {
aspect-ratio: 16 / 9;
overflow: hidden;
margin: 0;
}
.image-frame img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
cover preserves the source ratio and enlarges the image until the frame is filled. Any excess on the sides or top and bottom is cropped, as described in the MDN object-fit guide.
Choose between cover, contain, and fill
/* Crop overflow to fill the frame. */
img.cover { object-fit: cover; }
/* Show every pixel; empty space may remain. */
img.contain { object-fit: contain; background: #eee; }
/* Stretch to both dimensions; this can distort the image. */
img.fill { object-fit: fill; }
| Value | Use it when | Trade-off |
|---|---|---|
cover |
Edge-to-edge cards, hero banners, avatars | Crops part of the source. |
contain |
Product diagrams, screenshots, logos, documents | May leave bars or unused space. |
fill |
The source is known to match the frame or distortion is intentional | Can stretch or squash content. |
none |
Keep the image at its intrinsic size | It may overflow the frame. |
scale-down |
Use the smaller result of none and contain |
Useful when images must never be enlarged. |
Control which part is cropped
Use object-position to keep a face, product, or focal point visible:
.hero img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 20%; /* center horizontally, favor the top */
}
.subject-right img {
object-position: 75% 50%;
}
Percentages, lengths, and keywords such as top, center, and right are supported. Adjust this per image when important content sits near an edge.
Responsive ratios and breakpoints
You can change the frame ratio at different viewport sizes:
.card-media {
aspect-ratio: 4 / 3;
overflow: hidden;
}
.card-media img {
width: 100%;
height: 100%;
object-fit: cover;
}
@media (min-width: 900px) {
.card-media { aspect-ratio: 16 / 9; }
}
For a ratio that follows a design token, use a custom property:
:root { --media-ratio: 3 / 2; }
.media { aspect-ratio: var(--media-ratio); }
For older layouts that cannot use aspect-ratio, the padding-top technique expresses height as a percentage of width:
.legacy-frame {
position: relative;
height: 0;
padding-top: 56.25%; /* 9 / 16 × 100 for 16:9 */
overflow: hidden;
}
.legacy-frame > img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
Prefer aspect-ratio for new code because it states the intent directly.
Prevent layout shifts while images load
Reserve the intended shape before the image downloads:
.thumbnail {
aspect-ratio: 1 / 1;
background: #f2f2f2;
overflow: hidden;
}
.thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
}
You can also provide intrinsic dimensions on the element:
<img src="photo.jpg" width="1600" height="900" alt="...">
Those attributes describe the source ratio and let the browser reserve space. If your CSS deliberately uses another ratio, the wrapper’s aspect-ratio and the image’s fit rules determine the final frame.
Crop without distorting: complete HTML example
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Aspect-ratio demo</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; font: 16px/1.5 system-ui, sans-serif; }
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
max-width: 1100px;
margin: 2rem auto;
padding: 0 1rem;
}
.frame {
aspect-ratio: 4 / 3;
overflow: hidden;
background: #eee;
border-radius: .5rem;
}
.frame img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
.frame--contain img {
object-fit: contain;
}
</style>
</head>
<body>
<main class="gallery">
<figure class="frame">
<img src="photo.jpg" alt="Mountain lake" loading="lazy">
</figure>
<figure class="frame frame--contain">
<img src="diagram.png" alt="System diagram" loading="lazy">
</figure>
</main>
</body>
</html>
Change the actual image file with an editor
CSS does not write a new crop into the source file. When another system needs a 1:1, 4:3, or 16:9 asset, crop and export a new file.
- Open the original and keep an untouched copy.
- Choose the crop tool.
- Select a preset ratio or enter custom width and height.
- Move the crop to keep the subject and important edges visible.
- Export a new JPEG, PNG, or WebP at the required dimensions.
- Use the exported file in your page and keep the original for future ratios.
Adobe documents this workflow in Lightroom’s crop and rotate help; labels and availability can vary by product version or region.
Crop versus add canvas
A different ratio can be achieved by removing pixels, adding space around the image, or both. Cropping changes which part is visible. Adding a canvas preserves all pixels but creates borders or a background. If no content may be lost, use CSS contain or an editor workflow that expands the canvas.
Aspect-ratio math
The ratio is width divided by height. For a 16:9 image:
height = width × 9 ÷ 16
width = height × 16 ÷ 9
Examples:
- 1600 × 900 is 16:9.
- 1200 × 900 is 4:3.
- 1080 × 1080 is 1:1.
When converting a crop, choose the dimension that must remain fixed, then calculate the other dimension. Inspect the resulting crop at its final display size because a mathematically correct crop can still remove a face, label, or product edge.
ScreenshotNeo capture for checking a rendered ratio
After you implement CSS, capture the real page at the viewport and device settings your users receive. ScreenshotNeo can capture a full page or a selected element, apply custom CSS or JavaScript, wait for a selector or network idle, and return PNG, JPEG, WebP, or PDF. See the ScreenshotNeo documentation.
Or skip the browser setup
Use one request when you need a rendered image rather than configuring Playwright or another browser yourself:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', bytes);
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers identify the page verdict and billing result. Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf tools. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Useful capture options for aspect-ratio work
| Need | ScreenshotNeo option or capability |
|---|---|
| Match a phone, tablet, or desktop | Use one of 12 device presets or specify any viewport. |
| Sharper output | Set a retina scale. |
| Capture only the media card | Select one element by CSS selector. |
| Test dark mode | Enable dark mode. |
| Remove a layout element | Hide selectors or inject custom CSS. |
| Wait for a lazy image | Wait for a selector, delay, or network idle. |
| Keep repeated captures consistent | Use caching with a TTL you choose. |
| Capture many routes | Use bulk capture for up to 100 URLs per call. |
Common problems and fixes
| Symptom | Cause | Fix |
|---|---|---|
| Image looks stretched | Both dimensions are forced to incompatible values, or object-fit: fill is active. |
Set one dimension to auto, or use a ratio frame with object-fit: cover or contain. |
| Important subject is cut off | cover crops overflow from the wrong edge. |
Adjust object-position, change the frame ratio, or use contain. |
| Bars appear around the image | contain preserves all pixels but cannot fill the frame. |
Accept the bars, match the frame to the source ratio, or use cover if cropping is acceptable. |
aspect-ratio seems ignored |
Both width and height are definite, or another rule overrides the size. | Leave one dimension automatic and inspect computed styles in browser tools. |
| Layout jumps while loading | No space was reserved for the media. | Set aspect-ratio on the wrapper or provide accurate width and height attributes. |
| Lazy image is missing in a screenshot | Capture happened before the image loaded. | Wait for a selector, delay, or network idle; ensure the image is inside the captured viewport or full-page area. |
| Screenshot contains a consent banner | The page displayed it before capture. | Use ScreenshotNeo’s consent and cleanup behavior, or hide the banner with an approved custom selector. |
| Screenshot request returns an error | Invalid key, inaccessible URL, timeout, or target blocking automated browsers. | Check the key and URL, increase the wait strategy, send required headers or cookies, and inspect the response status and verdict headers. |
Performance, reliability, and cost
- Browser rendering: CSS fitting is cheap after the image is downloaded. Large source files still consume bandwidth and decode time, so serve appropriately sized responsive assets.
- Layout stability: Reserve the frame with
aspect-ratioto prevent reflow while images load. - Quality: A crop cannot restore detail that was absent in the source. Use a sufficiently large source for retina displays.
- Capture timing: Wait for the actual image or component, especially when JavaScript inserts it or lazy loading is enabled.
- Repeatability: Fix viewport, device scale, color mode, fonts, and wait conditions when comparing screenshots.
- ScreenshotNeo billing: Clean shots are billed; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Use caching when the page does not need a fresh render and bulk capture for batches.
Checklist
- Decide whether you need a display change or a new file.
- For natural sizing, set one dimension and keep the other automatic.
- For a fixed frame, set
aspect-ratioon the wrapper. - Choose
cover,contain, or intentionalfill. - Set
object-positionwhen the focal point is off-center. - Reserve space before loading to avoid layout shifts.
- Inspect edge content at each responsive breakpoint.
- Capture the rendered page at representative viewports before release.
FAQ
Can CSS change the aspect ratio without cropping?
Yes, with contain or a frame that matches the source ratio. The complete image remains visible, but empty space may appear. A new crop necessarily removes some visible area.
Does aspect-ratio edit the image file?
No. It controls the element’s preferred box ratio. Use an editor or image-processing pipeline to save a new crop.
Should I use width: 100%; height: 100%?
Only when the parent has a deliberate size and you also choose an appropriate object-fit. For natural responsive sizing, use height: auto.
What ratio should a social or card image use?
Use the ratio required by the destination or design system. Keep the original and export each required ratio so one crop does not have to serve every context.
How do I verify the ratio on a live page?
Inspect the computed width and height in browser developer tools, then capture the page at target viewports. A ScreenshotNeo element capture is useful when you need the exact rendered card or hero image.


