Hello, I'm Maneshwar. I'm working on FreeDevTools online currently building *one place for all dev tools, cheat codes, and TLDRs* — a free, open-source hub where developers can quickly find and use tools without any hassle of searching all over the internet.
If you’ve run a Lighthouse or PageSpeed Insights test and saw those yellow or red warnings like “LCP needs improvement” or “TBT is too high”, you’re not alone.
Even with fast frameworks like Astro and clean design systems like Tailwind CSS, performance issues can creep in.
This post breaks down the five key Core Web Vitals — what they mean, why they matter, and how to fix them in a typical Astro setup with Tailwind and Google Fonts.
1. Largest Contentful Paint (LCP)
What it means:
LCP measures how long it takes for the largest visible element — often your hero image, banner, or big headline — to load.
If it’s slow, visitors feel like your site is sluggish, even if other parts are ready.
Metric | Good | Needs Improvement | Poor |
---|---|---|---|
LCP | ≤ 2.5s | 2.5–4.0s | > 4.0s |
Common causes:
- Large or unoptimized hero images
- Slow-loading fonts or render-blocking CSS
- Uncached assets or no preloading
Fixes:
- Serve images in WebP or AVIF formats instead of PNG/JPEG.
<img src="/hero.webp" width="800" height="400" loading="eager" decoding="async" alt="Hero" />
- Preload the hero image so the browser fetches it early:
<link rel="preload" as="image" href="/hero.webp" />
-
Use Astro’s
<Image />
component for automatic optimization:
---
import { Image } from "astro:assets";
import hero from "../assets/hero.webp";
---
<Image src={hero} alt="Hero image" width={800} height={400} loading="eager" />
- Host Google Fonts locally to remove an external render-blocker (details later).
2. Interaction to Next Paint (INP)
What it means:
INP measures how quickly your site reacts when users interact — clicking buttons, typing in forms, etc.
High INP = laggy site.
Metric | Good | Needs Improvement | Poor |
---|---|---|---|
INP | ≤ 200ms | 200–500ms | > 500ms |
Common causes:
- Too much JavaScript blocking interactivity
- Over-hydration in Astro components
- Unoptimized animations or scroll handlers
Fixes:
- Use Astro Islands wisely. Only hydrate components that need it:
<Counter client:load /> <!-- avoid client:load on full pages -->
- Defer non-critical scripts:
<script src="/analytics.js" defer></script>
- Remove unnecessary JavaScript dependencies. For example, use native date or string methods instead of importing large libraries.
- Avoid heavy animations tied to scroll or mouse events.
Astro helps a lot here because it ships zero JS by default. Just don’t break that advantage by hydrating everything.
3. Cumulative Layout Shift (CLS)
What it means:
CLS tracks how much your layout “jumps around” as elements load.
It’s about visual stability.
If a user is about to click a button but the layout shifts, that’s bad UX.
Metric | Good | Needs Improvement | Poor |
---|---|---|---|
CLS | ≤ 0.1 | 0.1–0.25 | > 0.25 |
Common causes:
- Missing width/height attributes on images
- Fonts loading late and causing text jumps
- Lazy-loading banners or popups appearing suddenly
Fixes:
- Set width and height for all images:
<img src="/logo.svg" width="120" height="40" alt="Logo" />
-
Add
font-display: swap
to Google Fonts:
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
- Reserve space for embeds or popups using min-height or aspect ratios.
- Use transitions for any delayed elements (like cookie banners) to avoid abrupt shifts.
4. First Contentful Paint (FCP)
What it means:
FCP measures how long it takes for the browser to show any visible content — like text or a background color.
A slow FCP means your site “feels” blank for too long.
Metric | Good | Needs Improvement | Poor |
---|---|---|---|
FCP | ≤ 1.8s | 1.8–3.0s | > 3.0s |
Common causes:
- Blocking CSS or fonts
- No preconnect for Google Fonts
- Unoptimized critical rendering path
Fixes:
- Preconnect to Google Fonts early:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
- Host fonts locally (no external calls):
npm install @fontsource/inter
import "@fontsource/inter/400.css";
import "@fontsource/inter/700.css";
- Inline critical CSS (Astro already does this). Avoid big global imports or unnecessary Tailwind plugins.
- Enable caching and compression on your server (gzip or Brotli).
5. Total Blocking Time (TBT)
What it means:
TBT measures how long your main thread is blocked by scripts or heavy computations, affecting how soon the page becomes usable.
Metric | Good | Needs Improvement | Poor |
---|---|---|---|
TBT | ≤ 200ms | 200–600ms | > 600ms |
Common causes:
- Large JavaScript bundles
- Blocking third-party scripts
- Heavy computations on load
Fixes:
- Lazy-load non-essential components:
<Gallery client:visible />
- Defer all analytics or external scripts.
<script async src="https://www.googletagmanager.com/gtag/js?id=GA-ID"></script>
- Split code intelligently using Astro’s default Vite bundling. Remove any unneeded client-side libraries.
- Optimize images and avoid base64-encoding large files directly in HTML.
Wrapping Up
Core Web Vitals directly affect SEO, user experience, and conversion rates.
The beauty of Astro is that it’s designed for performance — but small details like how you load fonts, hydrate components, and serve images make a big difference.
If you fix these five areas — LCP, INP, CLS, FCP, and TBT — you’ll see not just better Lighthouse scores, but a visibly faster and smoother experience for every visitor.
I’ve been building for FreeDevTools.
A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction in searching tools/materials.
Any feedback or contributors are welcome!
It’s online, open-source, and ready for anyone to use.
👉 Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools
Top comments (0)