206

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?

22 Answers 22

287

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

Sign up to request clarification or add additional context in comments.

8 Comments

The gist is self sufficient. You can create it locally, and it will work just fine. Direct link to the download link: gist.github.com/gists/714352/download
Throws an 'Unexpected call to method or property access' error for me in IE8. I had to follow this article to get it working.
There can be only 31 styles in page in IE9- blogs.msdn.com/b/ieinternals/archive/2011/05/14/…
If it doesn't work. Try append style to body. i.e. $("<style>...</style>").appendTo("body");
@Andrew Can't you just define the style tag with an ID and then remove it later matching that ID?
|
134

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.

5 Comments

This. Should be the accepted answer. It actually answers the question.
I agree with @JohannesPille, this is the real answer!
not working in cordova ios. will you please suggest on this?
Quite efficient and straightforward. Once the new rule is injected in the header, you can retrieve it anywhere in your page, includind from PHP.
19

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?

6 Comments

I would say this is a CSS rule and not a CSS class.
This answer is misleading. The asker wanted to create a CSS rule at runtime, not set the style of a particular element to a constant (reusable) CSS declaration.
It's not quite what they asked for, but it is the right solution :) Filling the dom with extra <style> elements has some nasty code smell
How will you remove these rules applied when you need to, that's possible with other solutions...
@Kevin - that may be so but there are times when that's just what you need. for example - when an element is being re-created by some ajax script and you need to persist a new style rule.
|
13

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)

Comments

11

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%"
    }
});

Comments

9

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. :)

1 Comment

Just for clarity, I would suggest naming parameters selector and body. Replacement of comma will cause problems when specifying fonts or using rgb(), etc., but overall this idea is good.
8

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);
});

3 Comments

This answer is not quite what the asker asked for. The asker wanted to create a CSS rule at runtime, not set the style of a particular element to a constant CSS declaration.
I understand, but this is an alternative solution, so I provided it.
@MikeTrpcic The problem is that there are other people searching for this solution too - to add css rules to a page - and your answer doesn't solve that.
6

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.

1 Comment

What a nice idea! I used it in conjunction with the snippet on this page ssdtutorials.com/tutorials/title/jquery-flashing-text.html to allow for toggling a colour (the original would toggle a class only). Thanks!
6

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

Comments

6

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')

Comments

3

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.

2 Comments

seams teh best way right now. i've found something jQuery.cssRule but is some kind of plugin :-/
$("head").append($("<style type='text/css'> ... is one way
2

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

Comments

2

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.

2 Comments

@Daniel, yes it does; statement removed.
seems doesn't support rule like this: div:before{content:'name: ';}
2

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.

Comments

2

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);}

Comments

1

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!

Comments

1

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 '';
};

Comments

0

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.

Comments

0

If you don't want to use any plugins mentioned here on the board, you could use a simple function, e.g.:

var addStyle = function (style) {
    var allStyles = new Array();
    $.each(style, function (selector, rules) {
        var arr = $.map(rules, function (value, prop) { return "    " + prop + ": " + value + ";"; });
        allStyles.push(selector + " {\n" + arr.join("\n") + "\n}");
    });
    $("<style>").prop("type", "text/css").html(allStyles.join("\n")).appendTo("head");
};

and then call:

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

This is how it looks in html:

<style type="text/css">
    #my-window {
        position: fixed;
        z-index: 102;
        display: none;
        top: 50%;
        left: 50%;
    }
</style>

I got inspired by some answers here on the board, e.g. the "appendTo" portion is borrowed from here

Comments

-2

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?

1 Comment

and you don't want to put the information in the head section of your page either (between style tags)?
-2

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.

Comments

-10

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.