Here's a snippet you can use to create new rules and manipulate existing rules in a stylesheet. A particular sheet is recognized by its title
, so you need to give unique titles to those stylesheets you want to manipulate (add title
attribute to corresponding link
or style
tags).
function CssManipulator (sheetTitle) {
var that = this, // A reference to an instance
len = document.styleSheets.length, // Caches the length of the collection
n; // General loop counter
this.styleSheet = null; // Stores the stylesheet for the instance
this.selectors = {}; // Stores the selectors we've handled
this.cssRules = null; // Caches cssRules of the given stylesheet
// Search the given stylesheet by title and assign it and its cssRules to instance properties
for (n = 0; n < len; n++) {
if (document.styleSheets[n].title === sheetTitle) {
this.styleSheet = document.styleSheets[n];
this.cssRules = document.styleSheets[n].cssRules || document.styleSheets[n].rules;
break;
}
}
// Changes properties of the given selector
this.change = function (selector, prop, value) {
// FF knows only camel-cased propertynames, hence camel-casing the propName
var propName = (prop.charAt(0) === '-') ? prop.substring(1, prop.length) : prop;
propName = propName.replace(/-([a-z])/gi, function(str, chr) {
return chr.toUpperCase();
});
if (selector in that.selectors) { // Change the rule, if we've handled this selector before
that.styleSheet.cssRules[that.selectors[selector]].style[propName] = value;
} else { // Add a new rule if we haven't met this selector before
that.selectors[selector] = that.styleSheet.insertRule(selector + '{' + prop + ':' + value + ';}', that.cssRules.length);
}
};
}
selectors
contains the magic, it stores the index of the newly-created rule returned by insertRule
.
Usage
Create an instance of CssManipulator
for every stylesheet you want to change like this:
pageSheet = new CssManipulator('title_of_the_stylesheet');
Then you can manipulate most of the rules in a stylesheet (pseudo-elements can't be manipulated with this code) by calling object's change
method:
pageSheet.change('.some_selector', 'property-name', 'value_for_the_property');
This method adds a new selector once, nevertheless if the passed selector exists in the original stylesheet or not. Notice, that if you change a property name like background-color
, you need to pass "hyphen-mode" of the property name to the method.
You can develope the object further, for example change
method could be easily changed to accept more than one property-value pair per call.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…