where do I download?
You can always grab the project from Google Code or from here.

The class requires mootools 1.2 with Element and Class (weighs in at 24.7 KB). You can easily convert it to mootools 1.1 or another library. You can use the code as you see fit, so long as you link back to this page.

There are 2 flavors available. The regular code (weighs in at 2.96 KB) and the compressed code (weighs in at 1.38 KB).

Current version stands at 1.0, so no older versions available.
what is it?
This is a pretty simple class for the mootools library inspired by this post on the mootools forum. It adds a style element to the DOM, which is generated using the input you provide. This modifies the appearance of the page.
how does it help?
So, apparently it would be nice to be able to do certain things with CSS. Traditionally, these sorts of things are done on the server side using a server side language (like PHP) that generates CSS every time you hit the page. Wouldn't it be nice to do it on the client side? As the page loads and after, as the user interacts with it?

I think we can break down the usefulness of the technique into three categories:
  1. Programmatic CSS
  2. Browser Compatibility
  3. Custom CSS Properties
With programmatic css, you can use loops to generate CSS that might have taken pages to type out. You can have CSS constants. You can do all sorts of math and calculations for a property. You can also modify the style of elements on the fly, without using javascript on each element. I'm sure there's other cool stuff you can do that I didn't think of.

Browser compatibility is sort of self-obvious. Before, you used to have a style sheet for each browser to allow for their quirks and weird CSS implementation. Now you can generate CSS that is browser specific using JS. The class is built to allow you to extend it for any browser and any property. You can specify a property to be limited, in which case it will only generate it for the browser you specify.

Ever wanted to invet your own CSS property? Now you can. See the examples for what I mean.
how do you use it?
All of these examples are already implemented on this page, so you can take a look at the source code to see the actual code used.

Let's start off with something simple. Let's make this sentence bold. Let's make this sentence big. Let's make this sentence bold and big.

html
<span class="bold">Let's make this sentence bold.</span>
<span class="big">Let's make this sentence big.</span>
<span class="bb">Let's make this sentence bold and big.</span>

javascript
var css = new CSS();
css.add_rules({
    'span.bold, span.bb':
    {
        'font-weight': 'bold'
    },
    'span.big, span.bb':
    {
        'font-size': 'x-large'
    }
}).refresh();

So what's the big deal, right? I can do that with regular CSS. Yeah, but try removing the classes entirely from the page without touching each element and keeping the other classes intact. Now the sentences are back to normal.

html
<span class="a" onclick="css.remove_rules(['span.bold, span.bb', 'span.big, span.bb']).refresh();">removing the classes</span>

Now that we're getting somewhere, let's imagine for loops, constants, math, etc. all based on user behavior, browser, layout choices, etc. All of it dynamic.

Let's take a look at a practical example. Take a look all the way at the bottom of the page. See those badges? Aren't they pretty? They're actually just one image used as a background on anchors. You don't want to hammer your server for a dozen images. It slows things down for the user and on the server ... but if you have a lot of images that you combine into one to display partially using the background property, that will require a lof of CSS. You need to define the offset for each anchor. That sucks. Let's try this:

javascript
var url = '/_library/image/badge/credits.gif', badges = '', hover = '', rules = {};

for(var i = 0; i != 8; i++)
{
    var badge = (badges ? ', ' : '') + 'A#badge_' + i;

    badges += badge;
    hover += badge + ':hover';

    rules['A#badge_' + i] = {
        'background': 'url(' + url + ') -' + (i * 80) + 'px',
        'float': (i < 3 ? 'left' : 'right'),
        'margin': (i < 3 ? '0px 8px 0px 0px' : '0px 0px 0px 8px')
    };
}

rules[badges] = {
    display: 'block',
    opacity: 0.50,
    width: '80px',
    height: '28px'
};
rules[hover] = {
    opacity: 1.00
};

css.add_rules(rules).refresh();

If we take a look at the code, we're not only incrementing the background property by 80 pixels on each loop, but we're also setting the margin and the float property based on what iteration we're on, so that everything displays properly. We also set the hover property so that the opacity changes when you hover over the anchor ...

Speaking of which, let's talk about opacity. If you use the class without any changes, opacity will work fine in Firefox, Safari, and Opera ... but it won't work in IE. IE doesn't have an opacity property. You need to use a filter to get the same effect. So let's add this anywhere in the code before we use the class:

javascript
CSS.implement({
    'trident_opacity': function(value, property)
    {
        return ['filter', 'alpha(opacity=' + (value * 100) + ')'];
    }
});

Now that we added the code, any time that we specify the opacity property, our class will properly generate the opacity css for all browsers.

The format we use here is the engine name + '_' + property name. The class will default to whatever you define. Obviously, your function should spit back an array, with the property at the first index and the value at the second.

Now that we're done picking on IE, let's pick on Firefox and Safari. The good: they defined the CSS3 property for making things with rounded corners. The bad: they did it by using proprietary extensions. This gets a bit more complicated:

javascript
CSS.implement({
    local:
    {
        limited: ['border-radius']
    },

    'gecko_border-radius': function(value, property)
    {
        return ['-moz-' + property, value];
    },

    'webkit_border-radius': function(value, property)
    {
        return ['-webkit-' + property, value];
    }
});

All we're doing here is sticking their proprietary '-webkit-' or '-moz-' before the property. We no longer have to worry about that garbage since the class will take care of it for us and we can use the property 'border-radius'. Notice that we added 'border-radius' to the limited array in the class. That's to identify the 'border-radius' property as limited to a select few browsers. IE and Opera don't have this property, so we don't want to define it for them. Any property inserted into the limited array that doesn't have a function explicity defined for the browser being used will not be inserted into our stylesheet, which is just the way we want it. Remember we didn't insert the 'opacity' property into the limited array ... that's because it is defined for every browser, in some form.

You can actually end up building a compatibility library using this small class. To get started, take a look at: Now that we're sick of compatibility, let's move on to inventing our own properties. I normally have my dpi set to 120 since I use a high resolution monitor. IE seems to scale text to a larger setting when you set a higher dpi. That's nice and makes things readable, but my layout will look completely different on other browsers. So let's try this:

javascript
CSS.implement({
    local:
    {
        limited: ['dpi']
    },

    'trident_dpi': function(value, property)
    {
        return ['font-size', ((96 / window.screen.deviceXDPI) * value).round() + '%'];
    }
});

I can use the function by css.add_rule('body', {dpi:100}).refresh() and now my text will look normal in IE.

There are more fun things you can do with the class, but this should get you started. External methods for the class are destroy, refresh, add_prop, add_rule, add_rules, remove_prop, remove_rule, and remove_rules. You can figure out how to use all of them pretty easily by looking at the code.
any tips?
Just one for now. There is an option for the class called 'rules' that you can use like this:

javascript
var css = new CSS({
    rules:
    {
        "BODY, INPUT, SELECT, TEXTAREA":
        {
            "dpi": 100
        },
        "SPAN.a IMG, DIV.window_lucid IMG, DIV.veil":
        {
            "opacity": 0.50
        },
        "A SPAN, DIV.translucent":
        {
            "opacity": 0.75
        },
        "SPAN.a IMG:hover, DIV.window_lucid IMG:hover":
        {
            "opacity": 1.00
        },
        "A SPAN":
        {
            "border-radius": '5%'
        }
    }
}).refresh();

Kind of makes everything look more like a stylesheet. Also, try to put everything as high in the page as you can in a single block, before you define your static CSS. This way the browser doesn't have to refresh the content multiple times. Use refresh() as few times as possible.
contact?
Need to contact me for some reason? Have a suggestion? Something is broken? My name is Marat Denenberg and you can reach me at maratd@gmail.com
self
execution
modified
agent
/oss/css/index.php
0.02 seconds
June 16 2008 12:08:29
CCBot/1.0 (+http://www.commoncrawl.org/bot.html)