DEV Community

Cover image for How to build a CSS minifier with 8 lines of Javascript
DerDer56
DerDer56

Posted on • Updated on

How to build a CSS minifier with 8 lines of Javascript

Everybody likes a minified script. Minifying CSS is ridiculously simple, so today I'm going to show you how to make a CSS Minifier using only 8 lines of Javascript.

For our minifier, we first need to think about what we have to do, how to to it, and then do it.

Cool Gradient Background

What we have to do

The two steps to our minifier will be:

  1. Get rid of unnecessary whitespace and semicolons
  2. Get rid of comments

Other minifiers may have extra features that replace black with #000 and more, but we'll stick with two steps so that it's nice and simple and works on all browsers.

How do we do it?

Let's assume that we already made a page out of HTML and CSS, with a button that runs minify() when it's clicked, and we just need the Javascript. Our first code will look something like this:

var inputs = document.getElementsByTagName("textarea");
function minify() {
  // turn inputs[1] into inputs[0], but minified
  /* array counts start with 0, so inputs[0] is the 
  first input and inputs[1] is the second */
}

Inside the minify function we will use replace() to minify the value of the first input. The replace function requires a knowledge of RegExps. In our function we will use 4 replace functions to minify the CSS. I'm not going to explain how exactly these four RegExps work, as I'm sure you could find answers to any questions online.

Doing it

Step 1: Now we use the following 3 lines of code to get rid of whitespace and semicolons that we don't need. This one is easier said than done.

.replace(/([^0-9a-zA-Z\.#])\s+/g, "$1")
.replace(/\s([^0-9a-zA-Z\.#]+)/g, "$1")
// get rid of spaces next to non-alphanumerical (not a-z, A-Z, #, ., or 0-9) characters. for some reason combining these result in an error.
.replace(/;}/g, "}")
// get rid of semicolons where they're not needed (just before the end of a css declaration, the character })

Step 2: CSS comments are quite common and look like such:

/* hello, i am a comment! */

So we need a RegExp to get rid of comments, which is simpler than you might think. This line of code does the job nicely:

.replace(/\/\*.*?\*\//g, "")
// tip: if you get rid of the \s you can read it better 

So we end up with our whole script looking like this, with only 8 lines of code:

var inputs = document.getElementsByTagName("textarea");
var inputs = document.getElementsByTagName("textarea");
function minify() {
  inputs[1].value = inputs[0].value
    .replace(/([^0-9a-zA-Z\.#])\s+/g, "$1")
    .replace(/\s([^0-9a-zA-Z\.#]+)/g, "$1")
    .replace(/;}/g, "}")
    .replace(/\/\*.*?\*\//g, "");
}

And we're done! (Thanks to Habdul Hazeez for reporting a comment error. It was fixed. Also thanks to Lyrod for reporting this error:)

main .foo .bar {
  display: none;
}
/* is not the same as */
main.foo.bar{display:none}

Extra

You can see the minifier in action on this page. The full code for the site can be viewed here or here:

Thank you for reading!

Top comments (14)

Collapse
 
derder56 profile image
DerDer56 • Edited

content attributes are currently not supported, as this is a simple minifier. Also, technically speaking, I don't see why somebody would do this.

Anybody could just do:

div::before {
  display: block;
  content: "/\*not a comment*\/"
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
derder56 profile image
DerDer56

But if anyone knows how to prevent comment minification inside quotes, I could update the script.

Collapse
 
ziizium profile image
Habdul Hazeez • Edited

Try the following in your minifier:

/**
 * This comment is not minified
 */
main {
    display: none;
}
/* This comment is minified */
Collapse
 
derder56 profile image
DerDer56

I'll try to find a solution for that.

Collapse
 
derder56 profile image
DerDer56

Solution found! Get rid of comments after doing everything else. Thanks for telling me about this!

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Other minifiers may have extra features that replace black with #fff and more, but we'll stick with two steps so that it's nice and simple and works on all browsers.

Please tell us which ones do this so we can avoid them! 😝

Collapse
 
derder56 profile image
DerDer56 • Edited

Whoops! I wrote fff instead of 000, lol. Fixing that...

Collapse
 
lyrod profile image
Lyrod

Your minifier is not correct

main .foo .bar {
  display: none;
}

Will be translated to

main.foo.bar{display:none}

Which is not the same thing.

Collapse
 
derder56 profile image
DerDer56

Ok, I'm working on a fix for this...

Collapse
 
derder56 profile image
DerDer56

Fix found! I'm updating the post now...

 
derder56 profile image
DerDer56

Yep. But thanks for telling me anyway!

Collapse
 
mycodemagic profile image
MyCodeMagic

so bad it's not working