Change CSS class content from javascript [Firefox/

2019-08-04 04:21发布

问题:

I'm working on a firefox addon, and relies heavily on some dynamic changes with javascript. There are some UI elements (hbox/descriptions), which are styled using CSS classes. Now I wish to change the a CSS class defintion from javascript, without having to work element id's. Is it possible ?

Similar questions had been asked before, but most of them are using php to generate a CSS or jquery based changes. Here's an example for my scenario: My XUL :

<box id="firefox-addon-box">
  <description id="description-1" class="description-text"> Some description </description>
  <description id="description-2" class="description-text"> Some description </description>
</box>

My CSS :

.description-text {
  font-size: 15px; 
  color: #fff; 
}

So I wish to change the font-size in description-text class to say, 20px dynamically. Now I know that we can change the style using individual id's, with a getElementById() and changing the style. But here I wish to change a class (which matters to a lot of elements), rather than to work on individual ids. I also know that we can point to another class definition by setAttribute() and change 'class' - this would again require working on individual id's. In reality, I have plenty of UI elements (all pointing to one CSS class), and many values changed in a CSS class. So my question is, is there a way to directly change a CSS class definition from javascript, without having to work on element ids ? Thanks for any help.

回答1:

myVar = document.getElementsByClassName("description-text"); 

document.getElementsByClassName



回答2:

I asked a very similar question last night and figured it out this afternoon, which I have just tested as working on Firefox 29.0b1-49.0a1, may work on earlier versions, not sure about newer versions once XUL is removed (SDK or WebExtensions), but as it is pure JS/DOM/CSS, I think it might work ok.

What I learned was that it is easier than I thought. Essentially, you find the specific style sheet, the specific rule, and edit the "style" of that rule using DOM, just like in HTML.

document.styleSheets[ i ].href
document.styleSheets[ i ].cssRules[ j ].selectorText
document.styleSheets[ i ].cssRules[ j ].style.fontSize

It all starts with the document.styleSheets array-like object, where i is the outer document.styleSheet loop index and j is the cssRules inner loop index.

The href is optional to consider, and is the URI of the style sheet. If known, and if the sheet is not dynamically generated, and if you are certain that the selector you want exists only in that one file, then you can use it to limit searching through all selectors in all the ~10 style sheets that Firefox loads by default, before your add-on's first sheet is ever loaded.

Otherwise, you loop through all document.styleSheets, (optionally skip if href doesn't match), then loop through all the cssRules on each style sheet, and see if the .selectorText matches your desired selector, in the case of the OP: .description-text (note that you need the leading . or # etc, exactly as it appears in the CSS file, for classes or IDs, etc).

When you find the selector you want, then you can modify the .style object (well documented at W3Schools DOM Style Object). In the OP example, we want to change the font-size style to 20px, which would be .style.fontSize = '20px'.

Using these fundamentals, a more generic function can be crafted, to more easily reuse. Perhaps a getCSSrule function which takes a required selector and an optional href argument, which will help you by getting the sheet and rule you want. Perhaps a getCSSsheet function if you want to use just the href to get a sheet. Perhaps a setStyle function to set the style and value. Perhaps a set of delCSSsheet and delCSSrule functions if you want to discard these rather than modify. And also an insCSSsheet and insertCSSrule function, maybe a createCSSsheet and createCSSrule as well.

This url (Totally Pwn CSS with Javascript), despite the name, and defunct Web Archive only status, and being 9 years old or more, is actually still relevant.



回答3:

I will refrain from advising in favour of this method, but it is possible to also directly add css rules (or more complex remove them) doing the following

var css = '.description-text { font-size: 100px; }',
    head = document.getElementsByTagName('head')[0],
    style = document.createElement('style');

style.type = 'text/css';
if (style.styleSheet){
  style.styleSheet.cssText = css;
} else {
  style.appendChild(document.createTextNode(css));
}

head.appendChild(style);

There are rare occasions where this is a possible way to go and many situations where this is not the proper thing to do. You should never do this if you plan on overwriting the same thing multiple times (except if you remove the old rule first) and should only do this if you will use some other feature of CSS which builds upon this (e.g. new elements getting properly styles, 3rd party content getting properly styled, css animations, etc.).



回答4:

I had to do the same few months ago. I solved it with jQuery with .addClass() and .removeClass() and more http://api.jquery.com/category/css/

Or if you want only Javascript use the HTML DOM from pure Javascript. Official documentation about that with examples: http://www.w3schools.com/js/js_htmldom_css.asp



回答5:

Using JQuery you could use the css property :

$(".description-text").css({backgroundColor: "#ffe", borderLeft: "5px solid #ccc" });

All your elements that use the description-text class will be affected

Documentation of jquery css property

EDIT

Or with pure javascript

var elements = document.getElementsByClassName('description-text');

for(var i=0; i<elements.length; i++){
    elements[i].style.backgroundColor = "#ffe";
    elements[i].style.borderLeft = "5px solid #ccc";
    //any style you want to apply
}

Documentation of javascript style