/ โ† CSS Checker Fixes / CSS Bundle Size
In this guide
  1. Where the bytes in a big stylesheet come from
  2. Measuring what you are actually shipping
  3. The fix, step by step
  4. Example: a trimmed Sass entry file
  5. Platform notes
  6. Edge cases
  7. Stopping the bundle from growing back
  8. Questions and answers

Where the bytes in a big stylesheet come from

Hand-written CSS for a typical small-business site is rarely large. The kilobytes pile up in the build pipeline, where tools pull in far more than anyone chose line by line. When you open a bloated bundle and trace its contents, you usually find a mix of these:

Source of weightHow it gets inTypical sign
Whole UI frameworkOne line such as @import "bootstrap"; brings in every componentClasses for carousels, toasts and modals the site never uses
Duplicated partialsVariables or mixin files that also output rules, imported by several entry filesThe same selectors appearing two or three times
Embedded assetsFonts, SVG icons or background images inlined as data: URIsVery long base64 strings inside url()
Inline source mapsDevelopment build settings used in productionA large comment starting sourceMappingURL=data: at the end
One global bundleEvery page's styles compiled into a single fileCheckout, blog and account styles all load on the home page
Icon fontA full icon set loaded for a handful of iconsHundreds of .icon-*:before rules
Unminified outputMinifier missing or disabledComments, indentation and long colour values in the served file

Unused selectors on a single page are a related but separate problem. The unused CSS guide covers removing rules that nothing uses. This guide is about structure: what goes into each bundle, and which pages receive which bundle. How the finished file is delivered to the browser, including critical CSS and deferral, is in the render-blocking CSS guide.

Measuring what you are actually shipping

There are three sizes worth knowing for each stylesheet, and people often compare the wrong ones:

In DevTools, open the Network panel, filter to CSS and reload with the cache disabled. Hover the Size column, or turn on "Big request rows", to see both the transferred and the resource size. On the command line you can check the compressed size of a build output:

ls -l dist/assets/*.css
gzip -9 -c dist/assets/main.css | wc -c
brotli -c dist/assets/main.css | wc -c

To see what the bundle is made of, a CSS analyser such as Project Wallace reports the number of rules, selectors, declarations, duplicate values and embedded data: URIs. Simple searches also go a long way:

# How much of the file is base64 data?
grep -o 'data:[^)]*' dist/assets/main.css | wc -c

# Is the same selector compiled more than once?
grep -o '^\.btn-primary{' dist/assets/main.css | wc -l

If your build produces source maps as separate files, open the map in a text editor and look at the sources list. It names every partial and package that contributed to the output, which quickly shows whether an entire framework is in there.

๐Ÿ’ก Record the three sizes for your main templates before you change anything. Without a baseline it is hard to tell which change made the real difference, and easy to spend an afternoon on something that saved very little.

The fix, step by step

Step 1

Measure the bundle before and after compression

Run the CSS Checker on your main templates to see which stylesheets it reports as oversized, then record the raw and compressed size of each file and the total CSS each template loads. Use the Network panel with the cache disabled, or gzip and brotli on the build output. This baseline shows whether the problem is one huge global file, too many separate files, or a compression setting missing on the server.

Step 2

Break the bundle down by source

Open the source map, or temporarily build without minification, and list which packages and partials contribute to the output. Group them into your own styles, framework code, third-party widgets and embedded assets. Search for base64 strings and repeated selectors. Most bundles have one or two dominant sources, and those are where the savings are. Write down each source with an owner, so you know which ones you can change yourself.

Step 3

Import only the framework parts you use

Replace a single all-in-one framework import with the individual pieces you need. With Bootstrap's Sass source, import the functions, variables, mixins and then only the component partials your templates use, such as the grid, buttons and forms. With Bulma or Foundation, the same idea applies. If you use a utility framework such as Tailwind, make sure its content paths cover your templates so it only generates the classes you actually write.

Step 4

Stop the same partials compiling twice

Check each entry file for partials that output real rules, such as a reset or base typography, and make sure only one bundle includes them. Move Sass from the deprecated @import to @use and @forward, which load each module once per compilation. Keep variables and mixins in files that produce no CSS by themselves, so any number of entry files can use them without adding a single byte to the output.

Step 5

Take fonts, images and source maps out of the CSS

Move base64 fonts and large background images out of the stylesheet into separate files referenced with ordinary URLs, so they can be cached and downloaded in parallel. Replace a full icon font with inline SVG or a small SVG sprite containing only the icons you use. Check your production build settings and make sure source maps are written as separate files, or not at all, rather than embedded at the end of the stylesheet.

Step 6

Split the bundle by route or template

Divide the styles into a small shared file for the layout, header, footer and common components, plus one file per area such as shop, blog, checkout and account. In Vite, CSS imported by lazily loaded modules is split automatically when cssCodeSplit is on, which is the default. In webpack, use MiniCssExtractPlugin with separate entries or split chunks. Load each area's file only on the templates that need it.

Step 7

Minify, compress and set a size budget

Minify production CSS with cssnano or Lightning CSS, and confirm the server sends it with Brotli or gzip by checking the content-encoding response header. Give files content-hashed names and a long cache lifetime. Then add a size budget to your build or CI, for example a check that fails when the shared stylesheet grows past an agreed limit, so the bundle cannot quietly grow back after the next feature or plugin.

Example: a trimmed Sass entry file

Here is the before and after for a fictional shop, Fernbrook Candles, whose single stylesheet had grown large because of a full framework import and a reset that was pulled in twice.

Before

// main.scss
@import "bootstrap";          // every component, whether used or not
@import "reset";              // also imported inside _shop.scss
@import "icons";              // full icon font, base64 embedded
@import "shop";
@import "blog";
@import "account";

After: a shared file plus per-area files

// shared.scss (loaded on every page)
// Framework foundations first, in the order the framework documents
@import "bootstrap/scss/functions";
@import "settings";                     // your variable overrides, outputs nothing
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";
// Then only the components the templates use
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
@import "layout";                       // header, footer, navigation

// shop.scss (product and collection templates only)
@use "tokens";                          // shared variables as a module
@use "product-card";
@use "gallery";

// blog.scss (article templates only)
@use "tokens";
@use "article";

The file list above follows the partial-import approach in Bootstrap 5's documentation, which still uses @import for the framework's own files, so the shared file keeps that syntax while your own area files use @use. The exact list and order change between framework versions, so follow the documentation for the version you run. The principle is the same for any framework: pull in the foundations, then name each component explicitly, and let each template load only its own area file.

โš ๏ธ Splitting can go too far. Ten tiny stylesheets on one page mean ten requests and more chances of a late one. Aim for one shared file plus one area file per template, not a separate file for every component.

Platform notes

WordPress

Much of the weight on WordPress comes from plugins and page builders that enqueue their own full stylesheets on every page. You cannot restructure their builds, but you can stop their files loading where they are not used with wp_dequeue_style() in a child theme, and choose builders that output per-page CSS files. Block themes also offer an option to load block styles only for blocks present on the page. The WordPress CSS guide goes further.

Shopify

Online Store 2.0 themes already split component CSS into section-level files. Weight usually comes from apps and from custom code added to one catch-all file. See the Shopify CSS guide.

React, Next.js and other frameworks

Frameworks that bundle CSS per route do much of the splitting for you, as long as styles are imported by the components that use them rather than all at once in a root layout. A global stylesheet imported at the top of the app goes to every route. CSS-in-JS libraries that generate styles at runtime add JavaScript weight as well as CSS; the React and Next.js CSS guide compares the options.

Edge cases

Stopping the bundle from growing back

  1. Add a size check to your build or CI that compares each output file with a stored limit.
  2. Review new dependencies for their CSS as well as their JavaScript before installing them.
  3. Keep one owner for the shared stylesheet, so additions are a decision rather than a habit.
  4. Re-run the CSS Checker after each release and compare the reported sizes with your baseline.
  5. Keep variables and mixins in output-free files, and lint for the deprecated Sass @import.
Questions and answers

1. How big should a CSS file be?

There is no single correct figure, and Google does not set one. What matters is how much CSS a page has to download and parse before it can render, and how long that takes on a mid-range phone on mobile data. As a working approach, keep the shared stylesheet small enough that it arrives quickly after compression, and make sure each template loads only the area styles it uses. Measure your own pages rather than chasing a number from a blog post.

2. Is one big CSS file better than several small ones?

Neither extreme is ideal. A single file for the whole site is simple and caches well, but every page pays for styles it never uses, including checkout and account styles on the home page. Many tiny files mean more requests and more chances of one arriving late. The usual balance is a small shared file for layout and common components, plus one file per area of the site, loaded only on the templates in that area.

3. What is the difference between bundle size and unused CSS?

Bundle size is about how stylesheets are assembled and which pages receive them: framework imports, duplicated partials, embedded assets and splitting. Unused CSS is about rules that no page ever matches, which can be removed with tools such as PurgeCSS. They overlap, because a smaller bundle usually contains fewer unused rules, but they are fixed differently. Restructuring the build comes first, then removing leftover dead rules becomes easier and safer.

4. Why is my Bootstrap CSS so large?

Because a single import of the full framework includes every component it offers, from carousels and toasts to popovers and every utility class, whether your site uses them or not. Bootstrap is designed to be imported in parts. Import the functions, variables and mixins first, then only the component files you need. The documentation for your Bootstrap version lists the individual files and the order they must be imported in, which changes between major versions.

5. Does minifying CSS make much difference?

Minification removes comments, whitespace and redundant characters, and tools such as cssnano and Lightning CSS also merge duplicate rules and shorten values. The raw file gets noticeably smaller, which helps parsing. The transfer saving is often smaller than people expect when Brotli or gzip compression is already on, because compression is good at repeated text. Do both: minify at build time and make sure the server compresses CSS responses, then check the result in the Network panel.

6. Should fonts be embedded in CSS as base64?

Usually not. A base64 font is about a third larger than the original file, cannot be cached separately from the stylesheet, and makes the stylesheet itself slower to download, which delays the first paint. Serve font files as separate WOFF2 files referenced from your font-face rules, preload the one or two that appear on the first screen, and let the browser cache them. Tiny icons can sometimes be an exception, but SVG usually handles those better.

7. Will splitting CSS by route break my styles?

It can if the cascade order changes. When styles move from one file into several, rules that used to come later may now load earlier and lose to others with the same specificity. Test pages that load both the shared file and an area file, especially components used in more than one place. Cascade layers are a good way to make the intended order explicit, so it no longer depends on which file happens to load last.

See which stylesheets are too large

The CSS Checker measures stylesheet size and flags render-blocking and unused CSS, along with validation errors, specificity issues and prefix gaps, so you know where the weight is before you restructure the build.

Open CSS Checker Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All CSS Checker Fixes  ·  Fixing Unused CSS  ·  Fixing Render-Blocking CSS  ·  CSS in React and Next.js  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.