[jquery] Create a CSS rule / class with jQuery at runtime

Usually I have a CSS file which has the following rule:

#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

How can I avoid creating such a static CSS file by adding the CSS information during runtime actions to the body, or something similar? (only using jQuery)

I want to define it once but with jQuery and use it many times later; that's why I do not want to add it each time to the specific DOM elements.

I know the simple features (css("attr1", "value");), but how can I create a complete reusable CSS rule?

This question is related to jquery css

The answer is


You can use this lib called cssobj

var result = cssobj({'#my-window': {
  position: 'fixed',
  zIndex: '102',
  display:'none',
  top:'50%',
  left:'50%'
}})

Any time you can update your rules like this:

result.obj['#my-window'].display = 'block'
result.update()

Then you got the rule changed. jQuery is not the lib doing this.


You can create style element and insert it into DOM

$("<style type='text/css'> .redbold{ color:#f00; font-weight:bold;} </style>").appendTo("head");
$("<div/>").addClass("redbold").text("SOME NEW TEXT").appendTo("body");

tested on Opera10 FF3.5 iE8 iE6


Here's a setup that gives command over colors with this json object

 "colors": {
    "Backlink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Blazer": ["rgb(240,240,240)"],
    "Body": ["rgb(192,192,192)"],
    "Tags": ["rgb(182,245,245)","rgb(0,0,0)"],
    "Crosslink": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Key": ["rgb(182,245,182)","rgb(0,118,119)"],
    "Link": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link1": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Link2": ["rgb(245,245,182)","rgb(160,82,45)"],
    "Manager": ["rgb(182,220,182)","rgb(0,118,119)"],
    "Monitor": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Monitor1": ["rgb(255,230,225)","rgb(255,80,230)"],
    "Name": ["rgb(255,255,255)"],
    "Trail": ["rgb(240,240,240)"],
    "Option": ["rgb(240,240,240)","rgb(150,150,150)"]
  }

this function

 function colors(fig){
    var html,k,v,entry,
    html = []
    $.each(fig.colors,function(k,v){
        entry  = "." + k ;
        entry += "{ background-color :"+ v[0]+";";
        if(v[1]) entry += " color :"+ v[1]+";";
        entry += "}"
        html.push(entry)
    });
    $("head").append($(document.createElement("style"))
        .html(html.join("\n"))
    )
}

to produce this style element

.Backlink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Blazer{ background-color :rgb(240,240,240);}
.Body{ background-color :rgb(192,192,192);}
.Tags{ background-color :rgb(182,245,245); color :rgb(0,0,0);}
.Crosslink{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Key{ background-color :rgb(182,245,182); color :rgb(0,118,119);}
.Link{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link1{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Link2{ background-color :rgb(245,245,182); color :rgb(160,82,45);}
.Manager{ background-color :rgb(182,220,182); color :rgb(0,118,119);}
.Monitor{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Monitor1{ background-color :rgb(255,230,225); color :rgb(255,80,230);}
.Name{ background-color :rgb(255,255,255);}
.Trail{ background-color :rgb(240,240,240);}
.Option{ background-color :rgb(240,240,240); color :rgb(150,150,150);}

Simply

$("<style>")
    .prop("type", "text/css")
    .html("\
    #my-window {\
        position: fixed;\
        z-index: 102;\
        display:none;\
        top:50%;\
        left:50%;\
    }")
    .appendTo("head");

Noticed the back slashes? They are used to join strings that are on new lines. Leaving them out generates an error.


Maybe you can put the style information in a separate class in your css file, e.g.:

.specificstyle {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

and then use jQuery at the point of your choosing to add this classname to the element?


You can use insertRule if you don't need to support IE < 9, according to dottoro. There's a bit of cross browser code over there as well.

document.styleSheets[0].insertRule('#my-window {\
    position: fixed;\
    z-index: 102;\
    display:none;\
    top:50%;\
    left:50%;\
}', 0)

if you don' t want to assign a display:none to a css class, the right approach in to append to style, jQuery.Rule do the job.

I some cases you want to apply stiles before the append event of ajax content and fade content after append and this is it!


By using .addClass() in jquery we can dynamically add style to elements on page. eg. we have style

.myStyle
{
  width:500px;
  height:300px;
  background-color:red;
 }

Now in ready state of jquery we can add css like .addClass(myStyle)


You could just make a css class called something like .fixed-object that has all your css in it...

.fixed-object{
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}

Then in jquery anytime you want something to have that style just add that class to it...

$(#my-window).addClass('fixed-object');

That seems like the easiest way to do it, unless I'm misunderstanding what you need done.


This isn't anything new compared to some of the other answers as it uses the concept described here and here, but I wanted to make use of JSON-style declaration:

function addCssRule(rule, css) {
  css = JSON.stringify(css).replace(/"/g, "").replace(/,/g, ";");
  $("<style>").prop("type", "text/css").html(rule + css).appendTo("head");
}

Usage:

addCssRule(".friend a, .parent a", {
  color: "green",
  "font-size": "20px"
});

I'm not sure if it covers all capabilities of CSS, but so far it works for me. If it doesn't, consider it a starting points for your own needs. :)


I have been messing with some of this recently and i have used two different approaches when programming an iPhone / iPod site.

The first way I came across when looking for orientation changes so you can see whether the phone is portrait or landscape, this is a very static way but simple and clever:

In CSS :

#content_right,
#content_normal{
 display:none;
}

In JS File:

function updateOrientation(){
  var contentType = "show_";
  switch(window.orientation){
   case 0:
   contentType += "normal";
   break;

   case -90:
   contentType += "right";
   break; document.getElementById("page_wrapper").setAttribute("class",contentType);
}

In PHP/HTML (Import your JS file first then in body tag):

<body onorientationchange="updateOrientation();">

This basically chooses a different pre set CSS block to run depending on the result given back from the JS file.

Also the more dynamic way which I preferred was a very simple addition to a script tag or your JS file:

document.getelementbyid(id).style.backgroundColor = '#ffffff';

This works for most browsers but for IE it's best to take away it's ammunition with something tighter:

var yourID = document.getelementbyid(id); 
 if(yourID.currentstyle) { 
  yourID.style.backgroundColor = "#ffffff";      // for ie :@ 
 } else { 
  yourID.style.setProperty("background-color", "#ffffff");        // everything else :)
 }

Or you can use getElementByClass() and change a range of items.

Hope this helps!

Ash.


you can apply css an an object. So you can define your object in your javascript like this:

var my_css_class = { backgroundColor : 'blue', color : '#fff' };

And then simply apply it to all the elements you want

$("#myelement").css(my_css_class);

So it is reusable. What purpose would you do this for though?


What if you dynamically wrote a < script > section on your page (with your dynamic rules) and then used jQuerys .addClass( class ) to add those dynamically created rules?

I have not tried this, just offering a theory that might work.


Here you have a function to get the full definition of a CSS class:

getCSSStyle = function (className) {
   for (var i = 0; i < document.styleSheets.length; i++) {
       var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
       for (var x = 0; x < classes.length; x++) {
           if (classes[x].selectorText  && - 1 != classes[x].selectorText.indexOf(className)) {
               return classes[x].cssText || classes[x].style.cssText;
           }
       }
   }
   return '';
};

Note that jQuery().css() doesn't change stylesheet rules, it just changes the style of each matched element.

Instead, here's a javascript function I wrote to modify the stylesheet rules themselves.

    /**
     * Modify an existing stylesheet.
     * - sheetId - the id of the <link> or <style> element that defines the stylesheet to be changed
     * - selector - the id/class/element part of the rule.  e.g. "div", ".sectionTitle", "#chapter2"
     * - property - the CSS attribute to be changed.  e.g. "border", "font-size"
     * - value - the new value for the CSS attribute.  e.g. "2px solid blue", "14px"
     */
    function changeCSS(sheetId, selector, property, value){
        var s = document.getElementById(sheetId).sheet;
        var rules = s.cssRules || s.rules;
        for(var i = rules.length - 1, found = false; i >= 0 && !found; i--){
            var r = rules[i];
            if(r.selectorText == selector){
                r.style.setProperty(property, value);
                found = true;
            }
        }
        if(!found){
            s.insertRule(selector + '{' + property + ':' + value + ';}', rules.length);
        }
    }

Advantages:

  • Styles can be computed in a <head> script before the DOM elements are created and therefore prior to the first rendering of the document, avoiding a visually-annoying render, then compute, then re-render. With jQuery, you'd have to wait for the DOM elements to be created, then re-style and re-render them.
  • Elements that are added dynamically after the restyle will automatically have the new styles applied without an extra call to jQuery(newElement).css()

Caveats:

  • I've used it on Chrome and IE10. I think it might need a little modification to make it work well on older versions of IE. In particular, older versions of IE might not have s.cssRules defined, so they will fall back to s.rules which has some peculiarities, such as odd/buggy behavior related to comma-delimited selectors, like "body, p". If you avoid those, you might be ok in older IE versions without modification, but I haven't tested it yet.
  • Currently selectors need to match exactly: use lower case, and be careful with comma-delimited lists; the order needs to match and they should be in the format "first, second" i.e the delimiter is a comma followed by a space character.
  • One could probably spend some additional time on it trying to detect and intelligently handle overlapping selectors, such as those in comma-delimited lists.
  • One could also add support for media queries and the !important modifier without too much trouble.

If you feel like making some improvements to this function, you'll find some useful API docs here: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet


Here is a jquery plugin that allows you to inject CSS:

https://github.com/kajic/jquery-injectCSS

Example:

$.injectCSS({
    "#my-window": {
        "position": "fixed",
        "z-index": 102,
        "display": "none",
        "top": "50%",
        "left": "50%"
    }
});

If you don't want to hardcode the CSS into a CSS block/file, you can use jQuery to dynamically add CSS to HTML Elements, ID's, and Classes.

$(document).ready(function() {
  //Build your CSS.
  var body_tag_css = {
    "background-color": "#ddd",
    "font-weight": "",
    "color": "#000"
  }
  //Apply your CSS to the body tag.  You can enter any tag here, as
  //well as ID's and Classes.
  $("body").css(body_tag_css);
});

You can use a the cssRule plug-in. The code was simple then:

$.cssRule("#my-window {
    position: fixed;
    z-index: 102;
    display:none;
    top:50%;
    left:50%;
}");

One of the comments so far asked why one would want to do such a thing. For example, creating styles for a list where each item needs a distinct background colour (eg. GCal's list of calendars) where the number of columns is not known until run time.


Adding custom rules is useful if you create a jQuery widget that requires custom CSS (such as extending the existing jQueryUI CSS framework for your particular widget). This solution builds on Taras's answer (the first one above).

Assuming your HTML markup has a button with an id of "addrule" and a div with an id of "target" containing some text:

jQuery code:

$( "#addrule" ).click(function () { addcssrule($("#target")); });

function addcssrule(target) 
{ 
var cssrules =  $("<style type='text/css'> </style>").appendTo("head");

cssrules.append(".redbold{ color:#f00; font-weight:bold;}"); 
cssrules.append(".newfont {font-family: arial;}"); 
target.addClass("redbold newfont");     
}       

The advantage of this approach is that you can reuse variable cssrules in your code to add or subtract rules at will. If cssrules is embedded in a persistent object such as a jQuery widget you have a persistent local variable to work with.


In (unusual) cases where you want to be able to dynamically change styles often -- e.g. a theme builder app -- adding <style> tags or calling CSSStyleSheet.insertRule() will result in a growing stylesheet, which can have performance and design debugging implications.

My approach only allows a single rule per selector/property combo, clearing any existing on setting any rule. The API is simple and flexible:

function addStyle(selector, rulename, value) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    var rule = stylesheet.insertRule(selector + ' { ' + rulename + ':' + value + ';}', cssRules.length);
}

function clearStyle(selector, rulename) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var i=0; i<cssRules.length; i++) {
        var rule = cssRules[i];
        if (rule.selectorText == selector && rule.style[0] == rulename) {
            stylesheet.deleteRule(i);
            break;
        }
    }       
}

function addStyles(selector, rules) {
    var stylesheet = getAppStylesheet();
    var cssRules = stylesheet.cssRules || stylesheet.rules;
    for (var prop in rules) {
        addStyle(selector, prop, rules[prop]);
    }
}

function getAppStylesheet() {
    var stylesheet = document.getElementById('my-styles');
    if (!stylesheet) {
        stylesheet = $('<style id="my-styles">').appendTo('head')[0];
    }
    stylesheet = stylesheet.sheet;
    return stylesheet;
}

Usage:

addStyles('body', {
    'background-color': 'black',
    color: 'green',
    margin: 'auto'
});

clearStyle('body', 'background-color');
addStyle('body', 'color', '#333')

Bit of a lazy answer this, but the following article may help: http://www.javascriptkit.com/dhtmltutors/externalcss3.shtml

Also, try typing "modify css rules" into google

Not sure whatwould happen if you tried to wrap a document.styleSheets[0] with jQuery() though you could give it a try