tags:

views:

243

answers:

5

Hi Guys,

Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)

This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.

+6  A: 

You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript.

I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.

Alexander Gyoshev
That's pretty cool! I had no idea you could do that stuff. Looks pretty advanced, though. And I can't really see a good use for it if you got a good framework like Prototype or jQuery, that will do most of that work for you...But still nice to know. Bookmarked for future reference (: +1
peirix
Here's a good use: http://stylebuilder.telerik.com/ :P And yes, it's advanced - using jQuery is probably much more suitable for the situation ;)
Alexander Gyoshev
Here's some references from MDC:https://developer.mozilla.org/en/DOM/document.styleSheetshttps://developer.mozilla.org/En/DOM/Stylesheet
Fábio
A: 

your best bet for easy cross-browser compatibility is to use a library like jQuery. With jQuery you can simply do:

<script src="http://code.jquery.com/jquery-latest.js"&gt;&lt;/script&gt;
<script type="javascript/text">
    $(function(){   
        $('.className').click(function(){
             $(this).css("property", "setting");
        })
    })
</script>
contagious
A: 

While setAttribute is nice, there is a standard way of doing this across most browsers:

htmlElement.className = 'someClass';

To do it over many elements, you will need a cross browser solution:

function getElementsByClassName( className, context, tagName ) {
  context = context || document;
  if ( typeof context.getElementsByClassName === 'function' )
    return context.getElementsByClassName( className );

  if ( typeof context.getElementsByTagName !== 'function' )
    return [];

  var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
    context.getElementsByTagName('*'),
  ret = [];
  for ( var i = 0, il = elements.length; i < il; i++ )
    if ( elements[ i ].className.match( className ) )
      ret.push( elements[ i ] );

  return ret;
}

var elements = getElementsByClassName('someClass');

for ( var i = 0, il = elements.length; i < il; i++ )
  elements[ i ].className = 'newClass';

You may want to replace the line:

if ( elements[ i ].className.match( className ) )

With some Regular Expression, but you will have to escape special characters in that case.

Tim
A: 

Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.

.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#waraper.bar .yourclass { color: blue }

then you can just use

document.getElementById('wrapper').className='foo';

(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.

((parenthetically) is there any way to stop the SO formatter from assuming stuff starting with a # is a comment?)

Pete Jordan
+3  A: 

The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.

David Dorward