Part ONE: Interface introduction

First, there are three ways to define styles in HTML:

  1. throughlinkThe element contains external stylesheet files
  2. usestyleThe element defines an embedded style
  3. usestyleAttributes define styles for specific elements

The DOM2-level module provides a set of apis around these three application style mechanisms. Understanding this API will help you understand how to manipulate CSS with JS. There are many types of interfaces. The diagram below:

MDN

Interfaces are regular, and it’s hard to memorize them by rote, but it’s easier to understand interfaces by looking at the three ways they’re styled in HTML.

1.1 CSSStyleSheetStyle sheet object

The interface with StyleSheet in its name stands for StyleSheet. The CSSStyleSheet interface type represents a stylesheet. Includes external stylesheets contained through the link element and stylesheets defined in the

element. The CSSStyleSheet interface inherits StyleSheet. StyleSheet can be used as a base interface to define non-CSS stylesheets.

1.2 CSSRuleStyle sheet rule object

An interface with Rule in its name means Rule. The CSSRule object represents each rule in the stylesheet. CSSRule is actually a base type that many other types inherit from. The most common of these is the CSSStyleRule type, which represents style information.

All subtypes of CSSRule are as follows:

  1. CSSCharsetRule
  2. CSSConditionRule
  3. CSSCounterStyleRule
  4. CSSFontFeatureValuesRule
  5. CSSGroupingRule
  6. CSSImportRule
  7. CSSKeyframeRule
  8. CSSKeyframesRule
  9. CSSMarginRule
  10. CSSMediaRule
  11. CSSNamespaceRule
  12. CSSPageRule
  13. CSSSupportsRule
  14. CSSViewportRule
  15. CSSFontFaceRule
  16. CSSStyleRule

These rules rarely need to be accessed through scripts, and the most common is the CSSStyleRule type.

The following figure can deepen our understanding of the relationship between StyleSheet and CSSRule.

1.3 CSSStyleDeclarationObject applied to the element style property

Any HTML element that supports the style feature has a corresponding style attribute in JavaScript. This style object is an instance of CSSStyleDeclaration. Contains all style information specified by the STYLE feature of HTML, but does not include styles that are layered with external or embedded style sheets.

We often use the htmlElement. style attribute to return the CSSStyleDeclaration object. The CSSStyleDeclaration object represents the style property of an element.

Part II:CSSStyleSheetType Interface Introduction

2.1 StyleSheetProperties and methods supported by the type:

CSSStyleSheet inherits from StyleSheet, and StyleSheet acts as a base interface to define non-CSS stylesheets. The attributes inherited from the StyleSheet interface are as follows:

  • disabled: A Boolean value indicating whether the stylesheet is disabled. This property is readable/writable, and setting this value to true disables the stylesheet.
  • hrefThe URL of the stylesheet if the stylesheet is included; Otherwise, null.
  • media:
  • ownerNode: a pointer to the node that has the current style sheet, which may be passed in HTMLlink(HTMLLinkElement)orstyle(HTMLStyleElement)The introduction of. This property is null if the current stylesheet was imported by another stylesheet via @import. IE does not support this property.
  • parentStyleSheet: The current stylesheet is passed@importIn the case of imports, this property is a pointer to the stylesheet from which it was imported, otherwise null.
  • title: Value of the title property in ownerNode, otherwise null.
  • type: a string representing the style sheet type. For CSS stylesheets, this string is “type/ CSS “.

The CSSStyleSheet object is a set of read-only interfaces. Except for the disabled attribute.

2.2 CSSStyleSheetInterface types support properties and methods:

In addition to inheriting the attributes of the StyleSheet interface, CSSStyleSheet also supports the following attributes and methods:

  • cssRules(rules): a collection of style rules contained in a stylesheet. IE does not support this property, but there is a similar onerulesProperties.
  • ownerRule: If the stylesheet is passed@importImported, this property is a pointer to the imported rule; Otherwise, the value is null. IE does not support this property.
  • deleteRule(index): deletecssRulesA rule for a specified position in a collection. IE does not support this method, but does support a similar oneremoveRule()Methods.
  • insertRule(rule,index)To:cssRulesInsert at the specified position in the collectionruleA string. IE does not support this method, but does support a similar oneaddRule()Methods.
  • replace()Build a stylesheet that does not allow external references.
  • replaceSync()Build a stylesheet that allows external references.

2.3 the use ofJavaScriptAccessing style sheets

One way to access a stylesheet

All styleSheets applied to documents are represented through the Document.stylesheets collection. The collection’s Length attribute tells you the number of stylesheets in the document, and each stylesheet is accessible through square bracket syntax or the item() method.

let sheet = null;
for(leti = 0, len = document.styleSheets.length; i < len; i++) { sheet = document.styleSheets[i]; console.log(sheet.href) }Copy the code

The code above prints the href attribute of each stylesheet used in the document (style elements contain stylesheets that do not have the href attribute).

Style sheet access method two

You can also retrieve the CSSStyleSheet object using the link or style element. The DOM specifies a property that contains a CSSStyleSheet object called sheet. All browsers except Internet Explorer support this property. IE supports styleSheet.

Stylesheet objects are available in different browsers:

function getStyleSheet(element){
    returnelement.sheet || element.styleSheet; } / / the first < link / > element in the style sheet, if there are no returns empty HTMLCollection const link set = document. GetElementsByTagName ("link") [0];if(typeof link === 'object' && link.rel === 'stylesheet') {
 const sheet = getStyleSheet(link);
}

Copy the code

If the link tag is not an imported CSS style, the sheet returns NULL.

Part III:CSSRuleRule type interfaces

The CSSRule object represents each rule in the stylesheet. In fact, CSSRule is a base class type that can be inherited by a variety of other types, the most common of which is the CSSStyleRule type, which represents style information. (Other rules include @import, @font-face, @page, and @charset, but these rules rarely need to be accessed via scripts.) The CSSStyleRule object contains the following properties.

  • cssText: Returns the text of the entire rule. The text returned may not be the same as the actual text in the stylesheet because of the way the browser handles the stylesheet internally; Safari always converts text to all lowercase. IE does not support this property.
  • parentRuleIf the current rule is an imported rule, this property references the imported rule. Otherwise, the value is null. IE does not support this property.
  • parentStyleSheet: Style sheet to which the current rule belongs. IE does not support this property.
  • selectorText: Returns the selector text for the current rule.
  • styleA:CSSStyleDeclarationObject through which you can set and get specific style values in rules.
  • type: Represents the constant value of the rule type. For style rules, this value is 1. IE does not support this property.
  • styleMapA:StylePropertyMapObject.StylePropertyMapObject provides a representation of a CSS declaration block that can be substitutedCSSStyleDeclaration.

The cssText property of the CSSStyleRule object is similar to, but not identical to, the style.csstext property. The former contains the selector text and curly braces around the style information, while the latter contains only the style information (similar to the style.csstext element). In addition, cssText is read-only, and style.csstext can also be overridden.

Here is the result of getting the display of each attribute:

<style type="text/css">
  .demo {
    background-color: blue;
    width: 100px;
    height: 200px;
  }
</style> 

<script>
  var sheet = document.styleSheets[0];
  var rules = sheet.cssRules || sheet.rules;
  var rule = rules[0];
  console.log(rule.selectorText);           //.demo
  console.log(rule.style.backgroundColor);  //blue
  console.log(rule.style.width);            //100px
  console.log(rule.style.height);           //200px
  //.demo { background-color: blue; width: 100px; height: 200px; }
  console.log(rule.cssText);  
  //background-color: blue; width: 100px; height: 200px;             
  console.log(rule.style.cssText);        
</script>
Copy the code

Using rule-style, you can determine the style information associated with a rule in the same way you determine the inline style information for an element. As with elements, style information can be modified in this way, as in the following example:

var sheet = document.styleSheets[0];
var rules = sheet.cssRules || sheet.rules; 
var rule = rules[0]; 
rule.style.backgroundColor = "red";
Copy the code

Changing the rule in this way affects all the elements on the page that apply to the rule. In other words, if you have two div elements with demo classes, the modified styles will apply to both elements.

3.1 Creating and Deleting Rules (CSSStyleSheetInterface methods)

Create rules

DOM states that to add new rules to an existing stylesheet, you need to use the insertRule() method. This method takes two parameters: the text of the rule and an index indicating where to insert the rule.

var sheet = document.styleSheets[0];
sheet.insertRule("body { background-color: silver }", 0); / / IE does not supportCopy the code

IE8 and earlier support a similar method called addRule()

sheet.addRule("body"."background-color: silver", 0); // Only for IECopy the code

Insert rules into the stylesheet in a cross-browser fashion:

//insertRule(document.styleSheets[0], "body"."background-color: silver", 0);
function insertRule(sheet, selectorText, cssText, position){
    if (sheet.insertRule){
        sheet.insertRule(selectorText + "{" + cssText + "}", position);
    } else if(sheet.addRule){ sheet.addRule(selectorText, cssText, position); }}Copy the code

The above example inserts a rule that changes the background color of the element. The inserted rule becomes the first rule in the stylesheet (at position 0) — the order of the rules is critical in determining the rules to be applied to the document after the cascade.

Delete rules

The method for deleting a rule from a stylesheet is deleteRule(), which takes one parameter: the location of the rule to be deleted. For example, delete the first rule in a stylesheet.

sheet.deleteRule(0);
Copy the code

A similar method supported by IE is called removeRule() :

sheet.removeRule(0); // Only for IECopy the code

Remove rules from the stylesheet in a cross-browser fashion:

//deleteRule(document.styleSheets[0], 0);
function deleteRule(sheet, index){
    if (sheet.deleteRule){
        sheet.deleteRule(index);
    } else if(sheet.removeRule){ sheet.removeRule(index); }}Copy the code

Add rules and delete rules are not commonly used in Web development. Use them with caution.

Part IV:CSSStyleDeclarationAccess the style of the element directly

Any HTML element that supports the style feature has a corresponding style attribute in JavaScript. This is what we would normally write in an HTML element:

<div style="font-size:20px; color:red;"> container < / div >Copy the code

The style object above is an instance of CSSStyleDeclaration. Contains all style information specified by the STYLE feature of HTML, but does not include styles that are layered with external or embedded style sheets.

For CSS property names that use a dash (separating different terms, such as background-image), you must convert them to camel case. Here are a few examples:

CSS properties JavaScript attribute
background-image style.backgroundImage
color style.color
font-family style.fontFamily
var myDiv = document.getElementById("myDiv");
myDiv.style.backgroundColor = "red";
myDiv.style.width = "100px";
myDiv.style.border = "1px solid black";
Copy the code

One CSS property that cannot be converted directly is float. Because float is a reserved word in JavaScript, it cannot be used as an attribute name. The DOM2-level style specification specifies that the corresponding property name on the style object should be cssFloat. Internet Explorer supports styleFloat. You can determine which floats are supported by the current browser in the following way:

const support = (function(){
  const div = document.createElement("div");
  div.style.cssText = "float:left;";
  letsupport = { cssFloat: !! div.style.cssFloat }return support;
})()
const floatReal = support.cssFloat ? 'cssFloat' : 'styleFloat';
Copy the code

Document. documentMode can also be used to judge:

const floatReal =  Number(document.documentMode) < 9 ? 'styleFloat' : 'cssFloat'
Copy the code

As long as you get a reference to a valid DOM element, you can style it at any time using JavaScript:

var myDiv = document.getElementById("myDiv");
myDiv.style.width = "100px";
myDiv.style.border = "1px solid black";
Copy the code

All measures must specify a unit of measure. Here is an example of setting the style attribute of an element:

function setStyle(element, styles) {
    function is_numeric(n) {
        return(n ! = =' ' && !isNaN(parseFloat(n)) && isFinite(n));
    }
    Object.keys(styles).forEach(function(prop) {
        var unit = ' ';
        if (['width'.'height'.'top'.'right'.'bottom'.'left'].indexOf(prop) ! == -1 && is_numeric(styles[prop])) { unit ='px';
        }
        element.style[prop] = styles[prop] + unit;
    });
}
setStyle(document.getElementById("myDiv"),{ position: 'absolute', top: 0 })
Copy the code

Element.style returns only inline styles, not all styles for that Element. Styles set through the stylesheet, or inherited from the parent element, are not available through this property. The full style of the element is obtained via window.getComputedStyle().

4.1 CSSStyleDeclarationObject properties and methods

  • cssText: Allows you to access CSS code in the Style feature, readable and writable.
  • length: The number of CSS attributes applied to an element.
  • parentRule: Represents the CSSRule object of CSS information.
  • getPropertyPriority(propertyName): : If the given attribute is used! Important, return “important”; Otherwise, an empty string is returned.
  • getPropertyValue(propertyName): : Returns the string value of the given attribute.
  • item(index): Returns the name of the CSS property at a given location.
  • removeProperty(propertyName): Removes the given attribute from the style.
  • setProperty(propertyName,value,priority): Sets the given attribute to the corresponding value with a priority flag (“important” or an empty string).
cssTextBreak down

The CSS code in the Style feature is accessed through the cssText property. In read mode, cssText returns the browser’s internal representation of the CSS code in the Style feature. In write mode, the value assigned to cssText overrides the value of the entire style feature; That is, the style information previously specified by the style feature is lost. For example, if you set a border on an element with the style feature and then override cssText with no border, the border on the element will be erased.

<div id="demo" style="border:5px solid red;">容器</div>
var myDiv = document.getElementById("myDiv");
myDiv.style.cssText = "background-color: green";
console.log(myDiv.style.cssText) //background-color: green;
Copy the code

Setting cssText is the quickest way to apply multiple changes to an element, because you can apply them all at once.

lengthProperties,item()Method,getPropertyValue()Method,removeProperty()methods

The Length attribute is designed to work with the item() method to iterate over CSS attributes defined in the element. When using length and item(), the style object is really a collection:

<div id="demo" style="width:100px; font-size:22px;"> container </div> const myDiv = document.getelementById ('demo');
for(leti = 0; i < myDiv.style.length; Mydiv.style.item (I) console.log(mydiv.style [I]) //width font size}Copy the code

You can get the CSS property name (“background-color”, not “backgroundColor”) using either the square bracket syntax or the item() method. You can then use the acquired property name in getPropertyValue() to further obtain the value of the property.

<div id="demo" style="width:100px; font-size:22px;"> container </div> const myDiv = document.getelementById ('demo');
var prop, value, i, len;
for (i=0, len= myDiv.style.length; i < len; i++){
  prop = myDiv.style[i];
  value = myDiv.style.getPropertyValue(prop); 
  console.log(prop + ':' + value); //width:100px font-size:22px
}
Copy the code

To remove a CSS property from an element’s style, use the removeProperty() method. Using this method to remove a property means that the default style (cascading from other stylesheets) will be applied to the property. For example, to remove the font-size property set by the style feature:

<div id="demo" style="width:100px; font-size:22px;"> container </div> const myDiv = document.getelementById ('demo');
myDiv.style.removeProperty("font-size");
Copy the code

You can apply a default value to an element by simply removing the corresponding attribute.

4.2 getComputedStyle()Get the style of the calculation

While the Style object can provide style information for any element that supports the Style feature, it does not contain style information that is layered from other style sheets and affects the current element.

The dom2-level style enhances document.DefaultView to provide the getComputedStyle() method. This method takes two arguments: the element to get the computed style and a pseudo-element string (for example, “:after”). If no pseudo-element information is required, the second argument can be null. The getComputedStyle() method returns a live CSSStyleDeclaration object that updates itself automatically when the element’s style changes. This contains all the computed styles for the current element.

Window.getcomputedstyle () can also get the element’s CSSStyleDeclaration object. Document. The defaultView. GetComputedStyle (), and the window. The getComputedStyle () the difference, please refer to: MDN this article.

The following code gets the element style from window.getComputedStyle() :

<style type="text/css">
  .demo {
    background-color: blue;
    width: 100px;
    height: 200px;
  }
</style> 

<div id="demo" style="background-color: red; border: 5px solid black;"> container </div> <script> const myDemo = document.getelementById ('demo');
  const computedStyle = window.getComputedStyle(myDemo,null);
  console.log(computedStyle.backgroundColor); //rgb(255, 0, 0)
  console.log(computedStyle.width);           //100px
  console.log(computedStyle.height);          //200px
  console.log(computedStyle.border);          //5px solid rgb(0, 0, 0)
</script>
Copy the code

The background color printed above is not “blue” because the style is already overwritten in its own style property.

The border property may or may not return the actual border rule in the stylesheet. Because setting this property (the composite property) actually involves many other properties. When you set a border, you actually set the border width, color, style attributes for the four edges (border-left-width, border-top-color, border-bottom-style, etc.). . Because of this, even if computedStyle border will not return values in all browsers, but specific to computedStyle. BorderLeftWidth will return a value.

IE does not support the getComputedStyle() method, but it has a similar concept. In IE, every element that has a style attribute also has a currentStyle attribute. This property is an instance of CSSStyleDeclaration. Here is an example of a compatibility pattern:

function getStyles(elem) {
    window.getComputedStyle ?  window.getComputedStyle(elem,null) : elem.currentStyle;
}
var myDemo = document.getElementById('demo');
var computedStyle = getStyles(myDemo)
Copy the code

All computed styles are read-only. You cannot modify CSS properties in a computed style object.

Part five: Examples

5.1 Setting the Style

const ieVersion = Number(document.documentMode); /** * change :-_, etc., to camelCase, such as foo-bar to fooBar * @param name to process string * @returns {*} processed string */ const camelCase =function(name) {
  returnname.replace(/([\:\-\_]+(.) )/g,function(_, separator, letter, offset) {// The beginning is not uppercase, the rest is uppercasereturn offset ? letter.toUpperCase() : letter;
  }).replace(/^moz([A-Z])/, 'Moz$1'); // special processing for moz}; /** * Set element style * @param Element to set element * @param styleName to set style * @param value to set value */function setStyle(element, styleName, value) {
  if(! element || ! styleName)return; // If it is an object, set it one by oneif (typeof styleName === 'object') {
    for (var prop in styleName) {
      if (styleName.hasOwnProperty(prop)) {
        setStyle(element, prop, styleName[prop]); }}}else{ styleName = camelCase(styleName); // Opacity special handlingif (styleName === 'opacity' && ieVersion < 9) {
      element.style.filter = isNaN(value) ? ' ' : 'alpha(opacity=' + value * 100 + ') ';
    } else{ element.style[styleName] = value; }}};Copy the code

5.2 Getting the Style

var ieVersion = Number(document.documentMode); /** * change :-_, etc., to camelCase, such as foo-bar to fooBar * @param name to process string * @returns {*} processed string */ const camelCase =function(name) {
  returnname.replace(/([\:\-\_]+(.) )/g,function(_, separator, letter, offset) {// The beginning is not uppercase, the rest is uppercasereturn offset ? letter.toUpperCase() : letter;
  }).replace(/^moz([A-Z])/, 'Moz$1'); // special processing for moz}; /** * get the style, which is handled in IE9 and two other ways * @type{Function} * @param element to get the style element * @param styleName to get the styleName */ var getStyle = ieVersion < 9?function(element, styleName) {
  if(! element || ! styleName)returnnull; // change the styleName to camelCase styleName = camelCase(styleName); //floatSpecial handlingif (styleName === 'float') {
    styleName = 'styleFloat'; // Opacity switch (styleName) {case 'opacity':
        try {
          return element.filters.item('alpha').opacity / 100;
        } catch (e) {
          return 1.0;
        }
      default:
        return (element.style[styleName] || element.currentStyle ? element.currentStyle[styleName] : null);
    }
  } catch (e) {
    returnelement.style[styleName]; }} :function(element, styleName) {
  if(! element || ! styleName)return null;
  styleName = camelCase(styleName);
  if (styleName === 'float') {
    styleName = 'cssFloat';
  }
  try {
    var computed = document.defaultView.getComputedStyle(element, ' ');
    return element.style[styleName] || computed ? computed[styleName] : null;
  } catch (e) {
    returnelement.style[styleName]; }};Copy the code

5.3 Add and remove Class styles

Returns {Boolean} */ returns {Boolean} */ returns {Boolean} */function hasClass(el, cls) {
  if(! el || ! cls)return false;
  if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
  if (el.classList) {
    return el.classList.contains(cls);
  } else {
    return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > 1; }}; /** * Add some classes to the element * @param el to process * @param CLS to add classes */function addClass(el, cls) {
  if(! el)return;
  var curClass = el.className;
  var classes = (cls || ' ').split(' ');

  for (var i = 0, j = classes.length; i < j; i++) {
    var clsName = classes[i];
    if(! clsName)continue;

    if (el.classList) {
      el.classList.add(clsName);
    } else if(! hasClass(el, clsName)) { curClass +=' '+ clsName; }}if(! el.classList) { el.className = curClass; }}; /** * Remove some classes from the element * @param el to handle the element * @param CLS to remove the class */function removeClass(el, cls) {
  if(! el || ! cls)return;
  var classes = cls.split(' ');
  var curClass = ' ' + el.className + ' ';

  for (var i = 0, j = classes.length; i < j; i++) {
    var clsName = classes[i];
    if(! clsName)continue;

    if (el.classList) {
      el.classList.remove(clsName);
    } else if (hasClass(el, clsName)) {
      curClass = curClass.replace(' ' + clsName + ' '.' '); }}if (!el.classList) {
    el.className = trim(curClass);
  }
};

Copy the code

Refer to the link

JavaScript Advanced Programming (version 3)

JavaScript DOM advanced programming

Familiar with the getComputedStyle method for obtaining element CSS values

CSS Object Model

Stylesheets can be constructed

Familiar with the getComputedStyle method for obtaining element CSS values

CSS operation

Github.com/ElemeFE/ele…