Tuesday, August 16, 2011

Faking Custom CSS Properties

I ran into a situation today where I really needed to create my own, custom CSS property.  For example:

.myclass {
   my-property: 0;
}

Essentially, I needed a presentation value that was related to other elements on the page, but could not be derived or calculated based on those elements.  In an effort to keep presentation separate from code, I wanted custom CSS properties.  While I won't go into explaining exactly why I needed the custom property, I will show you how I accomplished the task:

HTML
<div id="foo">hello</div>

CSS

#foo {
   background: url('images/spacer.gif?bar=411');
}

JavaScript
getCustomCSSProperty('foo', 'bar');

Supporting JavaScript Functions
function getCustomCSSProperty(elId, propName)
{
    var obj = document.getElementById(elId);
    var bi = obj.currentStyle ? obj.currentStyle.backgroundImage : document.defaultView.getComputedStyle(obj, null).getPropertyValue('background-image');
    var biurl = RegExp('url\\(["\\\']?([^"\\\']+)["\\\']?\\)').exec(bi);
    return getParameterByName(propName, biurl[1]);
}

function getParameterByName(name, qs) {
    var match = RegExp('[?&]' + name + '=([^&]*)').exec(qs);
    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

Demo

How It Works
Basically, I use the query string of a background image URL to store my custom CSS properties. Each key of the query string equals a custom CSS property. I set the background image to a 1x1 transparent pixel so that a valid request is made to my website and a very small transfer needed.  By specifying a static resource, I can rest assured that the query string will be ignored by the web server (most web servers are configured to ignore the query string for static content and return the resource).  I use a little JavaScript to access the background image property of the element, parse the string to extract my property value and voila!

If the element I'm styling really needs a background image, I'll simply add my query string to the URL of the real image.

Caveats
  • A request must be made for each unique string of custom CSS properties since the browser considers each URL to be unique (i.e. "images/spacer.gif?bar=411" vs "images/spacer.gif?bar=911"). Caching will come into play after the first request though.
  • You must URL encode the name/value pairs in the query string.
  • You could conceivably run into namespace issues with your query string if you really need to use a background image on the element and require a legitimate query string on the URL to retrieve the image.

Alternative Solution
There is a jQuery plugin that lets you craft custom CSS properties. It is a much more extensive, powerful solution allowing you to include script in your CSS: http://bililite.com/blog/2009/01/16/jquery-css-parser/

Advantages of my solution over the jQuery CSS Parser
  • No jQuery library necessary. Only a little JavaScript is needed.
  • The CSS remains valid (although the jQuery parser does allow its properties to be enclosed in comments).


No comments:

Post a Comment