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

How to build a CSS minifier with 8 lines of Javascript

derder56 profile image DerDer56 Updated on ・3 min read

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!

Posted on by:

derder56 profile

DerDer56

@derder56

I don't know what to write here, except that I like coding.

Discussion

pic
Editor guide
 

Try the following in your minifier:

div::before {
  display: block;
  content: "/*not a comment*/"
}
 

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*\/"
}
 

Absolutely, there is no reason to do that 😁

Yep. But thanks for telling me anyway!

 

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

 

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! 😝

 

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

 

Try the following in your minifier:

/**
 * This comment is not minified
 */
main {
    display: none;
}
/* This comment is minified */
 

I'll try to find a solution for that.

 

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

 

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.

 

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

 

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