Skip to content
trending

Guides

121 Core Web Vitals Tests Rejected My Two Best Hypotheses

Concatenating CSS worsened TBT from 76 to 372 ms. Deferring AJAX from 64 to 265 ms. The real culprit was the ad stack. Report from 9 measurement series.

By 5 min read
121 Core Web Vitals Tests Rejected My Two Best Hypotheses

👁 112 reads

I spent several days optimizing this site, running a series of Lighthouse measurements after each change instead of a single run. The result was humbling: two of my best hypotheses turned out to be harmful, and I only found the real culprit when I stopped trusting single results. 121 measurements across nine series. Here’s what came out of them.

Three Conclusions in One Paragraph

1. A single Lighthouse measurement means nothing - the same URL gave me results from 60 to 96 points without any code changes. 2. Concatenating CSS files into one, advice from every tutorial, worsened TBT from 76 to 372 ms. 3. The culprit behind the variance wasn’t my code, but the ad stack - after blocking ad domains, the score stabilized at 77/77 with FCP variance at 0.7% instead of 22%.

Current AI Courses List

Compilation automatically refreshed once a day: prices, number of lectures and ratings straight from the seller’s catalog. New releases and bestsellers on top.

Open compilation →

Rule Zero: Measure a Series, Not a Single Run

This sounds trivial, but almost nobody does it - and that’s why almost all “optimizations” on the internet are random chance.

I ran Lighthouse ten times in a row on an unchanged URL. The results ranged from 60 to 96 points. If I had changed anything in the code and gotten a 96 run after the change and 60 before, I would have declared success. If it came out the other way, I would have rolled back a good fix.

Pro tip: minimum five runs per variant, compare medians and always report the full range. If the ranges before and after overlap, you don’t have a result - you have noise.

Hypothesis 1, Rejected: Concatenating CSS into One File

Classic advice: fewer HTTP requests, so combine stylesheets. I built a bundle from several theme CSS files, checked relative path correctness and import order, deployed it. Measurement:

Metric on post page Before After concatenation
TBT (main thread blocking) 76 ms 372 ms
styleLayout time 700 ms 1018 ms

Why it didn’t work: five separate stylesheets are five short parsing tasks that the browser can interleave with others. One 69 KB stylesheet is one long task that can’t be interrupted - and long tasks are exactly what TBT measures. I reduced the number of requests and worsened the perception of smoothness.

Pro tip: with HTTP/2, the number of requests stopped being a problem. Concatenating files is advice from the HTTP/1.1 era and today it can hurt.

Hypothesis 2, Rejected: Deferring Background Requests

The shop page sent several AJAX requests at startup. I deferred them using requestIdleCallback with a 3000 ms timeout - a textbook solution. Measurement:

  • Shop TBT: 64 ms → 265 ms
  • Request start shifted from 183-1329 ms range to 383-2411 ms

Why it didn’t work: the 3000 ms timeout caused the browser to fire all deferred requests in one batch - and precisely in the window where TBT is counted. Instead of spreading the work, I collected it into one bottleneck.

Pro tip: requestIdleCallback with a short timeout isn’t “do this later”. It’s “do this later, but definitely”. Without a timeout or with a very long one, it behaves differently.

What Worked and Why

One Line That Eliminated 70 ms of Forced Layout Recalculation

A script read an element’s position and immediately changed it. This causes forced layout recalculation - the browser must interrupt everything and calculate page geometry. Lighthouse indicated 70-75 ms in one line.

The fix is one line:

if (window.requestAnimationFrame) requestAnimationFrame(miejsce); else miejsce();

The read moves to a moment when the browser is recalculating layout anyway. The cost drops to zero, and the code does exactly the same thing.

Removing from Critical Path What the Page Doesn’t Use

The template stylesheet weighed 75,094 bytes and loaded on every subpage, even though most pages don’t use any of those templates. The basic version is 9,708 bytes - meaning 87% of the weight was wasted. Similarly jQuery, loaded despite having no consumer whatsoever.

Pro tip: before you start minifying, check whether the file is even needed on that page. Removal beats compression every day.

The Real Culprit: The Ad Stack

After rejecting both hypotheses, I asked a different question: where does the 60-96 point variance come from. I blocked ad and consent domains and repeated the series:

With ads Without ads
Performance score 60-96, bimodal stable 77/77
FCP variance 22% 0.7%
TBT variable 0
Stack weight 445-467 KB

The conclusion was brutal: for several days I optimized code that accounted for a fraction of the problem. The variance came from external scripts I have no control over and can’t remove because they finance the site.

Pro tip, most important in this entire text: before you optimize anything, measure how much of the result comes from you versus external scripts. Do a series with third-party domains blocked. If the difference is large, your real ceiling is much lower than you think - and it’s better to know this before three days of work than after.

Two Tool Traps I Hit Along the Way

Pingdom Can Lie About Compression

The report claimed the server doesn’t compress responses. I checked directly: the server sends br and zstd, and when asked explicitly for gzip, returns the homepage in 71,306 bytes instead of 289,394 uncompressed. The tool simply didn’t declare support for newer algorithms. Expiration headers were also in place.

Clearing Entire Cache Can Break Appearance

A plugin cleared the entire cache on every publication including minified CSS files. In the window between deletion and rebuild, the page linked to a stylesheet that didn’t exist - and for a moment displayed as bare HTML. With a dozen posts per day, this happened regularly.

Pro tip: after publishing a post, clear selectively - the post itself, homepage, its categories and RSS feed. A new article doesn’t change CSS file content, so there’s no reason to delete it.

Checklist If You Want to Repeat This Yourself

  1. Do ten measurements on an unchanged page. Record the median and range. This is your noise.
  2. Repeat the series with external domains blocked. The difference is the ceiling of your possibilities.
  3. Only now change one thing at a time and measure with a series, not a single run.
  4. If the ranges before and after overlap - roll back the change. Lack of evidence is not evidence.
  5. Start with removal, not minification. A file that doesn’t exist is always fastest.
  6. Look for forced layout recalculations. They can be worth 70 ms for one line of fix.
Google · Your sourcesQuantslant higher in your Google - one clickAdd to preferred sources →

Where These Numbers Come From

All values come from 121 Lighthouse measurements across nine series, performed on this site on September 18-19, 2026 on four page types: homepage, post, review and shop. Both rejected hypotheses were deployed to production, measured and rolled back. This is not a compilation of others’ advice - this is a report of what worked for me and what didn’t.

Kinetyra

// read next

More on this from QUANTSLANT

Piotr Olszewski

Editor and publisher · Quantslant

I edit and publish Quantslant. AI tools help with research, drafts and translation; choosing topics, running the tests, checking facts and the decision to publish are mine, and so is the responsibility for what appears here.

read nextAI Model Refuses to Read Documents: Testing Three ProvidersbenchmarksAI Model Refuses to Read Documents: Testing Three ProvidersA context test revealed content_filter triggers for every document above ~2000 tokens across AWS, the producer, and Google - even for text about plants.

Most read

  1. 1Best AI Video Generator Apps for Your Phone (2026)
  2. 2Claude Opus 5.5 Motion Graphics: 60s Showreel from One Prompt
  3. 3Wan 2.2 on RTX 4090: timings, VRAM and four test clips
// site map

This page in other languages6

Quantslant in numbers 1,423posts in archive22news from the last 7 days18video models in the observatory
🎬 AI Video Benchmarks: Higgsfield DoP vs OpenAI Sora • Higgsfield vs Runway Gen-3 • AI Video Credit Calculator
× ‹ enlarge ›