Month: August 2009

  • CSS minifier and alphabetiser

    Update: This project is now hosted on GitHub: https://github.com/barryvan/CSSMin/

    There are quite a few CSS minifiers out there, which can bring the raw size of your CSS files down substantially. There are, however, significant gains to be made if the CSS is minified so that it gzips better. To that end, I’ve written a small Java application that will read in a CSS file and output its contents to stdout or another file in a format that’s optimised for gzipping.

    The problem

    A gzipped file will be stored most efficiently when there are many recurring strings in the file. This means that when writing CSS files, this code:
    [sourcecode language=”css”].pony {
    border: solid red 1px;
    font-weight: bold;
    }
    .lemur {
    border: solid red 1px;
    font-weight: normal;
    }[/sourcecode]
    will be better-compressed than this:
    [sourcecode language=”css”].pony {
    border: solid red 1px;
    font-weight: bold;
    }
    .lemur {
    font-weight: normal;
    border: red solid 1px;
    }[/sourcecode]
    In the first sample, notice that we have a very long string that occurs twice:

     {
    border-style: solid red 1px;
    font-weight: 

    In the second sample, there are strings that occur more than once, but they’re much shorter. The gzip algorithm can, in the first case, replace that entire long string with a much shorter placeholder.

    What it does

    So, how can we optimise CSS for gzipping, then? A file that’s minified using this CSS Minifier will have these operations applied:

    • All comments removed.
    • The properties within all selectors ordered alphabetically.
    • The values for all properties ordered alphabetically.
    • All unnecessary whitespace removed.
    • Font weights replaced by their numeric counterparts (which are shorter).
    • Quotes stripped wherever possible.
    • As much text as possible transformed to lowercase.
    • Prefixed properties (for example, -moz-box-sizing) placed before the unprefixed variant (box-sizing).
    • Colours simplified from rgb() to six- or three-digit hex values, or simple names.
    • Units on values of 0 stripped.
    • Multi-parameter items simplified to as few parameters as possible.
    • Various other small tweaks and adjustments made.

    By way of example, the following CSS snippet:
    [sourcecode language=”css”]body {
    padding: 8px;
    margin: 0;
    background-color: blue;
    color: white;
    font-family: “Trebuchet MS”, sans-serif;
    }

    h1 {
    margin: 0;
    padding: 0;
    font-size: 200%;
    color: #0F0;
    font-weight: bold;
    }

    p {
    margin: 0 0 2em;
    line-height: 2em;
    }[/sourcecode]
    would be formatted to the following (note that line breaks have been added for legibility — no line breaks appear in the final output):

    body{background-color:blue;color:#fff;font-family:"trebuchet ms",sans-serif;
    margin:0;padding:8px}h1{color:#0f0;font-size:200%;font-weight:700;margin:0;
    padding:0}p{line-height:2em;margin:0 0 2em}

    Compression results

    These are the results of compressing the main CSS file for one of the webapps I develop at work.

     Original size (bytes)Gzipped size (bytes)
    Plain8193812291
    YUI6443410198
    LotteryPost6360910165
    CSS Drive6927510795
    CSSMin637919896

    Download

    Head over to GitHub to download the source.

    Usage

    First, if you haven’t done so yet, compile the code:
    [sourcecode]# javac CSSMin.java[/sourcecode]
    Then, you can call the minifier by running
    [sourcecode]# java CSSMin in.css [out.css][/sourcecode]
    If you do not specify an output file, the resultant CSS will be printed to stdout (and can then be redirected as you wish).

    Contact

    If you have any questions or comments about this app, or if you find a bug or some weird behaviour, just comment on this post, and I’ll see what I can do.

    You can also raise issues on GitHub, fork the project, commit changes, and more.

    If you find this utility useful, let me know!

  • Quicksort an array of objects

    Often, you will need to sort an array of objects in Javascript. The inbuilt sort() function can’t do this, but here is a Quicksort implementation for doing just this.

    Parameters

    array The array to be sorted. (See below for an implementation on the Array Native itself, which makes this variable unnecessary).

    key The key to sort by. Make sure every object in your array has this key.

    Examples

    [sourcecode language=’javascript’]
    var objs = [
    {fruit:”cherry”},
    {fruit:”apple”},
    {fruit:”banana”}
    ];

    console.log(objs.sortObjects(‘fruit’));
    // Logs [{fruit:”apple”},{fruit:”banana”},{fruit:”cherry”}] to the console
    [/sourcecode]

    The code

    [sourcecode language=’javascript’]
    sortObjects: function(array, key) {
    for (var i = 0; i < array.length; i++) { var currVal = array[i][key]; var currElem = array[i]; var j = i - 1; while ((j >= 0) && (array[j][key] > currVal)) {
    array[j + 1] = array[j];
    j–;
    }
    array[j + 1] = currElem;
    }
    }
    [/sourcecode]

    Implemented on the Array native:

    [sourcecode language=’javascript’]
    Array.implement({
    sortObjects: function(key) {
    for (var i = 0; i < this.length; i++) { var currVal = this[i][key]; var currElem = this[i]; var j = i - 1; while ((j >= 0) && (this[j][key] > currVal)) {
    this[j + 1] = this[j];
    j–;
    }
    this[j + 1] = currElem;
    }
    }
    });
    [/sourcecode]

  • Javascript string ellipsising

    Putting ellipses into strings that are too long has been around for a very long time. Unfortunately, Javascript doesn’t offer a native method of doing this, so below is a little function that’ll do it for you.

    This function returns a copy of the string it’s called on, ellipsised, and takes three parameters:

    toLength (required) The number of characters to truncate the string to (or 0 to disable ellipsising)

    where (optional, default ‘end’) A string representing where the ellipsis should be placed — ‘front’, ‘middle’, or ‘end’

    ellipsis (option, default ‘\u2026’) A string to be used as the ellipsis.

    Examples

    [sourcecode language=’javascript’]
    // Our clichéd string
    var s = ‘Jackdaws love my great big sphinx of quartz’;

    alert(s.ellipsise(10));
    // Alerts “Jackdaws l…”

    alert(s.ellipsise(10, ‘front’));
    // Alerts “… of quartz”

    alert(s.ellipsise(10, ‘middle’, ‘pony’));
    // Alerts “Jackdponyuartz”[/sourcecode]

    The code

    [sourcecode language=’javascript’]String.implement({
    ellipsise: function(toLength, where, ellipsis) { // Where is one of [‘front’,’middle’,’end’] — default is ‘end’
    if (toLength < 1) return this; ellipsis = ellipsis || '\u2026'; if (this.length < toLength) return this; switch (where) { case 'front': return ellipsis + this.substr(this.length - toLength); break; case 'middle': return this.substr(0, toLength / 2) + ellipsis + this.substr(this.length - toLength / 2) break; case 'end': default: return this.substr(0, toLength) + ellipsis; break; } } });[/sourcecode]If you're not using MooTools, you can use this variant instead:[sourcecode language='javascript']String.prototype.ellipsise = function(toLength, where, ellipsis) { // Where is one of ['front','middle','end'] -- default is 'end' if (toLength < 1) return this; ellipsis = ellipsis || '\u2026'; if (this.length < toLength) return this; switch (where) { case 'front': return ellipsis + this.substr(this.length - toLength); break; case 'middle': return this.substr(0, toLength / 2) + ellipsis + this.substr(this.length - toLength / 2) break; case 'end': default: return this.substr(0, toLength) + ellipsis; break; } }[/sourcecode]