Modifying CSS class property values on the fly with JavaScript / jQuery

103,598

Solution 1

Demo, IE demo

You could use the following function:

function setStyle(cssText) {
    var sheet = document.createElement('style');
    sheet.type = 'text/css';
    /* Optional */ window.customSheet = sheet;
    (document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);
    return (setStyle = function(cssText, node) {
        if(!node || node.parentNode !== sheet)
            return sheet.appendChild(document.createTextNode(cssText));
        node.nodeValue = cssText;
        return node;
    })(cssText);
};

Features:

  • The function is written in vanilla-js, so it has better performance than jQuery alternatives
  • One stylesheet is created after the first call to setStyle, so if you don't call it, it won't create any stylesheet.
  • The same stylesheet is reused for the following calls of setStyle
  • The function return a reference to the node associated with the bunch of CSS that you have added. If you call the function again with that node as a second argument, it will replace the old CSS with the new one.

Example

var myCSS = setStyle('*{ color:red; }');
setStyle('*{ color:blue; }', myCSS); // Replaces the previous CSS with this one

Browser support

At least, it works on IE9, FF3, Chrome 1, Safari 4, Opera 10.5.

There's also an IE version which works both on modern browsers and old versions of IE! (Works on IE8 and IE7, but can crash IE6).

Solution 2

Nice question. A lot of the answers here had a solution directly contradicting what you were asking

"I know how to use jQuery to assign width, height, etc. to an element, but what I'm trying to do is actually change the value defined in the stylesheet so that the dynamically-created value can be assigned to multiple elements.
"

jQuery .css styles elements inline: it doesn't change the physical CSS rule! If you want to do this, I would suggest using a vanilla JavaScript solution:

document.styleSheets[0].cssRules[0].cssText = "\
     #myID {
         myRule: myValue;
         myOtherRule: myOtherValue;
     }";

This way, you're setting the stylesheet css rule, not appending an inline style.

Hope this helps!

Solution 3

Like @benvie said, its more efficient to change a style sheet rather than using jQuery.css (which will loop through all of the elements in the set). It is also important not to add a new style to the head every time the function is called because it will create a memory leak and thousands of CSS rules that have to be individually applied by the browser. I would do something like this:

//Add the stylesheet once and store a cached jQuery object
var $style = $("<style type='text/css'>").appendTo('head'); 

function onResize() {
    var css = "\
        .someClass {\
            left:   "+leftVal+";\
            width:  "+widthVal+";\
            height: "+heightVal+";\
        }";

    $style.html(css);
}

This solution will change your styles by modifying the DOM only once per resize. Note that for effective js minification and compression, you probably don't want to pretty-print the css, but I did for clarity.

Solution 4

Use jquery to add a style override in the <head>:

$('<style>.someClass {color: red;} input::-webkit-outer-spin-button: {display: none;}</style>')
.appendTo('head'); 

Solution 5

I've got a solution for changing a value in specific CSS class. But it only works if you keep your CSS in the tag. If you just keep a link to your CSS from external files ex.

<style src='script.js'></style>

this solution won't work.

If your css looks like this for example:

<style id='style'>
.foo {
height:50px;
}
</style>

You can change a value of the tag using JS/jQuery.

I've written a function, perhaps it's not the best one but it works. You can improve it if you want.

function replaceClassProp(cl,prop,val){

if(!cl || !prop || !val){console.error('Wrong function arguments');return false;}


// Select style tag value

var tag = '#style';

    var style = $(tag).text();
    var str = style;

// Find the class you want to change
    var n = str.indexOf('.'+cl);
    str = str.substr(n,str.length);
    n = str.indexOf('}');
    str = str.substr(0,n+1);

    var before = str;

// Find specific property

    n = str.indexOf(prop);
    str = str.substr(n,str.length);
    n = str.indexOf(';');
    str = str.substr(0,n+1);

// Replace the property with values you selected

    var after = before.replace(str,prop+':'+val+';');
    style=style.replace(before,after);

// Submit changes

    $(tag).text(style);

}

Then just change the tag variable into your style tag id and exegute:

replaceClassProp('foo','height','50px');

The difference between this and $('.foo').css('height','50px'); is that when you do it with css method of jQuery, all elements that have .foo class will have visible style='height:50px' in DOM. If you do it my way, elements are untouched and the only thing youll see is class='foo'

Advantages

  • Clear DOM
  • You can modify the property you want without replacing the whole style

Disadvantages

  • Only internal CSS
  • You have to find specific style tag you want to edit

Hope it helps anyhow.

Share:
103,598
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I've run into a unique situation that I have so far been unable to find a solution for: dynamically assigning a value to a CSS style. I know how to use jQuery to assign width, height, etc. to an element, but what I'm trying to do is actually change the value defined in the stylesheet so that the dynamically-created value can be assigned to multiple elements.

    What I'm building is a slideshow of images that occupy the full viewport, recalculating the image's width, height, and left properties on resize so that the image is always centered, favors width over height, except when the viewport is taller than it is wide (resizing does not reload the page, just fires a function to resize the image).

    I have successfully been able to get it to work on one image, and now I'm trying to determine the best way to assign those property values to all images in the slideshow without having to specify those three things individually for every image.

    My Question:

    Can the values of properties in a class be modified on the fly? I'm sure the answer is out there, I'm probably just not using the correct terminology in my searches. Hope I did a good job of describing the problem. TIA.

  • Oriol
    Oriol over 10 years
    Because it's very inefficient
  • Oriol
    Oriol over 10 years
    +1 Your answer is much better than the others which use $('.myClass'). But yours could have a bad performance too if used lots of times (see Brian Peacock's answer)
  • Bort
    Bort about 9 years
    I an unable to see any effect. Oriol's solution works but this one doesn't. My code is: document.styleSheets[0].cssRules[0].cssText = ".myClass{ background-color:red; }"; I don't get an error, but nothing is changed. Tried in Chrome 48 and IE8. What am I doing wrong?
  • Gik
    Gik almost 9 years
    cssText is IE only. :-(
  • Blessed Geek
    Blessed Geek over 7 years
    This answer is contrary to the browsers I am using and developing for.
  • Serj Sagan
    Serj Sagan over 6 years
    Also, this applies the style directly to the element, so if you add other elements with this class to the DOM, the above jQuery will need to be rerun to see those effects.