6

Let's say we have defined a CSS class that is being applied to various elements on a page.

colourful
{
    color: #DD00DD;
    background-color: #330033;
}

People have complained about the colour, that they don't like pink/purple. So you want to give them the ability to change the style as they wish, and they can pick their favourite colours. You have a little colour-picker widget that invokes a Javascript function:

function changeColourful(colorRGB, backgroundColorRGB)
{
    // answer goes here
}

What goes in the body of that function?

The intent being that when the user picks a new colour on the colour-picker all the elements with class="colourful" will have their style changed.

Axel
  • 213
  • 1
  • 2
  • 7

9 Answers9

8
var setStyleRule = function(selector, rule) {
    var stylesheet = document.styleSheets[(document.styleSheets.length - 1)];
    if(stylesheet.addRule) {
        stylesheet.addRule(selector, rule)
    } else if(stylesheet.insertRule) {
        stylesheet.insertRule(selector + ' { ' + rule + ' }', stylesheet.cssRules.length);
    }
};
eyelidlessness
  • 62,413
  • 11
  • 90
  • 94
7

I would actually implement this server-side; just store the user's preferred colours in their session (via cookies or whatever is nice and easy for you) and generate the CSS dynamically, i.e.

colourful {
  color: ${userPrefs.colourfulColour};
  background-color: ${userPrefs.colourfulBackgroundColour};
} 

If it really suits you much better to do this via Javascript, you can manipulate the CSS using Javascript. See, for instance:

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
alex
  • 5,213
  • 1
  • 24
  • 33
  • 2
    If you go sever-side, isolate the server-dependent items from the rest of the styles, so that the browser can still cache the rest of your style sheet. – Joel Coehoorn Nov 05 '08 at 18:12
  • You may also need to include a cache-breaker in the server-generated css. – Joel Coehoorn Nov 05 '08 at 18:15
  • couldn't agree more - you definitely want this to be server side and in paths away from cachable/static css rules – danpickett Nov 05 '08 at 22:00
  • This is a great answer for a server-side solution. I had tried to set-up the question as a sort of general "tweaking css with javascript", which is why EndangeredMassa got the green check. Somebody should ask the question that goes with this answer. – Axel Nov 07 '08 at 14:28
  • What about dynamic redefinition without reload? :) – volter9 Nov 22 '14 at 22:05
4

I don't know about manipulating the class directly, but you can effectively do the same thing. Here's an example in jQuery.

$('.colourful').css('background-color', 'purple').css('color','red');

In plain javascript, you would have to do more work.

EndangeredMassa
  • 17,208
  • 8
  • 55
  • 79
  • This is what I was looking for (though the `'purple'` and `'red'` should be `backgroundColorRGB` and `colorRGB` respectively) – Axel Nov 06 '08 at 16:00
  • 1
    I'm glad to help! The purple/red stuff was just for example purposes. You wouldn't want me to do all the work, would you? (I kid. I kid.) – EndangeredMassa Nov 06 '08 at 16:27
4

I just tried using an empty <style> tag in the <head>, then filling it dynamically. Seems to work in ff3, at least.

So :

In the <head> , insert something like :

<style id="customstyle" type="text/css"></style>

Now you can use something like jquery to replace or append its content :

for replacing :

$("#customstyle").text(".colourful { color: #345 ; }");

appending :

 $("#customstyle").append(".colourful { color: #345 ; }");

If you want to save it somewhere, just grab the content :

  var csscontent =  $("#customstyle").text();

.. then you could send it back to server through ajax.

vincent
  • 6,368
  • 3
  • 25
  • 23
3

jQuery:

function changeColourful(colorRGB, backgroundColorRGB)
{
    $('.colourful').css({color:colorRGB,backgroundColor:backgroundColorRGB});
}

If you wanted the changes to persist across pages you would would have to store them in a cookie and reapply the function every time.

Ken
  • 77,016
  • 30
  • 84
  • 101
2

First check if document.styleSheets is defined (see @alex's response).

If not, this question should be helpful:
Get All Elements in an HTML document with a specific CSS Class

See the link in the accepted answer and my response at the bottom.

This is only one piece of the answer. You'll still have to go and apply the new values use each element's style property.

Community
  • 1
  • 1
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
2

Quick example for a specific div/colour - which could be dynamically passed in via a function

document.getElementById('Your Div Name Here').style.background = 'white';

Or, to change the class of the specified item

document.getElementById('Your Div Name Here').classname = 'newclassname'

That's assuming you can specify the divs in this way, if not, a combination of this and the node looping solution Kevin showed should do the trick

1

This is a complete example to change a background-image into a stylesheet. First part locate the right stylesheet. Here, I wanted the last one, whose href contained "mycss.css". You can also use the title property.

Second part locate the right rule. Here, I put a marker "MYCSSRULE" so I can locate the right rule.

The css rule in the mycss.css is: #map td, MYCSSRULE { background-image:url("img1.png"); }

The third part just alters the rule.

This process does not work with internet explorer 6. (IE 8 is ok). Works with Firefox 3 and Webkit.

Hope it helped.

function changeBgImg(newimage) {
  var i,n;
  var ssheets = document.styleSheets;         // all styleSheets. Find the right one
  var ssheet;

  // find the last one whose href contain "myhref"
  n = ssheets.length;
  for (i=n-1; i>=0 ;i--) {
    var thisheet = ssheets[i];
    if ( (null != thisheet.href) && (thisheet.href.indexOf("mycss.css") != -1) ) {
      ssheet = thisheet; break;
    }
  }

  if ( (null == ssheet) || ("undefined" == typeof(ssheet.cssRules))) {
    // stylesheet not found or internet explorer 6
    return;
  }

  // find the right rule
  var rule;
  n = ssheet.cssRules.length;
  for (i=0; i<n; i++) {
    var r = ssheet.cssRules.item(i);
    if (typeof(r.selectorText) == "undefined") { continue; }
    if (r.selectorText.indexOf("MYCSSRULE") != -1) {
      rule = r; break;
    }
  }

  if (null == rule) {
    // not found
    return;
  }

  rule.style.backgroundImage = "url(" + newImage + ")";
}
megar
  • 494
  • 5
  • 7
-1

Something like

function changeColourful(colorRGB, backgroundColorRGB)
 {changeColor (document, colorRGB, backgroundColorRGB)}

function changeColor (node, color, changeToColor)
{
   for(var ii = 0 ; ii < node.childNodes.length; ii++)
   {
     if(node.childNodes[ii].childNodes.length > 0)
     {
        changeColor(node.childNodes[ii], color, changeToColor);
     }

      if(node[ii].style.backgroundColor == color)
      {
        node[ii].style.backgroundColor = changeToColor;
      }

   }


}
kemiller2002
  • 113,795
  • 27
  • 197
  • 251