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.
myVar = document.getElementsByClassName("description-text");
document.getElementsByClassName
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.
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.).
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
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