3

I would like to use JavaScript to manipulate my CSS. First it was just thought to be a nice little script to try out different colors for my accordion menu together with different backgrounds/title-/content-/... background-colors from an input field.

I understand how I get the input value with js.

I understand how CSS is manipulated by using getElementById(), getElementsByClassName(), getElementsByTag(), and getElementsByName().

Now, the problem is that my CSS looks like this:

.accordion li > a {
  /* some css here */
}
.sub-menu li a {
/* some css here */
}
.some-class hover:a {
/* css */
}
.some-other-class > li > a.active {
/* css */
}

How would I change the properties of such stylings with JavaScript?

tshepang
  • 12,111
  • 21
  • 91
  • 136
qsi
  • 683
  • 1
  • 7
  • 16
  • css is not manipulated with `getElementById()` `getElementsByClassName()` `getElementsByTag()` `getElementsByName()` – Jay Harris Jul 03 '13 at 16:04
  • this is a completely pointless question. this is what css is for, why go the other way? – Jay Harris Jul 03 '13 at 16:08
  • If you want to manipulate stylesheets, you better start by reading about [`styleSheets`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet). – Teemu Jul 03 '13 at 16:12
  • to be a bit clearer: I know how I can manipulate my css properties using getElement(s)By... as long as their not as the example above. How would I change (for example:) the background-color of "sub-menu li a" using js? – qsi Jul 03 '13 at 17:24

3 Answers3

4

There's no way to manipulate some CSS styles directly with JavaScript. Instead you can change a rule in a stylesheet itself, something like this:

var changeRule = function(selector, property, value) {
        var styles = document.styleSheets,
            n, sheet, rules, m, done = false;
        selector = selector.toLowerCase();
        for(n = 0; n < styles.length; n++) {
            sheet = styles[n];      
            rules = sheet.cssRules || sheet.rules;
            for(m = 0; m < rules.length; m++) {
                if (rules[m].selectorText.toLowerCase() === selector) {
                    done = true;
                    rules[m].style[property] = value;
                    break;
                }
            }
            if (done) {
                break;
            }
        }
    };
changeRule('div:hover', 'background', '#0f0');

selector must match exactly an exisiting selector, only spaces between selector text and { are ignored.

You can develope the code to find and change partial hits of selector names, or just check a particular stylesheet instead of all of them. As it is, it's also quite expensive when having tens of stylesheets with thousands of rules.

Unfortenately pseudo elements can't be manipulated with this snippet.

A live demo at jsFiddle.

Teemu
  • 22,918
  • 7
  • 53
  • 106
1

All DOM elements have a style object that can be altered by JavaScript

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.style?redirectlocale=en-US&redirectslug=Web%2FAPI%2Felement.style

Or if you're using jQuery:

http://api.jquery.com/css/

You can target elements and manipulate their propertoes, but you do not alter the rules.

A common approach if you want to alter large numbers of style properties is to alter elements' class names to change their appearance. This can be done with the className property, or if you're using jQuery: addClass and removeClass.

Tim
  • 8,036
  • 2
  • 36
  • 52
0

I've implemented Teemu's answer with underscore. http://jsfiddle.net/6pj3g/4/

var rule = _.chain(document.styleSheets)
    .map(function(sheet){return _.flatten(sheet.cssRules)})
    .flatten()
    .unique()
    .find(function(rule){ return rule && rule.selectorText && (rule.selectorText.toLowerCase() === selector.toLowerCase())})
    .value()

if (rule){
    rule.style[property] = value;
} else {
    throw 'selector not found: ' + selector;
}
javajosh
  • 510
  • 5
  • 12