Why Your Website Is Slow and How to Fix It
Images account for 50% of most web pages. Here's how I cut my site's load time from 6 seconds to under 2 seconds with free tools.
I logged into Google Search Console on a Tuesday morning and saw something ugly. My site’s average load time had crept up to 6.3 seconds on mobile. My impressions were holding steady but clicks had dropped 18% over the past month. Google was showing my pages less because they were too slow.
I panicked a little. Then I opened PageSpeed Insights and ran my homepage. The diagnosis was clear within seconds.
Images are your biggest bottleneck
The average web page weighs about 2.5MB. Images account for roughly 1.5MB of that. Over half the data your visitors download is just pictures.
My homepage was worse than average. I had a hero photo that was 1.8MB on its own. Three product screenshots at 900KB each. A handful of icons and thumbnails that added another 600KB between them. Total image weight: just over 5MB. For a single page.
The thing is, none of those images needed to be that big. Not even close. My hero banner displays at 1200 pixels wide. I was uploading 5000-pixel JPEGs from my camera and letting CSS shrink them down. The browser still had to download every single pixel.
Step one: run the diagnosis
Before you change anything, measure. Open PageSpeed Insights and plug in your URL. Pay attention to two things.
First, your Largest Contentful Paint. That’s the metric Google uses to measure how long it takes for the biggest thing above the fold to show up. On my site that LCP element was my hero image. It was taking 4.8 seconds to load on a simulated mobile connection. Awful.
Second, look at the “Opportunities” section. PageSpeed will tell you exactly which images are too big and how much you’d save by compressing them. For me it listed seven images with a potential savings of 4.2MB. That was my roadmap.
Fix one: compress your images
This was the biggest win by far. I took every image on my homepage and ran it through the ImgPrism compressor. One file at a time, maybe two minutes total.
The hero image went from 1.8MB to 180KB at 80% quality. I opened both versions side by side and zoomed to 200%. I genuinely could not see a difference. That one change shaved 1.6MB off my page weight.
I did the same for the three product screenshots. Each one went from roughly 900KB down to about 110KB. Total savings from compression alone: 3.9MB.
My rule of thumb now is 80% quality for photos and 75% for screenshots. If it’s a background texture or pattern tile where nobody’s looking closely, 65% is fine. Start at 80 and adjust down until you notice something wrong, then go back up one notch.
Fix two: convert to WebP
JPEG has been the default for photos since the 90s. It’s fine. But WebP is better for the web in almost every case. A WebP file at the same visual quality as a JPEG is typically 25 to 35% smaller.
After compressing my images, I converted them all to WebP. The hero image that I’d just gotten down to 180KB dropped to 130KB. Same visual quality. Another 50KB gone.
My three product screenshots went from 110KB each to about 78KB each. The savings add up when you have multiple images on a page.
WebP support is universal now. Chrome, Firefox, Safari, Edge. Even Samsung Internet handles it. If you’re still serving JPEGs in 2025, you’re leaving file size savings on the table for no reason.
Fix three: serve the right dimensions
This was the dumbest mistake I was making, and it’s probably the most common one. My blog layout shows images at 800 pixels wide. My product page uses 1200-pixel images. But I was uploading everything at 4000 to 5000 pixels and relying on width: 100% in CSS to make them fit.
The browser downloads the full file first, then resizes it for display. That 5000-pixel image displaying at 800 pixels still costs the visitor 1.8MB of data transfer.
I started resizing every image to match its display size before uploading. Hero banners get 1200 pixels wide. Blog post images get 800 pixels. Thumbnails get 400 pixels. Nothing goes up at full camera resolution anymore.
The math is brutal. A 5000x3000 JPEG and an 800x480 JPEG of the same photo at the same quality setting can differ by a factor of 10x in file size. Ten times smaller just from resizing. Do this before you compress for the best results. Fewer pixels means less data to squeeze.
Fix four: add lazy loading
Images below the fold don’t need to load immediately. Lazy loading tells the browser to wait until the user scrolls close to an image before downloading it. If someone bounces after reading the first paragraph, they never download the images at the bottom of the page.
You can enable this in plain HTML. Just add loading="lazy" to your image tags:
<img src="photo.webp"
alt="Description of the image"
loading="lazy"
width="800"
height="600">
Two things to notice here. The loading="lazy" attribute does the actual lazy loading. But the width and height attributes matter too. They tell the browser how much space to reserve for the image before it loads, which prevents the page from jumping around as images pop in. That jumping is called Cumulative Layout Shift, and Google penalizes you for it.
My CLS score dropped from 0.24 to 0.03 after I added dimensions to every image tag. Took maybe five minutes.
What the numbers looked like after
I ran PageSpeed Insights again after making all four changes. Here’s the full comparison.
| Core Web Vitals Metric | Before | After | Improvement |
|---|---|---|---|
| Largest Contentful Paint | 4.8s | 1.4s | -3.4s |
| First Contentful Paint | 2.1s | 0.8s | -1.3s |
| Cumulative Layout Shift | 0.24 | 0.03 | -0.21 |
| Total Blocking Time | 380ms | 110ms | -270ms |
| PageSpeed score (mobile) | 38 | 91 | +53 |
Total image weight on my homepage went from 5.1MB to 380KB. The page loads in under 2 seconds on a simulated 4G connection now. That’s faster than 87% of sites in Google’s CrUX data for my niche.
The 270ms improvement in Total Blocking Time was a bonus I didn’t expect. Turns out decoding a 5000-pixel JPEG takes a lot of CPU. When I switched to properly sized WebP files, the browser spent way less time parsing image data, which freed up the main thread for actual page rendering.
Two more things worth doing
A CDN helps if your audience is spread across different regions. I use Cloudflare’s free tier and it knocked another 200ms off my Time to First Byte for visitors outside the US. Takes about ten minutes to set up if your DNS is already pointing at the right place.
Browser caching is the other easy win. Tell the browser to store your images locally so returning visitors don’t download them again. If you’re on Apache, add this to your .htaccess:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
</IfModule>
One year is fine for images that rarely change. If you update an image, just change the filename and the browser treats it as new.
Tools and further reading
Everything I did here used free browser-based tools. No accounts, no server uploads, no waiting in queues.
- Compress images to cut file sizes by 70 to 90%
- Resize images to the exact dimensions your layout needs
- Convert to WebP for the smallest possible files
If you want more background on why format choice matters, I wrote a JPEG vs PNG vs WebP comparison with real test numbers. For a full walkthrough of the optimization process, my image optimization guide covers the complete checklist.
Six seconds to two seconds. No server upgrades, no paid tools, no code changes beyond a couple of HTML attributes. Just treating images like they actually matter for performance. Because they do.