So, let’s start our thinning-the-stylesheet journey. In my opinion, we can classify into two categories:

“Minifying” a stylesheet.

Removing unused CSS selectors.

✍️ I quote minifying because I cannot find a better word to describe what it does in the following section.

Minifying

What is minifying? In this section, it does two different things:

Perform transformations (aka CSS Minifier).

Cutting css’s class name.

CSS Minifier

CSS Minifiers basically does three things:

Cleaning (removing duplicated/empty rules and comments).

Compression (shorter form for color, font, background).

Restructuring (merge of declarations, rulesets and so on).

The image below is the benchmark of CSS minifiers

📕 Worst — 📓 Average — 📗 Best

As the image above shows, there are a bunch of css minifiers, I encourage you to use cssnano or csso, top two popular css minifiers in term of features and ecosystem. You can use them in your module bundler via:

Cutting css’s classname

If you sneak into Gmail HTML page (the same for other Google platforms: G+, Driver …), you will see something like this

It looks too ugly 💩, right? because it doesn’t have any meaningful class names, we were taught that we should use meaningful names when programming to improve readability and maintainability, it goes against that. Why Google does that? Because shorter class name means:

smaller size ⟷ fewer bytes to delivery ⟷ our website is faster 🎉.

faster when querying rule 🎉.

The problem we need to solve in order to achieve what we want:

Keeping meaningful class name on development for ease of debugging → we just follow best practices (BEM, SMACSS, OOCSS …) or your own rule as long as it is consistency in your team 🔪.

Outputting ugly/shortest class name on production for lightweight delivery and fast loading ← here this tough one 🏋️‍.

Outputting ugly/shortest class name: We need a tool which transforms class names, also keeps them synchronous other places when compiling our source code. I am currently using Webpack, luckily, one of Webpack loaders named css-loader has built-in function getLocalIdent to support us to overcome this obstacle.

If you are familiar with webpack config, this is the simple version of increment name 0 , 1 , 2 ... 💣

That is the idea, you can write a better version than me, right? 😜

Removing unused css selectors

In order to remove unused selectors, we need to know which parts are used and which are not, therefore the first step is detecting unused selectors. How? There are two traditional ways to detect unused things on frontend code:

Runtime: run your webpage, scan through HTML, CSS and js files to check which selectors are used in HTML/javascript. From used selectors, you/tools can exclude them and get unused selectors.

Build time: via module bundler we can import CSS files and specify which selectors. Based on that information from module bundler, we can detect unused selectors (it sounds easy right? 🤷‍).

Runtime

There are three popular ways to check unused CSS selectors:

Command line: You run command line with the location of CSS/HTML/js files as input and output are used/unused CSS. There are a lot of tools but purgecss, uncss and purifycss are three top popular ones.

Website: Quite similar to Command line but on a website. You enter your Webpack’s URL and it does its job 👊.

For example: https://www.jitbit.com/unusedcss/, https://unused-css.com/, https://uncss-online.com/ …

but on a website. You enter your Webpack’s URL and it does its job 👊. For example: https://www.jitbit.com/unusedcss/, https://unused-css.com/, https://uncss-online.com/ … Chrome Code Coverage: The image below shows code coverage not only for CSS files but also for js files

How to open Code Coverage:

Step 1 : Open Chrome Dev Tools

: Open Chrome Dev Tools Step 2: Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows, Linux), type Coverage

Step 3: Click record button

Build time

As I mention above. It sounds easy, right? Yes, it will be super easy if your module bundler supports named exports, otherwise, it can be challenging 🤯. I am currently using Webpack and unfortunately, webpack and its eco system ( css-loader ) doesn't support named exports because moving from commonjs to es6 named exports is a breaking change, you can see why via this thread.

In order to climb a steep hill, there are two steps we need to deal with:

Step 1 : Support static import/export for css ← es6-css-loader (it is based on Webpack’s offical loaders named style-loader and mini-css-extract-plugin.

: Support static import/export for css ← es6-css-loader (it is based on Webpack’s offical loaders named style-loader and mini-css-extract-plugin. Step 2: Plugin to hook into Webpack build process to show unused css selectors ← webpack-deadcode-plugin.

📌 I made the demo to demonstrate how to use two plugins above, here is source code.

When running the demo, the output looks like the image below