CSS Tools

The tools described here can be found in the → tdi.tools.css module. The CSS tools mainly provide a minifier for now.

Minifying CSS

Minifying reduces the size of a document by removing redundant or irrelevant content. Typically this includes whitespace and comments. Some minifiers also try semantic reduction by collapsing rules, modifying color notations and so on.

TDI ships with the latest version of the rCSSmin minifier, which only removes spaces, comments and finishing semicolons – but does that very fast.

There are two use cases here:

  1. Minify style blocks within HTML templates during the loading phase
  2. Minify some standalone piece of CSS

The first case is handled by hooking the → tdi.tools.css.MinifyFilter into the template loader. See the filters documentation for a description how to do that.

For the second case there’s the → tdi.tools.css.minify function:

from tdi.tools import css

print css.minify(u"""
fieldset p {
    margin: 0.5em;
}
fieldset p span {
    float: right;
    display: inline-block;
    font-size: 0.8em;
}
""".lstrip())
fieldset p{margin:0.5em}fieldset p span{float:right;display:inline-block;font-size:0.8em}

Masking Style Blocks

HTML has a long history of adding new elements all the time. Conceptually this is possible, because browsers simply ignore the tags of unknown elements and apply no semantics. That’s forward compatibility. Now if you place something inside these new elements, which is not HTML content, you get a backwards compatibility problem.

cdata and cleanup

Style elements (and script elements for that matter) suffer from this problem since they were invented. The first solution was to enclose them with comment markers, but add special rules for browsers to accept these markers as part of the content:

<style><!--
   body {background-color: #fff; color: #000;}
--></style>

Then XHTML was invented. The XML parser cannot be tricked into such special rules. It would start throwing away the comment again, so people gave up backwards compliance and wrote:

<style><![CDATA[
   body {background-color: #fff; color: #000;}
]]></style>

and then, to be compatible with HTML again:

<style>/*<![CDATA[*/
   body {background-color: #fff; color: #000;}
/*]]>*/</style>

Then someone finally figured out [1] a mix of CDATA and comments completely compatible with all HTML/TagSoup parsers, and it looks like this:

[1]http://lists.w3.org/Archives/Public/www-html/2002Apr/0053.html
<style><!--/*--><![CDATA[/*><!--*/
  body {background-color: #fff; color: #000;}
/*]]>*/--></style>

This is funny stuff, but you wouldn’t want to write it all the time. You should consider applying that, however, because browsers are typically not the only applications parsing your HTML.

The functions → css.cdata and → css.cleanup can do that for you. cdata() takes a style block and encloses it in such an all-compatible CDATA/comment-mix-container. cleanup() does the reverse. It looks for common containers (like the ones described above) and strips them. In fact, the cdata() function calls cleanup() itself in order to avoid doubling itself:

from tdi.tools import css

print css.cdata("""
/*<![CDATA[*/
    body {font-family: sans-serif;}
/*]]>*/
""".strip())
<!--/*--><![CDATA[/*><!--*/
body {font-family: sans-serif;}
/*]]>*/-->

The cdata() function can be applied automatically to all style blocks of a template by hooking the → tdi.tools.css.CDATAFilter into the template loader. See the filters documentation for a description how to do that.