Why Your Website Is Slow, and What Actually Fixes It
Most slow websites are slow for four reasons, and heavy images are only one of them. What Core Web Vitals really measure, and the fixes that move the numbers.

Speed is three numbers, not one
"The site is slow" is a feeling. Before you can fix it you need to know which of three quite different things is actually happening, because they have different causes and different fixes.
Largest Contentful Paint (LCP) is how long until the biggest thing in the first screen appears. Usually that is a hero image or a headline. This is the number most people mean by slow.
Interaction to Next Paint (INP) is how long the page takes to respond when somebody taps something. A page can paint quickly and still feel broken if the first tap does nothing for half a second.
Cumulative Layout Shift (CLS) is how much the page moves around while loading. This is the one where you go to tap a link and an advert loads above it and you tap something else instead.
These are Google's Core Web Vitals, and they are worth caring about for the ordinary reason that they describe real frustration, and for the commercial reason that they are a ranking input. Measure them on a real page, not on your laptop on office wifi. Run the Website Health Checker against the live URL, and check the same page on a phone on mobile data.
Four things cause most of it.
Reason one: the images are too heavy
This is the common one and it is the easiest to fix, which is why it is also the one everybody has already half-fixed and then stopped.
The usual state of a business website is a hero image exported straight out of a design tool at 3000 pixels wide and 2 megabytes, displayed in a box 1200 pixels across. The browser downloads all of it and throws most of it away.
Three fixes, in order of return:
- Resize before you compress. No image needs to be wider than the largest box it will ever appear in. This alone usually removes more weight than every other technique combined. The widths to use, and why the order matters, are in preparing images for the web.
- Serve WebP. Use a
<picture>element with a WebP source and keep a JPEG fallback. On photographs the saving is routinely half the file size at the same visual quality. The WebP converter does this in your browser without uploading anything, and here is how to check whether a tool really works that way. - Compress to a budget, not to a slider. Decide that a hero is allowed 150KB and hit that. Compress image to size takes the target and works backwards, which is a much more useful way round than nudging a quality slider and guessing.
And lazy-load everything below the first screen, but not the hero. Lazy-loading the largest image in the first screen delays the exact thing LCP is measuring.
Reason two: the biggest thing on the screen is being animated
This one is invisible in every audit tool and it can cost you more than every image on the page. We know because we did it to ourselves.
The BitsSolved homepage opens with product screenshots. The first version faded them in on a staggered animation, about a third of a second, because it looked good. LCP on that page measured 1,588 milliseconds. We preloaded the images, which changed nothing at all, and that is the clue.
An element at opacity: 0 has not painted. As far as the browser is concerned it is not there yet. So the fade was not decorating the largest image, it was postponing it, and LCP was being pushed out by the full length of the animation no matter how fast the file arrived.
The fix was to stop fading the thing that holds the image and move it instead. Same entrance, same duration, transform: translateY(18px) to zero, opacity untouched. LCP fell to 60 milliseconds.
The rule that came out of it: whatever holds the largest image in the first screen may be transformed, but never faded. The text around it can fade all it likes. If your site has a hero animation and an LCP you cannot explain, this is the first thing to check, and it is a five minute change.
Reason three: the page waits for things it does not need yet
Every <script> in the head without defer or async stops the browser from building the page until that file has been fetched and run. Every stylesheet blocks rendering by design. Every font loaded from a third party domain adds a DNS lookup, a connection and a handshake before a single character can be drawn in the right typeface.
The compounding version of this is a site that loads a CSS framework from a CDN, an icon font from a second CDN, two web fonts from a third, and a tag manager that then loads four more things. Each is defensible on its own. Together they mean the browser spends the first second of the visit negotiating with five strangers.
What helps:
deferon every script that is not required to render the first screen.- Self-host your fonts, subset to the characters you use, and set
font-display: swapso text is readable while the real font arrives. - Stop loading a whole CSS framework from a CDN to use a tenth of it.
- Count your third-party scripts. Analytics, chat widget, heatmap, pixel, consent banner. Each one is a decision somebody made once and nobody has revisited.
Reason four: the server is slow before anything is downloaded
If the first byte takes 800 milliseconds, nothing you do in the browser will rescue the page. Common causes are shared hosting under load, a database query running on every page view with no caching, and a server physically far from your users. A site serving customers in Chennai from a data centre in Virginia is paying a round trip it does not need to.
This is the least glamorous category and often the highest return, because it is under the whole page rather than on top of it. It is also the one most likely to need someone in the infrastructure rather than in the markup, which is cloud and DevOps work.
What to measure, and what to ignore
Ignore the single overall score out of 100. It combines things you can change with things you cannot and encourages optimising for the number rather than for the visit.
Measure LCP, INP and CLS, on a real URL, on a phone. Then change one thing and measure again. Almost every genuinely fast site got there by removing things, not by adding techniques.
A reasonable order of work:
- Fix the hero. Resize it, convert it, stop fading it.
- Defer or delete scripts that are not needed for the first screen.
- Self-host the fonts.
- Then look at the server.
When it is worth rebuilding instead
Sometimes the honest answer is that the site cannot get there. A page carrying a page builder, six plugins that each inject their own CSS, and a theme nobody has the source for has a floor below which it will not go, and every hour spent is rent rather than progress.
The test we use is whether the fixes are landing. If two rounds of work have moved the numbers meaningfully, keep going. If they have not, the structure is the problem and you are paying to maintain the thing that is holding you back.
If you want an outside read on which of those you are in, that is what website fixes and maintenance is for: a real audit of the live site, and an honest continue-or-rebuild recommendation rather than an automatic quote for a rebuild.
Tools mentioned in this post
- Website Health CheckerOne scored report: uptime, SSL, DNS, speed, redirects, security headers, SPF and DMARC.
- Image CompressorCompress JPG, PNG and WebP images online, without uploading them to a server.
- Compress Image to Target SizeHit an exact file size: compress an image to 100 KB, 50 KB or any target you need.
- WebP ConverterConvert JPG or PNG to WebP, and WebP back to JPG or PNG, in your browser.


