How can I change the css class rules using jQuery?
Asked Answered
U

14

52

Can any one help me please, I have two sections of my question.

  1. What I want to do is changing css class rules using jQuery on the fly.

    .classname{color:red; font-size:14px;}

    In example above I have a class named .classname now using jQuery I want to change the font size only not color with in .classname not by adding css inline.

  2. I want to create and save .classname change to a file remember there will be complete stylesheet or no of classnames that will be save in file.

How I can do this the easiest and better way?

Thanks!

Uraemia answered 7/3, 2009 at 16:52 Comment(1)
This is particularly important if you want to add :hover and :active rules, which can't be done with $.css().Monteria
B
54

As far as I know there's no jQuery way to do this. There might be some jQuery plugin for this but I don't know.

Basically, what you're trying to achieve in your first question is possible using the styleSheets property of the document object. It's a little bit more complicated than that as you need to walk to a rather deep object chain, but nevertheless works in all major browsers including Internet Explorer 6. Below is a proof of concept. The CSS is inside a STYLE tag, but works with external CSS just as well. I'll let you do the abstractions.

Proof of Concept

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="imagetoolbar" content="false">
<meta http-equiv="imagetoolbar" content="no">
<style type="text/css">
.classname {
 color: red;
 font-size: 14px;
}
</style>
<script type="text/javascript">
window.onload = function() {
    document.getElementById("button").onclick = function() {
        var ss = document.styleSheets;

        for (var i=0; i<ss.length; i++) {
            var rules = ss[i].cssRules || ss[i].rules;

            for (var j=0; j<rules.length; j++) {
                if (rules[j].selectorText === ".classname") {
                    rules[j].style.color = "green";
                }
            }
        }
    };
}
</script>
</head>
<body>

<h1 class="classname">Some red text</h1>

<button id="button">Make text green</button>

</body>
</html>

For your second question, I don't have time to write a solution but it would involve reading the CSS declarations just as above and use the cssText property of a CssRule object in order to build a string which will eventually be sent to the server using a Ajax POST request. The server side is your business.

References:

Hope it helps

Booster answered 7/3, 2009 at 17:35 Comment(8)
Thanks lonut G.Stan how good you are i never used document.styleSheets even don't that kind of things exist :S. actually i want to do that kind of work coolchaser.com/layout/create or realeditor.com/editor can you please tell me concept how they are doing PLEASE.Uraemia
I don't understand why do you have to add new rule to all style sheets ? Why not add it only to last one or add new stylesheet ?Folkways
@alpav, oh, it's a bug :) I don't remember how it slipped through my eyes.Trinitrophenol
What is interesting is that I see that bug in jQuery.cssRule plugin too (see my question), so I wonder if it's a bug (you guys took it from the same place wherever it is) or necessity for something that I am not aware of.Folkways
My above example is conceived by me from the documentation pages I have linked to, and I think I remember why I did like this. I'm not just adding a new rule, I'm adding a new rule to an existing declaration. So I had to look up every stylesheet in order to find that declaration. Now, the best optimization that I can come up with right now, is to read the styleSheets in reverse order, and break the loop after the first encounter of that selectorText. This way, you modify just one stylesheet, the one with the highest precedence.Trinitrophenol
I don't know why, but this solution doesn't work in Google Chrome (but it does in Safari, curiously). Any help?Jennajenne
@JesuferVn works for me. I've used the exact code in the answer to test this.Trinitrophenol
jQuery isn't the solution!? gaspLupulin
B
17

Recently I had the need to fix some jquery theme issue for Autocomplete widget. I wanted to change the background color of the autocomplete widget.

So I looked up the CSS and found that the autocomplete class is defined like this

.ui-autocomplete { position: absolute; cursor: default; }   

So in my program I issue the following statement to change the class by adding the background property. Note that I keep the other attributes as it is otherwise it will break existing functionality

$("<style type='text/css'> .ui-autocomplete { position: absolute; cursor: default; background:black; color:white} </style>").appendTo("head");
Burgenland answered 18/10, 2011 at 16:0 Comment(1)
This hack made me grin. It saves a mountain of code from the highest-voted answer here. I'm using it.Suspire
Y
13

You should take this approach only if:

  • You need to set the value to something that is impractical to enumerate (i.e. varying width in pixels) with class names
  • And you want to apply this style to elements that will be inserted in the DOM in the future

There is a jQuery plugin that does that: http://plugins.jquery.com/project/jquerycssrule

For a small project I worked on I extracted the bare essentials and created the following function:

function addCSSRule(sel, prop, val) {
    for(var i = 0; i < document.styleSheets.length; i++){
        var ss    = document.styleSheets[i];
        var rules = (ss.cssRules || ss.rules);
        var lsel  = sel.toLowerCase();

        for(var i2 = 0, len = rules.length; i2 < len; i2++){
            if(rules[i2].selectorText && (rules[i2].selectorText.toLowerCase() == lsel)){
                if(val != null){
                    rules[i2].style[prop] = val;
                    return;
                }
                else{
                    if(ss.deleteRule){
                        ss.deleteRule(i2);
                    }
                    else if(ss.removeRule){
                        ss.removeRule(i2);
                    }
                    else{
                        rules[i2].style.cssText = '';
                    }
                }
            }
        }
    }

    var ss = document.styleSheets[0] || {};
    if(ss.insertRule) {
        var rules = (ss.cssRules || ss.rules);
        ss.insertRule(sel + '{ ' + prop + ':' + val + '; }', rules.length);
    }
    else if(ss.addRule){
        ss.addRule(sel, prop + ':' + val + ';', 0);
    }
}
Yount answered 1/12, 2009 at 16:58 Comment(2)
It appears to be gone now... alas.Dyadic
Just search for jqurycssrule on guthub: github.com/search?q=jquerycssruleYount
B
12

If I understand your question correctly, you would like to read through a CSS file, make changes to a class and then persist those changes by saving the file?

You can't do this with JavaScript/jQuery running from the client side; You can certainly change the font size of each individual element in the DOM that matches the CSS class .classname, like so

$('.classname').css('font-size','14px');

but client-side JavaScript cannot access the filesystem from the web browser, so you would need some other way (i.e. server-side code) to make changes to the CSS file itself.

Bree answered 7/3, 2009 at 17:1 Comment(2)
You're not changing the font size of the css class itself here, you're adding an individual font-size style declaration to every dom element that matches that class name - an important difference. If, after running this jquery statement, you were to construct a new dom element of class .classname and append it to the document, it would not have the font-size property. You'd need to re-run the jquery command to set the font-size property of the new element.Obvolute
@Obvolute correct, it was a bad choice of words on my part. Have updated the wording to clarifyBree
R
6

You can also try JSS, it's worked wonderfully for me: https://github.com/Box9/jss

Download and include jss.js in your HTML:

<script type="text/javascript" src="jss.js"></script>

Add new rule (or extend existing rule):

jss('.special', {
    color: 'red',
    fontSize: '2em',
    padding: '10px'
});

Retrieve existing rule:

jss('.special').get();

Returns:

{
    'color': 'red',
    'font-size': '2em',
    'padding-bottom': '10px',
    'padding-left': '10px',
    'padding-right': '10px',
    'padding-top': '10px'
}

Remove existing rule:

jss('.special').remove();
Rb answered 14/7, 2012 at 19:11 Comment(3)
You say 'add' or 'extend', but can you actually 'override' a rule also? I'm going to download it and try it out and come back with an answer if no one has answered.Coulee
Yes, @Jeach, "extend" really means "override". I'm using it for the Options screen of a Google Chrome extension. When users define their settings, they override the information in the stylesheets, so any dynamically added elements use the new styles instead. There's no easy way to do this with jQuery as far as I know - you would have to reapply the styles to the new elements, you can't actually "change" a class. JSS simply modifies the css rules of the document using methods already suggested in some of the other answers, but in a very concise way.Rb
Nope, this doesn't work for me either (also tried 'jQuery.Rules'). Note to anyone, that I had to wrap the 'z-index' in quotes otherwise it gave me an error when trying to change it. But I think the reason 'jss' and 'jQuery.Rules' don't work is because the people who implemented the web page, references the CSS in all pages I load with AJAX to inject in the body. So I'm not sure if that's why it's not working, but my rules NEVER change regardless of the library I've tried. I need to investigate this further at some point to see if my theory is the reason it's not working!Coulee
S
2

the DOM Level 2 lets manipulate directly the css rules of a stylesheet. ex :

var ss = document.styleSheets[1];  // ref to the first stylesheet
ss.cssRules[0].style.backgroundColor="blue";  // modification of the 1rst rule

There are 2 interfaces :

That make it possible to active/inactivate a stylesheet, remove a rule, add a rule etc... All the details here in MDM : Using_dynamic_styling_information

Secretarygeneral answered 21/5, 2012 at 8:38 Comment(0)
T
1

What you are looking to do is done by having a couple of themes on the server (theme1.css, theme2.css, theme3.css, etc.) and letting the user select the theme he likes. You can then save in the database with the user profile the theme the user chose (theme2.css). When the user then displays his page, you include at the top of the page the theme2.css instead of the theme default.css.

This would work well with server side technology such as PHP or ASP.NET or whatever you like. Of course, you could potentially use javascript to save a cookie on the user computer to remember his choice and use javascript again to include the file that you remembered via the cookie.

If you want to let the user manage exactly what applies to specific elements of the design (such as the color of the header, the font, etc.) you could again, using a server-side technology (better in this case in my opinion) or javascript save things like header=blue, font=Arial and using jQuery apply what was stored to your page.

Hope it gives you an overview.

Teri answered 7/3, 2009 at 18:19 Comment(4)
Thanks ipfavreau got the first point loading different css but it will be predefined. coolchaser.com/layout/create want to do this type of stuff or same changing myspace theme. i have to save all the classes name in db and attributes ? send changes n retrieve than change interface ?Uraemia
If you don't mind the changes not persisting forever, you can save the changes in a cookie using only javascript, but as I was saying, it'll probably do a better job in a database yes. And you could yes save all attributes in the DB and then display them back, even without reloading using AJAX.Teri
great Thanks dude, i will make the database tables having all classes names as table and attributes where i can update class rules too. am i write ?Uraemia
Well, answering about your architecture in a simple comment might be out of the scope of this answer, you'll probably want to ask another question more focused on that specific implementation, but basically, yes, you'll want a table that links a user, an attribute and the chosen value.Teri
D
0

On a semi-related note, also see my answer about changing LESS variables which will result in updated CSS rules. Depending on your case that may be more useful since a single LESS variable can drive a lot of CSS rules.... https://mcmap.net/q/354025/-do-you-recommend-against-javascript-based-less

Decury answered 4/3, 2012 at 23:41 Comment(0)
S
0

not sure about changing the class properties I came here looking for an answer to that myself and seems there are a few answers for that already, as for saving you could use jquery $.post method to send a form containing changes or $.get with url encoded values to then write to the new css file using PHP fwrite, or file_put_contents. make sure you restrict access to this feature or ensure values meet a certain criteria before storing any data.

Squad answered 7/3, 2012 at 9:15 Comment(0)
J
0

For the first part, I usually specify a style block and switch it on/off with jQuery. For example:

<style type="text/css" id="my-style" media="all">
    .classname{color:red; font-size:14px;}
</style>

Then you can to the switching by setting the disabled attribute, such as:

$('#my-style').prop('disabled', true);
$('#my-style').prop('disabled', false);
Joyous answered 12/4, 2013 at 21:51 Comment(0)
W
0

You can use YUI Stylesheet Utility.

http://yuilibrary.com/yui/docs/stylesheet/

It works grate!

Winegrower answered 6/11, 2014 at 8:0 Comment(0)
T
0

As styles applied to the head section 'overload' each other, their late append() with styles for all relevant elements will be used, unless there was !important involved earlier.

The function used for assigning the css-content should be text() not html() to prevent accidental injections of code

var dynamic_css = function(class_name){
  return '.' + class_name + ' {color:red; font-size:14px;}';
}
var styles = $('<style type="text/css">');
styles.text(dynamic_css('my_classname'));
$('html head').append(styles);

later:

styles.remove();

it also works well to assign a class to the styles element to identify it later

Tallbot answered 11/11, 2014 at 21:26 Comment(0)
S
-1

I am pretty sure you can't change the rules inside an existing style. Even firebug won't let you do this. You can style an element or set of elements, you can assign and unassign classes, but I don't think you can alter existing classes. In order to do what you are asking you will need to maintain some sort of associative array that records proposed changes to existing classes and then to save those changes you will need to upload to a server that can then offer a link for download to the client.

Solfatara answered 7/3, 2009 at 17:34 Comment(0)
A
-1

I used the addClass of jquery : http://api.jquery.com/addClass/ and then set the class as the attributes i want to change.

Aluminize answered 18/2, 2010 at 10:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.