How to Make an Image Smaller in HTML (5 Methods)
You have a 4000x3000 image. You need it to display at 800x600. There are two completely different problems hiding in that sentence:
- Display size — how large the image appears on the page (controlled by HTML and CSS)
- File size — how many bytes the browser downloads (controlled by compression and export settings)
Setting width="800" on an <img> tag makes the image look smaller. The browser still downloads all 4.8 MB of the original. Your page still loads slowly. Your Core Web Vitals still suffer.
This guide covers both problems. Methods 1-4 handle display size. Method 5 handles file size. For a fast site, you need both.
Quick Comparison
| Method | Controls | Responsive? | Reduces File Size? | Best For |
|---|---|---|---|---|
width/height attributes |
Display size | No | No | Fixed-dimension layouts, CLS prevention |
CSS max-width |
Display size | Yes | No | Fluid layouts, responsive design |
srcset + sizes |
Display size + source selection | Yes | Yes (serves smaller files) | Serving resolution-appropriate images |
<picture> element |
Display size + format + art direction | Yes | Yes (serves smaller files/formats) | Format switching, art direction |
| Pre-upload compression | File size | N/A | Yes | Reducing actual bytes transferred |
Try it yourself
Reduce file size without visible quality loss — free, instant, no signup. Your images never leave your browser.
Method 1: width and height Attributes
The simplest approach. Add width and height directly to the <img> tag:
<img
src="hero-photo.jpg"
alt="Mountain landscape at sunset"
width="800"
height="600"
>
The browser renders the image at 800x600 pixels regardless of the original file dimensions. These values are in CSS pixels, not the intrinsic pixel dimensions of the file.
Why you should always include both attributes: When width and height are present, the browser reserves the correct space in the layout before the image loads. This prevents Cumulative Layout Shift (CLS) — that annoying jump when images pop in and push content around. For a deeper look at how dimensions affect performance, see our guide on HTML image dimensions.
The catch: The browser still downloads the full-size file. A 4000x3000 JPEG at 4.8 MB renders at 800x600, but the user waited for 4.8 MB to arrive. On mobile connections, that matters a lot.
When to use this method:
- Email templates where CSS support is unreliable
- Fixed-width layouts where the image never needs to scale
- As a supplement to CSS (always set both for CLS prevention, even if CSS controls the visual size)
Method 2: CSS max-width and height
CSS gives you responsive control that HTML attributes alone cannot:
<img
src="hero-photo.jpg"
alt="Mountain landscape at sunset"
width="1200"
height="900"
style="max-width: 100%; height: auto;"
>
Or in a stylesheet (preferred):
img {
max-width: 100%;
height: auto;
}
This is the responsive image baseline. The image scales down to fit its container but never stretches beyond its intrinsic width. height: auto preserves the aspect ratio.
A more controlled approach with object-fit:
.thumbnail {
width: 300px;
height: 300px;
object-fit: cover; /* crops to fill the box */
}
.preview {
width: 300px;
height: 200px;
object-fit: contain; /* fits inside the box, may letterbox */
}
object-fit: cover is your friend for avatar circles, card thumbnails, and gallery grids — any context where you need a fixed aspect ratio box but have images of varying proportions.
Keep the HTML attributes: Even when CSS controls the visual size, include width and height on the <img> tag. The browser uses them to calculate the aspect ratio for layout reservation. CSS controls appearance; HTML attributes prevent layout shift.
The same catch applies: The browser still downloads the full-size file. You are resizing on the client side. For optimal website image sizes, you want to serve appropriately-sized source files — which brings us to srcset.
Method 3: srcset and sizes for Responsive Images
srcset lets you provide multiple versions of the same image at different resolutions. The browser picks the best one based on viewport width and screen density:
<img
src="hero-800w.jpg"
srcset="
hero-400w.jpg 400w,
hero-800w.jpg 800w,
hero-1200w.jpg 1200w,
hero-1600w.jpg 1600w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
800px
"
alt="Mountain landscape at sunset"
width="1200"
height="900"
>
Here is what each piece does:
srcsetlists available files and their intrinsic widths (thewdescriptor is the actual pixel width of each file).sizestells the browser how wide the image will be displayed at each breakpoint —100vwon small screens (full width),50vwon medium screens (half width),800pxon large screens.srcis the fallback for browsers that do not supportsrcset(rare, but required).
The browser does the math: on a 375px-wide phone at 2x density, it needs a 750px-wide image, so it picks hero-800w.jpg. On a 1440px desktop at 1x, it needs 800px, same file. On a 1440px Retina display, it grabs hero-1600w.jpg.
The real benefit: A phone downloads a 45 KB file instead of a 380 KB file. Same visual quality, 88% less data. This is the first method that actually reduces bytes transferred.
The work involved: You need to generate multiple versions of each image. Tools like Pixotter's resize tool handle this — drop your image, export at 400, 800, 1200, and 1600px widths, done.
For more on how srcset interacts with lazy loading, check our dedicated guide.
Method 4: The picture Element
<picture> goes beyond srcset by adding art direction and format switching:
<picture>
<!-- Serve AVIF where supported (smallest file) -->
<source
type="image/avif"
srcset="hero-800w.avif 800w, hero-1200w.avif 1200w"
sizes="(max-width: 800px) 100vw, 800px"
>
<!-- Fall back to WebP -->
<source
type="image/webp"
srcset="hero-800w.webp 800w, hero-1200w.webp 1200w"
sizes="(max-width: 800px) 100vw, 800px"
>
<!-- Fall back to JPEG for old browsers -->
<img
src="hero-800w.jpg"
srcset="hero-800w.jpg 800w, hero-1200w.jpg 1200w"
sizes="(max-width: 800px) 100vw, 800px"
alt="Mountain landscape at sunset"
width="1200"
height="900"
loading="lazy"
decoding="async"
>
</picture>
The browser picks the first <source> it supports, then selects the right size from that source's srcset. If nothing matches, it falls back to the <img> tag.
Art direction example — serve a different crop on mobile versus desktop:
<picture>
<source
media="(max-width: 600px)"
srcset="hero-mobile-crop.jpg"
>
<source
media="(max-width: 1200px)"
srcset="hero-tablet.jpg"
>
<img
src="hero-desktop.jpg"
alt="Mountain landscape at sunset"
width="1200"
height="600"
>
</picture>
On mobile, you might want a tighter crop that shows the subject clearly instead of a tiny version of the full landscape. Art direction gives you that control.
When <picture> beats srcset alone:
- You want to serve AVIF/WebP to supporting browsers and JPEG/PNG to the rest
- Different crops at different breakpoints (mobile: portrait crop, desktop: landscape)
- Different images entirely based on context (dark mode, reduced motion, print)
Method 5: Actually Reduce the File Size
Methods 1-4 control how the browser displays the image. None of them change the source file. If your original JPEG is 4.8 MB, that is still 4.8 MB hitting the network (unless srcset or <picture> routes the browser to a smaller variant you prepared).
The most impactful optimization is shipping a smaller file in the first place:
- Resize to the dimensions you need. A 4000x3000 photo displayed at 800x600 wastes 96% of its pixels. Export at 1600x1200 (2x for Retina) and the file drops from 4.8 MB to under 800 KB before any compression.
- Compress. JPEG quality 80 is visually indistinguishable from quality 100 for most photos, at 60-70% less file size. Tools like Pixotter's compress tool let you dial in a target size.
- Choose the right format. AVIF is 30-50% smaller than JPEG at equivalent quality. WebP splits the difference. PNG is for graphics with transparency and sharp edges, not photographs.
For a detailed walkthrough on shrinking file sizes, see our guide on how to make an image MB smaller.
Resize images before adding them to HTML
Pixotter resizes and compresses images in your browser — serve the right file size, not just the right display size.
Display Size vs. File Size — Why Both Matter
Think of it this way: HTML and CSS are the frame on the wall. The file is the painting. You can put a small frame around a huge painting — visitors still carried the huge painting into the room.
Here is the performance math:
| Scenario | File Downloaded | Display Size | LCP Impact |
|---|---|---|---|
| 4000x3000 JPEG, no HTML sizing | 4.8 MB | Native (huge) | Terrible |
4000x3000 JPEG, width="800" |
4.8 MB | 800x600 | Still terrible — same download |
800x600 JPEG, width="800" |
120 KB | 800x600 | Good |
800x600 WebP, width="800" |
65 KB | 800x600 | Great |
srcset with 4 sizes, WebP |
25-120 KB (varies) | Responsive | Best — right file for each device |
The bottom row is the target: combine srcset (or <picture>) with properly sized, compressed source files. Each device downloads only the bytes it needs.
This is especially critical for Largest Contentful Paint (LCP). If your hero image is the LCP element — and it usually is — every kilobyte of unnecessary data delays your most important Core Web Vital. For a full rundown, see our image SEO optimization guide.
Frequently Asked Questions
Does setting width and height in HTML compress the image?
No. width and height attributes only control the display size — how many CSS pixels the image occupies on the page. The browser downloads the full original file regardless. To reduce the actual data transferred, resize and compress the source file before uploading.
What is the difference between width/height attributes and CSS width/height?
HTML attributes set the intrinsic size hint. The browser uses them to reserve space in the layout and prevent layout shift. CSS properties control the rendered size and can be responsive (percentages, max-width, media queries). Use both: HTML attributes for layout stability, CSS for responsive behavior.
Should I use srcset or the picture element?
Use srcset + sizes when serving the same image at different resolutions (the common case). Use <picture> when you need format switching (AVIF/WebP/JPEG fallback) or art direction (different crops per breakpoint). <picture> is a superset — it does everything srcset does and more, at the cost of more markup.
How do I make an image responsive without distortion?
Set max-width: 100% and height: auto in CSS. Include the correct width and height attributes on the <img> tag so the browser calculates the aspect ratio. The image will scale down with its container without stretching or squishing.
Is it bad to use inline styles for image sizing?
For one-off adjustments, inline styles are fine. For consistent patterns (thumbnails, hero images, card grids), move styles to a CSS class. The performance difference is negligible — the concern is maintainability. When you need to change every thumbnail from 200px to 250px, a class makes that one edit instead of fifty.
What image dimensions should I use for the web?
It depends on how the image is displayed. A full-width hero on a 1920px-wide layout needs a source file of at least 1920px (or 3840px for Retina). A 300px-wide thumbnail needs only 600px at most. The rule: export at 2x the CSS display size to look sharp on high-DPI screens, then let srcset serve 1x files to standard screens. For platform-specific sizes, check our website image size guide.
Wrapping Up
Making an image smaller in HTML is really two jobs: controlling how it renders and controlling how much data it costs. The HTML and CSS methods (attributes, max-width, srcset, <picture>) handle rendering. Compression and resizing handle file size.
For the fastest pages, do both. Resize and compress your images to the dimensions each breakpoint actually needs, then use srcset or <picture> to serve the right version to each device. Your visitors get sharp images. Your server sends fewer bytes. Everybody wins.
Try it yourself
Resize to exact dimensions for any platform — free, instant, no signup. Your images never leave your browser.