jQuery CSS Abstraction

Avatar of Chris Coyier
Chris Coyier on (Updated on )

It should be said, first and foremost, that you should try to keep your styling and your JavaScript away from each other. If you want to change the style of an element with JavaScript, add (or remove) a class name from the element. Then use that class name as your hook in the CSS to affect the styling.

However, there are times when you need to apply styling within JavaScript. jQuery has a function just for it:

$("#thing").css("margin-right", 0);

It can even be kind of appealing, because jQuery handles some cross-browser weirdness for you. For example, opacity is one of those things that requires a variety of CSS properties to be cross-browser compatible. But with jQuery, you don’t need to apply all of them. Just setting the opacity with the CSS function works. jQuery knows what kind of browser environment it is in and will apply the right property.

// just works
// also alternate CSS syntax
$("#thing").css({
   opacity: 0.5
});

So you might extend that thinking into assuming that jQuery will help you out with other things that require multiple CSS properties to get the same cross browser effect, like the quintessential example of border-radius. We need -moz-border-radius for Mozilla browsers, -webkit-border-radius for WebKit browsers, and border-radius for Opera (and the future). But jQuery doesn’t help us here.

// not gonna help in current Firefox or Safari/Chrome
$("#thing").css({
   "border-radius": "20px"
});

To get cross-browser compatible CSS through jQuery, we’ll still have to list all three:

$("#thing").css({
   "border-radius": "20px",
   "-moz-border-radius": "20px",
   "-webkit-border-radius": "20px"
});

So what’s up with that? David Walsh thinks it would be library bloat to have this abstraction within jQuery. Ben Alman thinks jQuery should handle fully supported CSS properties (the border-radius spec isn’t officially final). Screwlewse thinks that the only reason opacity is supported that way is because it’s required for animation (core functions like fadeToggle).

I’m not sure what I think 100%. On one hand it sure would be nice to have that handled magically for me. On the other I can understand the bloat and not-final-spec arguments.

What do you think?

If you have found yourself needing to apply rounded corners through jQuery, you might be smart to abstract it away into a little plugin for yourself.

$.fn.roundThis = function(radius) {
    return this.each(function(e) {
        $(this).css({
           "border-radius": radius,
           "-moz-border-radius": radius,
           "-webkit-border-radius": radius
        });  
    }); 
};

$(function() {

    // usage
    $("#thing-that-will-become-rounded").roundThis("20px");

});

This still won’t handle IE though, but there are great plugins that do.


In other news: Congratulations to Brent Traut for winning the free jQuery Conference ticket from my little contest. There were ten people who entered who donated a total of $115 to open source projects. Pseudo-random number generation picked the winner. If you were still thinking of coming, you should! And if you were still thinking about donating to open source, you should!