YUI CSS Min – part 2

May 20th, 2010. Tagged: CSS, performance, tools, yahoo, yui

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

Tell your friends about this post: Facebook, Twitter, Google+

12 Responses

  1. 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

  2. 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.

  3. 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.

  4. 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.

  5. @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.

  6. 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.

  7. 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}

  8. Thanks Emil, this is good stuff! I believe someone even committed a patch for shorthands.

    Definitely going in the next release

  9. 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 none value but can also take numeric values.

  10. Excellent, thanks Matthias!

  11. Here’s another possible optimization:

    .test[foo='bar'] { color: red; }

    Compressed:

    .test[foo='bar']{color:red}

    Could be:

    .test[foo=bar]{color:red}

    Of course, YUI compressor should only remove the quotes around the attribute value in cases where it’s allowed — e.g. if you have something like a[href$='.pdf'] { color: red; }, removing the quotes would make the CSS invalid (and it wouldn’t work in all browsers anymore).

  12. I think the admin of this web site is in fact working hard in favor of his site, as here every material is quality
    based information.

Leave a Reply