# CSS Performance: What Slows a Page, and Critical CSS

See why a stylesheet holds up the first paint, find unused CSS with the Coverage panel, animate transform instead of layout, skip off-screen work with content-visibility, inline the critical CSS, and measure the result with Lighthouse.

Freelancer · CSS · Web Development · Updated November 1, 2026

## After this lesson you can

- Explain why a stylesheet blocks the first paint, and speed it up with critical CSS, fewer requests and smaller files
- Choose transform and opacity over layout properties for animation, and use content-visibility and will-change where they fit
- Measure a page's speed with Lighthouse, and find unused CSS with the Coverage panel

## Key takeaways

- A browser won't paint the page until it has downloaded every stylesheet linked in the head, so fewer and smaller stylesheets mean a faster first paint.
- The Coverage panel in Chrome and Edge shows how much of each stylesheet the page used, so you can find CSS that does nothing there.
- Animating width, top or margin makes the browser redo the layout on every frame. Animating transform and opacity doesn't, so it stays smooth.
- content-visibility auto lets the browser skip the work for sections that are off screen. Critical CSS inlines the first screen's styles so it shows sooner.
- Measure before and after every change with Lighthouse. Speed you can't measure is a guess.

Picture a Weekend Kitchen reader in the grocery store, phone in one hand and a basket in the other, with one bar of signal. They tap the link to the shakshuka recipe and stare at a white screen. Three seconds later, they give up and pick another recipe from somewhere else. Speed isn't a bonus on the web: people leave slow pages, and search engines count speed among the things that decide which pages they show first. CSS is one of the things that decides how fast a page appears, and how smoothly it moves once it's there.

This lesson is the advanced end of the course. You won't need every technique on a small site, so it ends with the most important habit of all: measure first.

## Why a stylesheet holds up the first paint

A restaurant kitchen doesn't send out a plate before the chef knows how it should be arranged, or every diner would get a pile of food followed by a rearranged plate. A browser does the same with CSS. It won't **paint**, meaning draw the page on screen, until it has downloaded and read every stylesheet linked in the `<head>`. If it painted first, the reader would see the page plain and unstyled, then watch it jump into shape. So a stylesheet is **render-blocking**: the page waits for it.

```html
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="print.css" media="print">
```

Every linked stylesheet is one more download before the first paint. The second line has `media="print"`, so the browser knows it's only for printing: it still downloads it, but doesn't wait for it. Two more habits help. Keep the number of files small, and avoid `@import` inside a stylesheet: the browser only finds out about the imported file after the first one arrives, so the downloads happen one after another instead of together.

## Smaller files, and the CSS nobody uses

A stylesheet's size matters most on a slow phone connection. Two things make it smaller. **Minifying** strips out the spaces, line breaks and comments that people need and browsers don't; tools do it as the site is built, so you keep writing readable CSS. And deleting **unused CSS** removes rules that match nothing on the page. A whole framework's stylesheet can be hundreds of kilobytes, and a page often uses a small part of it.

```css
.recipe-card{padding:1rem;border-radius:8px;background:#fffaf2}
```

That's one rule, minified. To find unused CSS, open the **Coverage** panel in Chrome or Edge: press **Ctrl+Shift+P** (Cmd+Shift+P on a Mac), type *coverage*, and choose **Show Coverage**. Click its reload button, and it lists each stylesheet with how many bytes the page used and how many it didn't. Click a file to see its lines marked: unused ones in red. Firefox has no Coverage panel.

Read "unused" carefully. It means unused on *this* page, in *this* state. A `:hover` rule, a phone layout's media query or the rules for another page show as unused too. Use Coverage to find big chunks worth a look, not to delete lines blindly.

## Animate transform, not layout

Each time something changes on a page, the browser may have up to three jobs to do:

- **Layout**: work out every box's size and place. Redoing it after a change is a **reflow**, and a change to one box can move every box after it.
- **Paint**: fill in the pixels, colors, text and shadows. Redoing it is a **repaint**.
- **Compositing**: stack the painted layers into the final picture, like sliding photos around on a glass table.

Animating `width`, `height`, `top`, `left` or `margin` changes the layout, so the browser reflows and repaints up to 60 times a second, and on a phone the motion stutters. Animating `transform` and `opacity` changes only the compositing step, which is fast:

```css
/* Slower: the layout is redone on every frame */
.recipe-card:hover {
  margin-top: -4px;
}

/* Smoother: only the compositing step changes */
.recipe-card {
  transition: transform 0.2s ease;
}

.recipe-card:hover {
  transform: translateY(-4px);
}
```

To see the cost, open the **Rendering** panel in Chrome or Edge (**Ctrl+Shift+P**, then *Show Rendering*) and tick **Paint flashing**: everything the browser repaints flashes green.

`will-change: transform` tells the browser ahead of time that an element is about to animate, so it can prepare a layer for it. Use it on one or two elements that animate often, not on everything: each prepared layer uses memory. It also starts a stacking context, which can change what sits on top, as *Common Layout Bugs and How to Fix Them* showed.

## content-visibility: skip what's off screen

A long recipe post ends with 200 reader comments. The browser lays out and paints all of them before it's done, even though nobody can see them until they scroll there. **`content-visibility: auto`** tells the browser it may skip that work for a section while it's off screen, and do it as the reader scrolls close:

```css
.comments {
  content-visibility: auto;
  contain-intrinsic-size: auto 800px;
}
```

`contain-intrinsic-size` gives a guess at the section's height, so the scrollbar doesn't jump while the real content isn't drawn yet. The text is still on the page, so find-in-page and screen readers still reach it. `content-visibility` is Baseline newly available since September 2025, which makes it a safe bonus: a browser that doesn't know it skips the line and draws everything, as before.

## Critical CSS: the first screen first

The **first screen** is what a reader sees before they scroll: on Weekend Kitchen, the header, the post's title and the hero photo. **Critical CSS** is the few rules that screen needs, put straight into the page in a `<style>` element, so the browser can paint it without waiting for a download. The rest of the stylesheet loads after:

```html
<head>
  <style>
    body { margin: 0; font-family: Georgia, serif; }
    .site-header { background-color: #8a3b12; color: #ffffff; }
    .post-hero { min-height: 60vh; }
  </style>
  <link rel="preload" href="styles.css" as="style" onload="this.onload = null; this.rel = 'stylesheet'">
  <noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
```

`rel="preload"` downloads the full stylesheet without blocking the paint, and the `onload` attribute, one line of JavaScript, switches it on when it arrives. The `<noscript>` line covers a browser with JavaScript turned off. Tools that work out the critical CSS for you write these lines too. It's real work to keep up, so it pays off on big pages and slow connections. A small site with one small stylesheet may gain nothing, which is why the last step matters most.

## Measure with Lighthouse

**Lighthouse** is a speed check built into Chrome and Edge. Open the developer tools, choose the **Lighthouse** panel, pick **Navigation** mode, **Mobile** and the **Performance** category, and click **Analyze page load**. It loads the page as a mid-range phone on a slow connection would, and gives it a score from 0 to 100 with the numbers behind it. Two to watch:

- **Largest Contentful Paint (LCP):** how long until the biggest thing on the first screen, often the hero photo, appears. 2.5 seconds or less is good.
- **Cumulative Layout Shift (CLS):** how much the page jumps around while it loads. 0.1 or less is good.

Below the numbers, it lists what to fix, such as render-blocking requests and unused CSS. Run it in a private window (Incognito in Chrome, InPrivate in Edge), so browser extensions don't slow the result. Firefox has no Lighthouse panel: for a page that's online, such as one on GitHub Pages, use PageSpeed Insights at pagespeed.web.dev in any browser.

**Try it.** Run Lighthouse on a page of your own, note the score and the LCP, change one thing from this lesson, and run it again. Change one thing at a time, so you know which one helped.

## Check yourself

2 questions to try on the lesson page.

## So what

A fast page is one that people stay on. Keep stylesheets few and small, animate with transform, let the browser skip what's off screen, and above all measure before and after, so you spend your effort where it counts.

## Key terms

- [Critical CSS](https://www.ask-codey.com/glossary/critical-css)
- [Reflow](https://www.ask-codey.com/glossary/reflow)
- [Repaint](https://www.ask-codey.com/glossary/repaint)
- [Compositing](https://www.ask-codey.com/glossary/compositing)
- [content-visibility](https://www.ask-codey.com/glossary/content-visibility)
- [will-change](https://www.ask-codey.com/glossary/will-change)

## Cheat sheets

- [CSS Performance: What Slows a Page, and Critical CSS](https://www.ask-codey.com/cheat-sheets/css-performance-cheat-sheet)

## Related

- [Will It Work Everywhere? Browser Support and @supports](https://www.ask-codey.com/lessons/css-browser-support)
- [Debugging Layouts with Developer Tools](https://www.ask-codey.com/lessons/css-debugging-with-devtools)

Source: https://www.ask-codey.com/lessons/css-performance
