Dynamic modification of CSS rules

I have been recently involved in a discussion about modifying styles for HTML elements: usually it happens by changing the class attribute of an element from one style rule to another, which are typically similar, differing only for one declaration or two — but, I was asked, would it be possible to directly modify CSS rules themselves?

During some recreational time, I did a little research and found that the W3C has designed DOM Level 2 CSS interfaces with the goal of exposing Cascading Style Sheets constructs to object model consumers. Those of course include JavaScript, and by browsing the W3C specification I was able to play on the document by using the objects defined in the document itself. (Thank you, Firebug!)

The document object defines a styleSheets property, which can be indexed to retrieve StyleSheet objects representing the single style sheet linked by the HTML document. In particular, I was interested to the spec.css sheet, which I picked up by writing:

specCSS = document.styleSheets[0]

By using the cssRules attribute of a StyleSheet object, it is possible to retrieve an object which can later be indexed to pick a single CSSStyleRule contained in the style sheet. I cheated a bit by looking at an “interesting” rule I could try to modify, exploiting the View CSS function of the Web Developer Toolbar, and chose the rule for styling IDL definitions in the specification. It was the second rule in the sheet, so I took it by writing:

idlCode = specCSS.cssRules[1]

That CSSStyleRule object defines a style attribute which is an indexed object containing style definitions for that rule. IDL definitions in W3C specification documents are written in black, and the corresponding style is defined in the rule for the .idl-code class I retrieved. So, to change it, I just typed:

idlCode.style.color = 'yellow'

and instantly Firefox let me see code in IDL definitions painted in yellow. (Yellow on gray, that is… so, well, it wasn’t that visible at all.)

I had changed an existing style definition in a rule; what about then changing the rule by introducing a new style definition? I used Firebug’s dir on the idlCode.style object, and found the name of another “interesting” property to dynamically modify, that is the font size. The result of the following command:

idlCode.style.fontSize = '30px'

was to expand code in IDL definitions up to 30 (yellowish) pixels.

To answer that initial question, then: yes, CSS rules can be dynamically modified. I still consider more elegant to define two different rules and just change an element’s class, however; and I have still to be showed an example where dynamically changing CSS rules is useful to be sold on that technique.

~ by Giulio Piancastelli on March 19, 2007.

6 Responses to “Dynamic modification of CSS rules”

  1. I think that we HAD a nice example, in that initial discussion, but I’ll try to re-formulate in a more abstract terms: suppose you would like to associate a more “semantic” interpretation, like “class paper-titles is the style for paper titles”. What you do in this case is to create classes “paper-title-1″, “paper-title-2″, etc, or similar variation (say, “paper-title-large”, “paper-title-small”, etc.) for any variation of the style you would need according to different situations / views / users / contexts / etc. This could be many, and without any real connection between them (apart defining them incrementally, in case), which IN PRINCIPLE is a bad thing.

    But if you stop being SO conservative ;) , and think of classes as a mere part of the DOM (more or less), you may think as doing a different thing: just having one class for each “abstract entity”, then change the class according to the different situations / views / users / contexts / etc. I do not say it is better IN GENERAL: it could be so in some situations.
    A small example: suppose that ALL classes have to increase their font size when moving from, say, “small view” to “large view” (a session property in a portal). Wouldn’t be great to have a function encapsulating all changes to classes in a single call, and increasing font sizes to all classes?

    Of course many more articulated examples could be made… But to start, this might be enough!

  2. I think it’s not a matter of being conservative: it’s more a matter of understanding how concepts fit in the current web technology models, in order to avoid losing the nice properties that those models earn us. By creating static CSS rules that represent the style each element may have at any given moment, I create a single, well-defined, and authoritative source where style concerns and responsibilities are placed. On the contrary, by dynamically modifying CSS rules (instead of just changing an element’s class), I happen to split up style data: therefore, to recollect the whole style model of a web application, I also need to read through JavaScript files, trying to extract relevant style information obfuscated by JavaScript code.

    If you are willing to lose the separation of concerns that defining static CSS rules earns us, I would very like to know what we are gaining in return. As you said, it may be a trade-off appropriate in some particular situations only; but I’m having a hard time thinking about those special cases, so I’m still unconvinced on the merits of that technique.

    As far as your example is concerned, the functionality exists in any browser as a proper GUI command: for example, in Firefox it is under View > Text Size > [Increase | Decrease]. No need to explicitly involve CSS classes, JavaScript code, or session properties on the server side.

    Indeed, the problems of space and text dimension have always been acknowledged: I have googled a little, and discovered that from 1994 [1] to 2004 [2] there is a clear path in research for making the client support ways to collapse and expand various parts of the web page. As in Firefox’s case, it seems to be the browser’s responsibility, not the web page’s responsibility, to provide mechanisms for adjusting dimensions of content. (In fact, the web page could at most declare styles for different media types.) I believe that the aim is to avoid confusing visitors by providing a uniform and familiar experience on the client device side (including handhelds and PCs) rather than resorting to web developers’ “creative” ways of providing site navigation.

    [1] Hsu, J., Johnston, W., and McCarthy, J. “Active Outlining for HTML Documents: An X-Mosaic Implementation.” In Proc. Second Intl. WWW Conference. 1994.
    [2] Baudisch, P., Xie, X., Wang, C., and Ma, W. “Collapse-to-zoom: viewing web pages on small screen devices by interactively removing irrelevant content.” In Proceedings of the 17th Annual ACM Symposium on User interface Software and Technology. 2004.

  3. Although I am still new at the Javascript DOM CSS thing, I think that when you have things like Google’s GPC, where you don’t have control over the CSS sheet imported for the page, (and it is far too restricted as to what you can do from a design standpoint in my opinion,) then being able to use Javascript to alter things like column widths and such is very useful. I have modified a script from David Flanagan’s “JavaScript The Definitive Guide” to allow better use of the real estate on the screen. Currently I only have it working correctly in Firefox, but I’m still figuring it out. You can see it on my site
    AIScripting – Scripting
    . The original CSS specifies that the main container is 718px wide, considerably less than my screen of 1280px width. I change it to 90% and get the added benefit that I don’t have to scroll back and forth with the window reduced in size.

  4. I think I may have an example for you. Of course, if you think I’m wrong, and have a more elegant solution, I’ve love to hear that too.

    I have a little webapp for a client of mine that helps them sort through a bunch of review objects. They can filter the review objects by a bunch of criteria: the ‘type’ of review object, tags they may have applied to it, etc. Each option is presented as a checkbox.

    This works fine if the review objects are already loaded. The problem is that to speed things up a bit, I made the loading ‘lazy’. Since the review objects are partitioned by type, I made it so that they aren’t loaded via ajax until they are requested.

    There lies the problem. What I did before was iterate through the objects of a given class, and altered the element css. That won’t, however, affect elements that have yet to be loaded. If I could alter the css in the stylesheet, then as they are loaded they pick up the correct properties.

    Yes, I could store the information in some kind of hash, and apply the styles to the elements as they are loaded, but that’s no fun.

    – David

  5. nice article. mmm… i’m facing the problem of dynamically changing style rules (without using a javascript framework) and although it works it is very painful to know the exactly stylesheets and rules indexes. For examples, inside a document with lots of stylesheets and rules, how can I do for selecting a rule using its selector ?

  6. If you want to change rules easily, just use jQuery:

    $(’css-selector’).css(’attribute’,'value’);
    Example:
    $(’#myid span.myclass em’).css(’color’, ‘red’);

    Or, if you want to change multiple properties:

    $(’css-selector’).css({’attribute1′ : ‘value1′, ‘attribute2′ : ‘value2′, ‘attributeN’ : ‘valueN’});
    Example:
    $(’#myid span.myclass em’).css({’background-color’ : ‘yellow’, ‘font-weight’ : ‘bold’});

    You need to download and include in your page the latest version of the jQuery framework from jquery.com for that to work.

    Ok, that doesn’t really modify the CSS rules, but just apply inline styles through DOM manipulation, but the syntax is dead simple plus it’s automatic and seamless, so the effect is the same as if you really modified a class, but it’s much easier to do, since you can use CSS selectors, instead of traversing all CSS classes almost blindingly by using cssRules[1], cssRules[n], etc.

    Hope that helped!

    OMA

Leave a Reply