How I Cut 39 KB of HTML From Every Page on My WordPress Site

Imdad Khan Author
9 min read
Share
How I Cut 39 KB of HTML From Every Page on My WordPress Site

My homepage was 694 KB of HTML. Not images, not scripts — the HTML document itself, before a single asset loaded. A site audit flagged 85 pages with a low text-to-HTML ratio and I went looking for the cause.

The fix everyone reaches for first is the caching plugin’s optimisation toggles, and on a site like mine that would have broken things. This is what I found when I measured instead of guessing, which options I deliberately left switched off, and how I removed 39 KB from every page on the site without changing a single pixel.

Homepage before694 KB of HTML
Inline CSS416 KB in 37 blocks
Removed per page39 KB
Pages affectedAll 174

Measure before you touch anything

“The page is too big” is not actionable. What is in it is actionable, and you can find out in about a minute by fetching the page and counting what each type of tag contributes.

On my homepage the answer was blunt:

ComponentCountSize
Inline <style> blocks37416 KB
Inline <script> blocks56132 KB
Inline SVG24462 KB
External script tags234 KB
Link tags335 KB

Inline CSS was 60% of the document. Everything else was noise by comparison, and any effort spent on images or scripts would have been effort spent in the wrong place.

Breaking it down further, the largest single block was my theme’s dynamic CSS at 84 KB, with another 20 KB from its addon. But the next biggest contributors were mine — a site-wide navigation stylesheet at 16 KB and a footer stylesheet at 23 KB, both printed inline, both identical on every one of the 174 pages, and both re-downloaded on every single page view because inline CSS cannot be cached.

The useful realisation: the biggest single block belonged to the theme and I could not safely touch it. The second and third biggest belonged to me and I could fix them completely. Always check how much of the problem is yours before you start editing things you did not write.

The options I deliberately left switched off

My caching plugin already had CSS minify, JS minify and HTML minify enabled. The page was still 694 KB, which tells you something important: minification was never the problem. The bytes were real content, not whitespace.

The tempting next step is the aggressive optimisation set. I left all of it off, on purpose:

Remove Unused CSS. This generates a per-page stylesheet containing only the rules it thinks the page needs. On a site with 46 interactive tools, where elements are created by JavaScript after the page loads, “unused” is a guess the tool cannot make correctly. Rules for elements that do not exist yet look unused right up until the moment they are needed.

Combine JavaScript. Merging separate scripts into one file changes execution order and scope. On a site where several tools each carry their own logic, this is one of the most reliable ways to break something in a way that only shows up on one page, days later.

Asynchronous CSS with critical CSS generation. Defers your stylesheet and inlines a generated “above the fold” subset. When it works it is excellent. When the generator misjudges, visitors get a visible flash of unstyled content on first load.

None of these are bad features. They are aggressive features, and the more custom JavaScript a site runs, the worse the odds. If your site is a straightforward blog they are usually fine. Mine is not, so the honest answer was to solve the problem a different way.

The fix: cache what repeats

Inline CSS has one unavoidable property — it is downloaded again with every page. An external stylesheet is fetched once and served from browser cache for every page after. For CSS that appears on all 174 pages, that difference is the entire argument.

So the approach was to move my own site-wide CSS into a cached file. The part worth copying is not the idea, it is how to do it without any risk of breaking the site.

The rule I built it around: never remove the inline copy until the replacement is confirmed present.

The process runs in two passes. On the first render, the code finds the inline block, writes its contents to a file named after a hash of the CSS, and records it — but changes nothing on the page. On every render after that, a link to the cached file is printed in the head, and only once that link is confirmed in the output does the inline block get stripped.

That ordering makes the failure modes harmless. If the file cannot be written, no link appears, nothing is stripped, and the page renders exactly as before. If the file is later deleted, the link disappears, the stripping stops, and the inline CSS comes back on its own. Hashing the contents means editing the CSS produces a new filename automatically, so there is no cache to clear and no stale styles.

I also added an escape hatch — appending ?hn_no_extcss=1 to any URL bypasses the whole thing — which turned out to matter more than I expected.

The escape hatch earned its keep immediately

After deploying, I scrolled to the bottom of the homepage and saw a large blank area below the footer. My first instinct was that I had broken the layout.

Instead of guessing, I loaded the same page twice — once normally, once with the bypass parameter — and measured the rendered height of both.

They were identical: 15,476 pixels each way. The blank area was pre-existing over-scroll and had nothing to do with my change. Without that bypass I would have spent an hour reverting a change that was working correctly.

Build the off switch before you need it. A one-line bypass turns “did I break this?” from an investigation into a measurement.

Where the homepage weight actually came from A chart showing inline CSS at 416KB dominated the 694KB homepage, followed by inline scripts at 132KB, inline SVG at 62KB and much smaller contributions from link and external script tags. 694 KB homepage, by component Inline CSS 416 KB — 60% of the document Inline scripts 132 KB Inline SVG 62 KB Link tags 5 KB External scripts 4 KB
Optimising images or scripts here would have been effort spent on the bottom two rows.

The result, and what it is honestly worth

39 KB came off every page. The homepage went from 694 KB to 655 KB, and lighter pages dropped proportionally more — a product page went from 327 KB to 288 KB, around 12%.

An unexpected bonus: the caching plugin noticed the new external files and began minifying and serving them through its own optimiser, so they got smaller again without any further configuration.

Now the honest part. 39 KB is not a dramatic number, and the low text-to-HTML ratio warning that started this is a soft signal with no direct ranking impact. If you are chasing that specific audit warning, this is not where your time is best spent.

The real benefit is caching. That 39 KB was previously re-downloaded on every page view by every visitor. It is now fetched once. For someone reading three articles, that is 78 KB saved rather than 39, and it comes out of the render path where it matters most.

And the homepage is still 655 KB. My theme’s 104 KB of inline CSS is untouched, because I could not find a documented, reversible way to move it and guessing at theme options on a live site is how you spend an evening restoring a backup.

Worth doing

  • Measure the document composition before changing anything
  • Find out how much of the weight is your own code
  • Move repeated site-wide CSS into a cached file
  • Hash the filename so edits invalidate automatically
  • Build a bypass parameter before you deploy

Approach with caution

  • Remove Unused CSS on any JavaScript-heavy site
  • Combining JavaScript files
  • Automatic critical CSS with deferred stylesheets
  • Editing theme options you cannot easily reverse
  • Assuming minification will fix a large document

Most of that HTML came from the tool pages — what went into building 46 browser-based tools explains why. For the wider check that surfaced the problem, see how to do an SEO audit.

Frequently asked questions

Does a low text-to-HTML ratio hurt rankings?
Not directly. It is a soft signal that audit tools report, and it can point at real bloat worth fixing. Chasing the number itself is not a good use of time; reducing genuine page weight for speed is.
Why not just enable Remove Unused CSS?
On a mostly-static blog it is often fine. On a site where JavaScript creates elements after load, the tool cannot know which rules will be needed, and the styles that go missing are exactly the ones for interactive parts. I left it off deliberately.
Is inline CSS always bad?
No. A small critical block inline is a legitimate technique. The problem is large stylesheets repeated on every page, because inline CSS can never be cached — each page view downloads it again.
How do I check what is actually in my HTML?
Fetch the page and total up the characters inside each tag type. A few lines in the browser console will do it. You are looking for which component dominates, and the answer is often not what you expect.
What if the cached file fails to write?
In the approach described here, nothing happens — no link is printed, so the inline copy is never removed and the page renders as before. That ordering is deliberate: the fallback is always the working state.
Was 39 KB per page worth the effort?
For the audit warning, no. For repeat visitors it is worth more than the number suggests, because it moves from re-downloaded on every view to fetched once. Set expectations accordingly.

The short version

Measure the document before you touch a setting. On my site 60% of a 694 KB homepage was inline CSS, and the parts I could safely fix were my own, not the theme’s. Moving repeated site-wide styles into a hashed, cached file removed 39 KB from all 174 pages with no visual change, while the aggressive caching options that would have “fixed” it faster stayed off — because on a site running 46 interactive tools, those are the ones that break things quietly.

How this article was made

All figures come from this site during August 2026 — the 694 KB homepage, the component breakdown, the 39 KB saving and the identical 15,476 pixel page heights are measurements taken here, and the approach described is running in production. I have not tested Remove Unused CSS or JavaScript combination on this site, so my caution about them reflects how they interact with heavy client-side JavaScript in general rather than a measured failure of my own. On a simpler site they may well work fine.

Was this article helpful?
Scroll to Top