There is a lot of JavaScript code in web applications now, and we are always looking for various solutions that make them faster.
1. We use event proxying to make event monitoring more efficient.
2. We use function debuncing technology to limit the number of times a given method is called within a period of time. Please refer to: How to prevent high-frequency triggering of event functions (Chinese translation)
3. We use a JavaScript loader to load the part of the resources we really need, etc.
There is another way to make our page faster and more efficient. That is to dynamically add and delete certain styles in the style sheet through JS, instead of constantly querying DOM elements and applying various styles. Here is how it works.
Get the stylesheet
You can choose any style sheet to add style rules. If you have a definite style sheet, you can add an ID attribute to the <link> or <style> tag in the HTML page, and then you can get the CSSStyleSheet object directly through the sheet attribute of this DOM element. Stylesheets can also be traversed to:
The code copy is as follows:
// Return an array-like (Array-like) style list StyleSheetList
var sheets = document.styleSheets;
/*
The return value is similar to the following:
StyleSheetList
{
0: CSSStyleSheet,
1: CSSStyleSheet,
2: CSSStyleSheet,
3: CSSStyleSheet,
4: CSSStyleSheet,
length: 5,
item: function
}
*/
// Get the first sheet, ignoring the media attribute
var sheet = document.styleSheets[0];
What you need to pay special attention to is the media attribute of the style sheet - when you want to display it on the screen, you must not add CSS rules to the print style sheet. You can take a closer look at the attribute information of the CSSStyleSheet object:
The code copy is as follows:
// The console outputs the information of the first style sheet
console.log(document.styleSheets[0]);
/*
Return value:
CSSStyleSheet
cssRules: CSSRuleList[Object]
disabled: false
href: "http://davidwalsh.name/somesheet.css"
media: MediaList[Object]
ownerNode: link[object]
ownerRule: null
parentStyleSheet: null
rules: CSSRuleList[Object]
title: null
type: "text/css"
*/
// Get media type (media type)
console.log(document.styleSheets[0].media.mediaText)
/*
The return value may be:
"all" or "print" or other media applied to this stylesheet
*/
In all cases, you definitely have a way to get the stylesheet to add the rules.
Create a new stylesheet
In many cases, the best way to do this might be to create a new <style> element to store these dynamic rules. This is also very simple:
The code copy is as follows:
var sheet = (function() {
// Create <style> tag
var style = document.createElement("style");
// You can add a media (/media query, media query) attribute
// style.setAttribute("media", "screen")
// style.setAttribute("media", "only screen and (max-width : 1024px)")
// For WebKit hack:(
style.appendChild(document.createTextNode(""));
// Add <style> element to the page
document.head.appendChild(style);
return style.sheet;
})();
The tragedy is that WebKit needs a little hack to be created correctly, but we only need to care about this sheet.
Insert rule
In earlier versions of IE, the insertRule method of Stylesheets was not available, although it is now the standard for rule injection. The insertRule method requires writing the entire CSS rule, which is the same as in the style sheet:
The code copy is as follows:
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);
Although this JavaScript API method looks a bit rustic, it does work like this. The second parameter index indicates the location (index) to be inserted in the rule. This is also very useful so that you can insert the same rule/code, which allows the back rules to take effect. The default index is -1, which represents the end of the entire set. If you want to have additional/lazy control rules, you can also add !important tags to a certain rule to avoid indexing issues.
Add rules - non-standard addRule method
The CSSStyleSheet object has an addRule method that allows you to register CSS rules into the stylesheet. The addRule method accepts three parameters: the first parameter is the selector, the second parameter is the CSS rule code, and the third is the integer index starting from 0, indicating the position of the style (in the same selector):
The code copy is as follows:
sheet.addRule("#myList li", "float: left; background: red !important;", 1);
The return value of the addRule method is always -1, so this value has no practical significance.
Remember, the advantage of this approach is that elements added from the page automatically have the styles applied to them, which means you don't have to add them to specific elements, but instead inject them directly into the page. Of course, more efficient!
Security application rules
Because not all browsers support the insertRule method, it is best to create a wrapper function to handle the rule application. Here is a quick way to do it:
The code copy is as follows:
function addCSSRule(sheet, selector, rules, index) {
if("insertRule" in sheet) {
sheet.insertRule(selector + "{" + rules + "}", index);
}
else if("addRule" in sheet) {
sheet.addRule(selector, rules, index);
}
}
//How to use
addCSSRule(document.styleSheets[0], "header", "float: left");
This tool method should cover all cases where new style rules are added. If you are worried about errors in your application, you should wrap the code for the method with a try{} catch(e){} block.
Insert media query rules
There are two ways to add media query rules. The first is to use the standard insertRule method:
The code copy is as follows:
sheet.insertRule(
"@media only screen and (max-width : 1140px) { header { display: none; } }"
);
Of course, because the old version of IE does not support insertRule, another way is to create a STYLE element, specify the appropriate media attribute, and then add the style to the new stylesheet. This may require the use of multiple STYLE elements, but it is also easy. I might create an object, specify the media query as well as the index, and create/get them like that.
Dynamically adding rules to stylesheets is an efficient method, and may be easier than you think. Remember that this solution may need to be used in your next big application, because it can prevent you from falling into the pit in both code and element processing.