How to Improve Lighthouse Scores Without Breaking Your Site (2026)

Improving Lighthouse scores starts with fixing real user metrics, not chasing 100. Compress and properly size your LCP image, defer non-critical JavaScript, and set explicit width and height on media to stop layout shift. Check Search Console field data too, since lab scores and real Core Web Vitals often disagree.
Part of the complete web design guide.
On this page
- Understand what Lighthouse is actually measuring
- The metrics that matter in 2026
- Fix LCP first. It’s almost always an image or a render-blocking resource.
- Don’t lazy-load your hero image
- Serve the right format at the right size
- Fonts: the silent LCP killer
- JavaScript is where INP goes to die
- Audit your third parties
- CSS: less blocking, more containment
- What not to do
- A realistic workflow
- FAQ
- Do Lighthouse scores affect Google rankings directly?
- Why is my Lighthouse score different every time I run it?
- Can I fix all of this with a plugin or a CDN?
Lighthouse is a diagnostic tool, not a scoreboard. Chasing a perfect 100 usually means you optimize for Google’s test environment instead of actual visitors, and you can easily make a site worse in the process. Here’s what actually moves the numbers in 2026, and what to skip.
Understand what Lighthouse is actually measuring
Lighthouse runs a headless Chrome instance, throttles the network and CPU, loads your page, and reports on a handful of categories. The performance score is a weighted blend of lab metrics. Those metrics are not the same as the field data Google uses for ranking, which comes from the Chrome User Experience Report (CrUX) and shows up in Search Console under Core Web Vitals.
So you can pass Lighthouse with flying colors and still fail Core Web Vitals, or vice versa. Always check both. If your Search Console CWV report is green but Lighthouse is red, you probably don’t have a real problem. If the reverse is true, you do.
The metrics that matter in 2026
- LCP (Largest Contentful Paint): target under 2.5s. Usually an image or a big text block.
- INP (Interaction to Next Paint): replaced FID in March 2024. Target under 200ms. This is about how long the browser takes to respond to clicks and taps.
- CLS (Cumulative Layout Shift): target under 0.1. Things jumping around while the page loads.
TTI and TBT still show up in Lighthouse but they’re lab-only proxies. Don’t over-optimize for them.
Fix LCP first. It’s almost always an image or a render-blocking resource.
Nine times out of ten on a small business site, LCP is a hero image that’s either huge, lazy-loaded when it shouldn’t be, or not discoverable early enough by the browser.
Don’t lazy-load your hero image
This is the single most common mistake I see. loading="lazy" on the LCP image tells the browser to wait until layout to even start fetching it. Remove it, and preload the image instead.
<link rel="preload" as="image" href="/img/hero.avif" fetchpriority="high">
<img src="/img/hero.avif" width="1600" height="900"
alt="Storefront on Main Street" fetchpriority="high">
Set explicit width and height attributes on every image. That alone fixes most CLS. The browser reserves the correct space before the image loads.
Serve the right format at the right size
AVIF and WebP are both well supported now. Serve AVIF first, WebP as fallback, and a JPEG as the last resort. Don’t ship a 2400px wide image to a 400px phone.
<picture>
<source srcset="/img/hero.avif" type="image/avif">
<source srcset="https://i0.wp.com/www.kennykey.com/img/hero.webp" type="image/webp">
<img src="https://i0.wp.com/www.kennykey.com/img/hero.jpg" width="1600" height="900" alt="Storefront">
</picture>
If you use a CDN with image resizing (Cloudflare Images, imgix, Cloudinary, or even WordPress with a decent image plugin), let it handle the resizing and format negotiation. You’ll get better results than hand-exporting files.
Fonts: the silent LCP killer
Custom fonts block text rendering. Two changes fix this:
- Use
font-display: swapso text renders immediately in a fallback font. - Preload the font file if it’s above the fold.
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
}
<link rel="preload" href="/fonts/inter.woff2" as="font"
type="font/woff2" crossorigin>
If you can get away with a system font stack, do it. Zero network requests, zero layout shift. For a lot of small business sites, that’s the right call.
JavaScript is where INP goes to die
INP measures how long the browser takes to respond to a user interaction. If you have a big third-party script (chat widget, analytics suite, marketing pixels) running on the main thread, every click feels laggy.
Audit your third parties
Open DevTools, go to the Coverage tab, and look at how much JavaScript you’re shipping that never executes. Then look at the Network tab and count how many requests come from domains you don’t control. Chat widgets and tag managers are the usual suspects.
Fix it by:
- Deferring non-critical scripts with
deferorasync. - Loading chat widgets on first interaction instead of on page load.
- Removing pixels you’re not actually using. Every agency that’s ever touched the site probably added one.
<script defer src="/js/app.js"></script>
<!-- Load chat only when the user shows intent -->
<script>
const loadChat = () => {
const s = document.createElement('script');
s.src = 'https://chat.example.com/widget.js';
s.async = true;
document.head.appendChild(s);
window.removeEventListener('scroll', loadChat);
window.removeEventListener('mousemove', loadChat);
};
window.addEventListener('scroll', loadChat, { once: true, passive: true });
window.addEventListener('mousemove', loadChat, { once: true, passive: true });
</script>
CSS: less blocking, more containment
Your stylesheet blocks rendering. If it’s 300KB of unused framework CSS, that’s a real cost. Two things help:
- Inline critical above-the-fold CSS in the
<head>, load the rest async. - Break large stylesheets into smaller ones so the browser only downloads what that page needs.
If you’re on a framework like Tailwind, you already have this mostly handled via purging. If you’re on a bloated WordPress theme with three page builders stacked on top of each other, that’s usually a bigger project, and honestly, sometimes rebuilding is cheaper than untangling it. If you’re weighing that tradeoff, working with someone who does Long Island web design day to day means you’ve probably seen which themes are worth saving and which aren’t.
What not to do
- Don’t chase a 100. A 92 and a 100 are functionally identical to users and to Google.
- Don’t use Lighthouse’s simulated throttling as gospel. It’s a lab estimate, not reality.
- Don’t inline everything. Inlining 500KB of CSS to save a request is a net loss on repeat visits.
- Don’t blindly install a “Lighthouse fixer” plugin. Most of them just defer scripts and call it a day.
- Don’t optimize on your fiber connection. Test on real throttled mobile, or use WebPageTest with a real device profile.
A realistic workflow
- Run Lighthouse on mobile with the default settings. Note the score, but ignore it.
- Look at the Opportunities and Diagnostics sections. Fix the two or three biggest items.
- Re-run. Then check Search Console’s Core Web Vitals report a few weeks later for field data.
- Repeat quarterly. Sites drift as you add scripts and content.
That’s it. No magic plugin, no secret trick. Just the same handful of problems on almost every site, fixed properly.
FAQ
Do Lighthouse scores affect Google rankings directly?
No. Google uses field data from real users (Core Web Vitals via CrUX) as a small ranking signal. Lighthouse is a lab tool that helps you find problems. Fixing the underlying issues helps both, but the score itself isn’t a ranking factor.
Why is my Lighthouse score different every time I run it?
Lighthouse uses simulated throttling and runs against a single cold load. Network variance, third-party scripts, and A/B tests all change results run to run. Treat the score as a range, not a fixed number, and focus on the specific audits rather than the total.
Can I fix all of this with a plugin or a CDN?
A CDN with image optimization and a caching layer handles a good chunk of it (LCP, some TTFB). But CLS from missing image dimensions, INP from heavy third-party JS, and render-blocking CSS are code-level problems. No plugin fixes those for you.


