YUI CSS Min - part 2
The first part is here. It was more about building the YUICompressor, writing and running test cases. Now let's see what the compressor does exactly to your CSS.
BTW, you can play with the web UI to see for yourself how the minifier works.
Stripping comments and white space
This is the bare minimum a minifier can do. And when it comes to CSS, this is also the place where ther biggest improvement comes from. In JS for example you can rename variables and save bytes, but in CSS the possibilities are more limited. No shorter way to say text-decoration, unfortunately.
So before:
/***** classmates stuff *****/ .classmates { /* after 10 years */ weight: considerable; }
After:
.classmates{weight:considerable}
Special comments
Stripping comments is nice but not always ok. Sometimes you need to retain copyright information. Use ! at the beginning of the comment to mark the comment as special.
Before:
/*! (c) copyright copyleft */ .classmates { /* after 10 years */ weight: considerable; }
After:
/*! (c) copyright copyleft */.classmates{weight:considerable}
Thanks to the charmingly insisting Billy Hoffman and the valid case he presented, the bang (!) itself is preserved too. This way you can safely double minify. Also lint tools (such as Zoompf, YSlow and PageSpeed) can see the ! and conclude that this comment is there intentionally, not because you forgot to minify.
Striping last semi-colon
The last semi-colon in a declaration block is out. So keep it in your source for maintenance purposes and let the minifier take care of stripping it out.
Before:
a { one: 1; two: 2; }
After:
a{one:1;two:2}
Extra semi-colons
One semi-colon is all you need, so the minifier will strip an accidentally added one.
Before:
p :link { ba: zinga;;; foo: bar;;; }
After:
p :link{ba:zinga;foo:bar}
No empty declarations
Empty declaration blocks don't do anything, so why send them over the net?
Before:
.empty { ;}
After:
(nothing...)
Zero values
A zero is a zero. Zero pixels or % or centimeters or whatever, it's still zero. Also sometimes (when everything is a zero) you need just one zero instead of four, or three or two.
Before:
a { margin: 0px 0pt 0em 0%; background-position: 0 0ex; padding: 0in 0cm 0mm 0pc }
After:
a{margin:0;background-position:0 0;padding:0}
Floats
For values such as 0.something, the 0 is not needed.
Before:
::selection { margin: 0.6px 0.333pt 1.2em 8.8cm; }
After:
::selection{margin:.6px .333pt 1.2em 8.8cm}
Colors values
RGB color values are nice, but not the most concise form. Make them hex. Also AABBCC hex can be the shorter ABC. But don't touch RGBA and don't touch the IE filter values in quotes.
Before:
.color { me: rgb(123, 123, 123); impressed: #ffeedd; background: none repeat scroll 0 0 rgb(255, 0,0); }
After:
.color{me:#7b7b7b;impressed:#fed;background:none repeat scroll 0 0 #f00}
Before:
.cantouch { alpha: rgba(1, 2, 3, 4); filter: chroma(color="#FFFFFF"); }
After (no color minification) :
.cantouch{alpha:rgba(1,2,3,4);filter:chroma(color="#FFFFFF")}
Single charsets
Only one charset is allowed per stylesheet. So, if there's more than one, strip it. It may happen when merging several stylesheets into one.
Before:
@charset "utf-8"; #foo { border-width: 1px; } /* second css, merged */ @charset "another one"; #bar { border-width: 10px; }
After:
@charset "utf-8";#foo{border-width:1px}#bar{border-width:10px}
Alpha opacity
There's a shorter way to write opacity filter for IE.
So before:
code { -ms-filter: "PROGID:DXImageTransform.Microsoft.Alpha(Opacity=80)"; /* IE 8 */ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); /* IE 4-7 */ }
After:
code{-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}
There are more filters that could be shorten besides the opacity, but MSDN suggests the longer syntax should be used, So a bit more experimentation is needed here...
Thanks!
Whew, sort of a lengthy post. Thank you for reading and coming up next time... hacks
If you have ideas, comments, your bug reports are welcome
This entry was posted on Thursday, May 20th, 2010 and is filed under CSS, performance, tools, yahoo, yui. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Get notification for future posts: follow me on Twitter or subscribe to my RSS feed

May 21st, 2010 at 12:03 am
CSS Tidy also does all of mentioned (except flters) and some more minifications. I.e. you can also shrink font and background properties. Sometimes it’s even safe
P.S. Spam protection: Sum of 1 + 2 != 3. Wow
May 21st, 2010 at 12:12 am
yes, I think CSS tidy is the most advanced, it parses the CSS, while YUI’s css min is a bunch of regexp. I’ve compared some here:
http://www.phpied.com/reducing-tpayload/
YUI CSS min is a little better now than these measurements but just with about 2%
For background and font you mean using shorthands, right?
Sorry for the spam thingie, it’s just some plugin I installed.
May 21st, 2010 at 1:43 am
The only issue I once had with charsets is that Safari doesn’t like @charset “utf-8″;rule{here:0px} It needs a space behind the charset ; or it will ignore the complete stylesheet.
So you might want to double check that if you are using charsets inside your stylesheets.
May 21st, 2010 at 1:59 am
When evaluating CSS, I come across a lot of developers that default to color names. It would be nice to regex out at least common values like black and white to #000 and #fff.
May 21st, 2010 at 3:35 am
@Stoyan: not sure what version of CSS Tidy was used - because there has ben made some improvements, but we still can’t sync C-branch with PHP-branch to release 1.3
CSS Tidy also can merge selectors and sort (yeah!) properties and selectors in alphabetic order.
May 21st, 2010 at 4:10 pm
Sunnybear, that’s cool, I thought CSSTidy was no longer being developed, happy to see the project is alive and kicking. Yes, I was using the PHP version for testing.
May 27th, 2010 at 3:26 am
I noticed few areas that could be improved. All the tests are based on http://tools.w3clubs.com/cssmin/
Original:
.test1 {
margin: 10px 15px 8px 15px;
}
.test2 {
margin: 10px 15px 10px 15px;
}
Compressed:
.test1{margin:10px 15px 8px 15px}.test2{margin:10px 15px 10px 15px}
Could be:
.test1{margin:10px 15px 8px}.test2{margin:10px 15px}
It seems that margin:{x x x x} also does not become margin{x}
May 27th, 2010 at 2:40 pm
Thanks Emil, this is good stuff! I believe someone even committed a patch for shorthands.
Definitely going in the next release
May 28th, 2010 at 7:56 am
Some additional optimizations:
.test { border:none; }Compressed:
.test{border:none}Could be:
.test{border:0}The same goes for other CSS properties that have a
nonevalue but can also take numeric values.May 28th, 2010 at 10:11 am
Excellent, thanks Matthias!