Reduce unused JavaScript and CSS: a practical guide
Pages ship code they never use. How to find unused JavaScript and CSS with the Coverage tool, what Lighthouse flags, and how to remove, split or delay it.
In this guide
What "unused" means
When a browser loads a stylesheet or a script, it does not know which part the current page will need. It downloads the whole file. Unused code is the part that is never used while the page loads and while you use it: CSS rules for elements that are not on the page, and functions that never run.
The Chrome documentation gives the standard example. You want one button component from a CSS framework, so you link the framework's whole stylesheet. The page needs a few hundred bytes of it and downloads tens of kilobytes. JavaScript works the same way: a charting library imported for one small chart, a sliding gallery loaded on every page, a polyfill for a browser nobody uses.
Why it costs speed
- Download time. More bytes on the network, especially on slow mobile connections.
- Parsing and running (JavaScript). The browser must parse and compile every script it downloads, and run the top-level code, even if no function in it is ever called. This is main-thread time, which drives Total Blocking Time and slow responses.
- Blocking the first paint (CSS). Stylesheets in the head block rendering until they have been downloaded and read, so a large stylesheet delays everything. See render-blocking resources.
- Memory and style work. More rules to match against every element, on every change.
Text compression shortens the download but not the parsing, so shrinking the code is better than compressing it.
What Lighthouse reports
Lighthouse 13 lists two diagnostics, "Reduce unused JavaScript" and "Reduce unused CSS" (more on CSS in CSS performance). Neither counts toward the performance score directly. They describe how many bytes of each file were not used, and they have thresholds so that small cases do not clutter the report: the JavaScript diagnostic ignores a source unless more than 20 KB of it is unused, and the CSS diagnostic ignores a stylesheet unless more than 10 KB of it is unused. A page that passes both can still have unused code, just under those limits.
Step 1: find the unused code
Chrome DevTools Coverage. Open DevTools, run the "Show Coverage" command, press the record button and reload the page. The panel lists every CSS and JavaScript file with its size and the percentage that was unused, and colors the lines in the Sources panel: one color for what ran, another for what did not. Sort by unused bytes to see the worst first. Then use the page as a visitor would: open the menu, scroll, switch tabs, and watch the numbers change.
The Lighthouse report. It names the files and the unused bytes without you having to interact, which is a good way to start.
Bundle analysis. If your site is built with a bundler, a bundle analyzer draws a map of what is in each file, which library takes how much, and what is included twice. Most bundlers have a plugin for it. This finds the dependencies that cost the most before the code reaches the browser.
A caution from the Chrome documentation applies: finding unused code is relatively easy, and refactoring a codebase so each page ships only what it needs can be difficult. Coverage shows what did not run during your recording, not what can never run.
Step 2: remove what nobody uses
The cheapest bytes are the ones you delete.
- Remove features and libraries nobody uses: an old slider, a social share bar, a second copy of a library, a testing tool, a font icon set of which you use three icons.
- On WordPress, deactivate plugins that are not needed, and check each remaining plugin's settings for an option to load its scripts and styles only on the pages that use them. A form plugin that loads on every page, though the form is on one, is the classic find. Some themes let you switch off whole feature sets.
- Replace heavy libraries with lighter ones, or with features the browser now has. Many things that needed a library years ago, such as selecting elements, animating, fetching data or building a lightbox, are available natively.
- Remove polyfills for browsers you no longer support, because modern browsers do not need them.
- Remove duplicate modules: two versions of the same library pulled in by different dependencies.
Step 3: ship only what each page needs
Where the code is needed somewhere but not everywhere, split it.
JavaScript. Code splitting breaks one large bundle into several smaller files. MDN lists two main approaches: splitting by entry point, so that each page or section has its own bundle, and dynamic splitting, where a dynamic import() loads a piece of code at the moment it is needed:
document.querySelector('#open-chart').addEventListener('click', async () => {
const { drawChart } = await import('./chart.js');
drawChart();
});The chart code downloads only when someone asks for the chart. Import only the parts of a library that you use, for example a single function instead of the whole package, so that your bundler can leave the rest out. This is called tree shaking, and it only works with modules that are written so that unused exports can be seen. The whole process for a bundle, from finding what is in it to splitting it, is in JavaScript bundle size and code splitting, and old libraries are covered in removing jQuery and other legacy libraries.
CSS. Split the stylesheet by template or section, so the checkout page does not load the blog's styles. A link with a media attribute keeps a file from blocking rendering when the condition is false, which suits print styles and large-screen-only styles. Remove rules for components that are not on the page with a tool that scans your pages and drops what they do not use. Many performance plugins have this option. Always keep a safelist for classes that are added by scripts or appear only in some states.
Both. Load heavy, rarely used parts only when needed: a video player on a click, a map when the visitor scrolls to it, a chat tool after a delay. See third-party scripts for patterns that work.
Step 4: test every state
Unused code removal is the kind of change that can break things in ways you do not see on the first load. Before and after, check:
- the menu on a phone and on a desktop, open and closed;
- forms, including error messages and success messages;
- pop-ups, tabs, accordions and sliders;
- pages in other templates, such as the cart, the account and a post;
- anything that only appears for logged-in users;
- different languages, if the site has them.
When you remove CSS automatically, compare screenshots of your main pages before and after.
A worked example
This one is made up to show the method. A WordPress home page loads 14 stylesheets and 22 scripts. The Coverage tool shows that two stylesheets from a form plugin and a gallery plugin are 94% unused, because neither feature is on the home page, and a slider script of 180 KB runs on a page that has no slider. Three changes remove most of the waste: set the form plugin to load its files only on the contact page, remove the gallery plugin from the pages that do not use it, and replace the slider on the home page with a single image. None of this needs code. After each change, the page is tested again and the unused bytes drop.
How to check the result
- Run Coverage again and compare the total unused bytes.
- Compare the requests in the Network panel: fewer and smaller files.
- Run the lab test three times. Total Blocking Time and First Contentful Paint should improve, since less code is parsed and run.
- Click through the pages as in Step 4.
Check your own page
Run the free audit and look at the unused code diagnostics and the JavaScript execution time. Start with the largest file on the list: ask what it is for, which pages need it, and whether it can be removed, split or loaded later.
Sources
- Find unused JavaScript and CSS with the Coverage tab in the Chrome documentation: how to record coverage and read it.
- Reduce unused JavaScript and Reduce unused CSS in the Lighthouse documentation.
- Lazy loading on MDN: code splitting, dynamic
import()andmediaon stylesheets.
Start here
Free website audit
Live Google data for any public page: mobile and desktop.
Mobile + desktop · Lighthouse lab test · Real-user Chrome data when Google has it
Rather have this done for you? Speed optimization · Book a call