JavaScript CSS 操作

2023-03-20 15:47 更新

CSS 與 JavaScript 是兩個(gè)有著明確分工的領(lǐng)域,前者負(fù)責(zé)頁(yè)面的視覺效果,后者負(fù)責(zé)與用戶的行為互動(dòng)。但是,它們畢竟同屬網(wǎng)頁(yè)開發(fā)的前端,因此不可避免有著交叉和互相配合。本章介紹如何通過 JavaScript 操作 CSS。

HTML 元素的 style 屬性

操作 CSS 樣式最簡(jiǎn)單的方法,就是使用網(wǎng)頁(yè)元素節(jié)點(diǎn)的getAttribute()方法、setAttribute()方法和removeAttribute()方法,直接讀寫或刪除網(wǎng)頁(yè)元素的style屬性。

div.setAttribute(
  'style',
  'background-color:red;' + 'border:1px solid black;'
);

上面的代碼相當(dāng)于下面的 HTML 代碼。

<div style="background-color:red; border:1px solid black;" />

style不僅可以使用字符串讀寫,它本身還是一個(gè)對(duì)象,部署了 CSSStyleDeclaration 接口(詳見下面的介紹),可以直接讀寫個(gè)別屬性。

e.style.fontSize = '18px';
e.style.color = 'black';

CSSStyleDeclaration 接口

簡(jiǎn)介

CSSStyleDeclaration 接口用來操作元素的樣式。三個(gè)地方部署了這個(gè)接口。

  • 元素節(jié)點(diǎn)的style屬性(Element.style
  • CSSStyle實(shí)例的style屬性
  • window.getComputedStyle()的返回值

CSSStyleDeclaration 接口可以直接讀寫 CSS 的樣式屬性,不過,連詞號(hào)需要變成駱駝拼寫法。

var divStyle = document.querySelector('div').style;

divStyle.backgroundColor = 'red';
divStyle.border = '1px solid black';
divStyle.width = '100px';
divStyle.height = '100px';
divStyle.fontSize = '10em';

divStyle.backgroundColor // red
divStyle.border // 1px solid black
divStyle.height // 100px
divStyle.width // 100px

上面代碼中,style屬性的值是一個(gè) CSSStyleDeclaration 實(shí)例。這個(gè)對(duì)象所包含的屬性與 CSS 規(guī)則一一對(duì)應(yīng),但是名字需要改寫,比如background-color寫成backgroundColor。改寫的規(guī)則是將橫杠從 CSS 屬性名中去除,然后將橫杠后的第一個(gè)字母大寫。如果 CSS 屬性名是 JavaScript 保留字,則規(guī)則名之前需要加上字符串css,比如float寫成cssFloat

注意,該對(duì)象的屬性值都是字符串,設(shè)置時(shí)必須包括單位,但是不含規(guī)則結(jié)尾的分號(hào)。比如,divStyle.width不能寫為100,而要寫為100px。

另外,Element.style返回的只是行內(nèi)樣式,并不是該元素的全部樣式。通過樣式表設(shè)置的樣式,或者從父元素繼承的樣式,無法通過這個(gè)屬性得到。元素的全部樣式要通過window.getComputedStyle()得到。

CSSStyleDeclaration 實(shí)例屬性

(1)CSSStyleDeclaration.cssText

CSSStyleDeclaration.cssText屬性用來讀寫當(dāng)前規(guī)則的所有樣式聲明文本。

var divStyle = document.querySelector('div').style;

divStyle.cssText = 'background-color: red;'
  + 'border: 1px solid black;'
  + 'height: 100px;'
  + 'width: 100px;';

注意,cssText的屬性值不用改寫 CSS 屬性名。

刪除一個(gè)元素的所有行內(nèi)樣式,最簡(jiǎn)便的方法就是設(shè)置cssText為空字符串。

divStyle.cssText = '';

(2)CSSStyleDeclaration.length

CSSStyleDeclaration.length屬性返回一個(gè)整數(shù)值,表示當(dāng)前規(guī)則包含多少條樣式聲明。

// HTML 代碼如下
// <div id="myDiv"
//   style="height: 1px;width: 100%;background-color: #CA1;"
// ></div>
var myDiv = document.getElementById('myDiv');
var divStyle = myDiv.style;
divStyle.length // 3

上面代碼中,myDiv元素的行內(nèi)樣式共包含3條樣式規(guī)則。

(3)CSSStyleDeclaration.parentRule

CSSStyleDeclaration.parentRule屬性返回當(dāng)前規(guī)則所屬的那個(gè)樣式塊(CSSRule 實(shí)例)。如果不存在所屬的樣式塊,該屬性返回null

該屬性只讀,且只在使用 CSSRule 接口時(shí)有意義。

var declaration = document.styleSheets[0].rules[0].style;
declaration.parentRule === document.styleSheets[0].rules[0]
// true

CSSStyleDeclaration 實(shí)例方法

(1)CSSStyleDeclaration.getPropertyPriority()

CSSStyleDeclaration.getPropertyPriority方法接受 CSS 樣式的屬性名作為參數(shù),返回一個(gè)字符串,表示有沒有設(shè)置important優(yōu)先級(jí)。如果有就返回important,否則返回空字符串。

// HTML 代碼為
// <div id="myDiv" style="margin: 10px!important; color: red;"/>
var style = document.getElementById('myDiv').style;
style.margin // "10px"
style.getPropertyPriority('margin') // "important"
style.getPropertyPriority('color') // ""

上面代碼中,margin屬性有important優(yōu)先級(jí),color屬性沒有。

(2)CSSStyleDeclaration.getPropertyValue()

CSSStyleDeclaration.getPropertyValue方法接受 CSS 樣式屬性名作為參數(shù),返回一個(gè)字符串,表示該屬性的屬性值。

// HTML 代碼為
// <div id="myDiv" style="margin: 10px!important; color: red;"/>
var style = document.getElementById('myDiv').style;
style.margin // "10px"
style.getPropertyValue("margin") // "10px"

(3)CSSStyleDeclaration.item()

CSSStyleDeclaration.item方法接受一個(gè)整數(shù)值作為參數(shù),返回該位置的 CSS 屬性名。

// HTML 代碼為
// <div id="myDiv" style="color: red; background-color: white;"/>
var style = document.getElementById('myDiv').style;
style.item(0) // "color"
style.item(1) // "background-color"

上面代碼中,0號(hào)位置的 CSS 屬性名是color1號(hào)位置的 CSS 屬性名是background-color。

如果沒有提供參數(shù),這個(gè)方法會(huì)報(bào)錯(cuò)。如果參數(shù)值超過實(shí)際的屬性數(shù)目,這個(gè)方法返回一個(gè)空字符值。

(4)CSSStyleDeclaration.removeProperty()

CSSStyleDeclaration.removeProperty方法接受一個(gè)屬性名作為參數(shù),在 CSS 規(guī)則里面移除這個(gè)屬性,返回這個(gè)屬性原來的值。

// HTML 代碼為
// <div id="myDiv" style="color: red; background-color: white;">
//   111
// </div>
var style = document.getElementById('myDiv').style;
style.removeProperty('color') // 'red'
// HTML 代碼變?yōu)?// <div id="myDiv" style="background-color: white;">

上面代碼中,刪除color屬性以后,字體顏色從紅色變成默認(rèn)顏色。

(5)CSSStyleDeclaration.setProperty()

CSSStyleDeclaration.setProperty方法用來設(shè)置新的 CSS 屬性。該方法沒有返回值。

該方法可以接受三個(gè)參數(shù)。

  • 第一個(gè)參數(shù):屬性名,該參數(shù)是必需的。
  • 第二個(gè)參數(shù):屬性值,該參數(shù)可選。如果省略,則參數(shù)值默認(rèn)為空字符串。
  • 第三個(gè)參數(shù):優(yōu)先級(jí),該參數(shù)可選。如果設(shè)置,唯一的合法值是important,表示 CSS 規(guī)則里面的!important
// HTML 代碼為
// <div id="myDiv" style="color: red; background-color: white;">
//   111
// </div>
var style = document.getElementById('myDiv').style;
style.setProperty('border', '1px solid blue');

上面代碼執(zhí)行后,myDiv元素就會(huì)出現(xiàn)藍(lán)色的邊框。

CSS 模塊的偵測(cè)

CSS 的規(guī)格發(fā)展太快,新的模塊層出不窮。不同瀏覽器的不同版本,對(duì) CSS 模塊的支持情況都不一樣。有時(shí)候,需要知道當(dāng)前瀏覽器是否支持某個(gè)模塊,這就叫做“CSS模塊的偵測(cè)”。

一個(gè)比較普遍適用的方法是,判斷元素的style對(duì)象的某個(gè)屬性值是否為字符串。

typeof element.style.animationName === 'string';
typeof element.style.transform === 'string';

如果該 CSS 屬性確實(shí)存在,會(huì)返回一個(gè)字符串。即使該屬性實(shí)際上并未設(shè)置,也會(huì)返回一個(gè)空字符串。如果該屬性不存在,則會(huì)返回undefined

document.body.style['maxWidth'] // ""
document.body.style['maximumWidth'] // undefined

上面代碼說明,這個(gè)瀏覽器支持max-width屬性,但是不支持maximum-width屬性。

注意,不管 CSS 屬性名的寫法帶不帶連詞線,style屬性上都能反映出該屬性是否存在。

document.body.style['backgroundColor'] // ""
document.body.style['background-color'] // ""

另外,使用的時(shí)候,需要把不同瀏覽器的 CSS 前綴也考慮進(jìn)去。

var content = document.getElementById('content');
typeof content.style['webkitAnimation'] === 'string'

這種偵測(cè)方法可以寫成一個(gè)函數(shù)。

function isPropertySupported(property) {
  if (property in document.body.style) return true;
  var prefixes = ['Moz', 'Webkit', 'O', 'ms', 'Khtml'];
  var prefProperty = property.charAt(0).toUpperCase() + property.substr(1);

  for(var i = 0; i < prefixes.length; i++){
    if((prefixes[i] + prefProperty) in document.body.style) return true;
  }

  return false;
}

isPropertySupported('background-clip')
// true

CSS 對(duì)象

瀏覽器原生提供 CSS 對(duì)象,為 JavaScript 操作 CSS 提供一些工具方法。

這個(gè)對(duì)象目前有兩個(gè)靜態(tài)方法。

CSS.escape()

CSS.escape方法用于轉(zhuǎn)義 CSS 選擇器里面的特殊字符。

<div id="foo#bar">

上面代碼中,該元素的id屬性包含一個(gè)#號(hào),該字符在 CSS 選擇器里面有特殊含義。不能直接寫成document.querySelector('#foo#bar'),只能寫成document.querySelector('#foo\\#bar')。這里必須使用雙斜杠的原因是,單引號(hào)字符串本身會(huì)轉(zhuǎn)義一次斜杠。

CSS.escape方法就用來轉(zhuǎn)義那些特殊字符。

document.querySelector('#' + CSS.escape('foo#bar'))

CSS.supports()

CSS.supports方法返回一個(gè)布爾值,表示當(dāng)前環(huán)境是否支持某一句 CSS 規(guī)則。

它的參數(shù)有兩種寫法,一種是第一個(gè)參數(shù)是屬性名,第二個(gè)參數(shù)是屬性值;另一種是整個(gè)參數(shù)就是一行完整的 CSS 語(yǔ)句。

// 第一種寫法
CSS.supports('transform-origin', '5px') // true

// 第二種寫法
CSS.supports('display: table-cell') // true

注意,第二種寫法的參數(shù)結(jié)尾不能帶有分號(hào),否則結(jié)果不準(zhǔn)確。

CSS.supports('display: table-cell;') // false

window.getComputedStyle()

行內(nèi)樣式(inline style)具有最高的優(yōu)先級(jí),改變行內(nèi)樣式,通常會(huì)立即反映出來。但是,網(wǎng)頁(yè)元素最終的樣式是綜合各種規(guī)則計(jì)算出來的。因此,如果想得到元素實(shí)際的樣式,只讀取行內(nèi)樣式是不夠的,需要得到瀏覽器最終計(jì)算出來的樣式規(guī)則。

window.getComputedStyle方法,就用來返回瀏覽器計(jì)算后得到的最終規(guī)則。它接受一個(gè)節(jié)點(diǎn)對(duì)象作為參數(shù),返回一個(gè) CSSStyleDeclaration 實(shí)例,包含了指定節(jié)點(diǎn)的最終樣式信息。所謂“最終樣式信息”,指的是各種 CSS 規(guī)則疊加后的結(jié)果。

var div = document.querySelector('div');
var styleObj = window.getComputedStyle(div);
styleObj.backgroundColor

上面代碼中,得到的背景色就是div元素真正的背景色。

注意,CSSStyleDeclaration 實(shí)例是一個(gè)活的對(duì)象,任何對(duì)于樣式的修改,會(huì)實(shí)時(shí)反映到這個(gè)實(shí)例上面。另外,這個(gè)實(shí)例是只讀的。

getComputedStyle方法還可以接受第二個(gè)參數(shù),表示當(dāng)前元素的偽元素(比如:before、:after:first-line、:first-letter等)。

var result = window.getComputedStyle(div, ':before');

下面的例子是如何獲取元素的高度。

var elem = document.getElementById('elem-container');
var styleObj = window.getComputedStyle(elem, null)
var height = styleObj.height;
// 等同于
var height = styleObj['height'];
var height = styleObj.getPropertyValue('height');

上面代碼得到的height屬性,是瀏覽器最終渲染出來的高度,比其他方法得到的高度更可靠。由于styleObj是 CSSStyleDeclaration 實(shí)例,所以可以使用各種 CSSStyleDeclaration 的實(shí)例屬性和方法。

有幾點(diǎn)需要注意。

  • CSSStyleDeclaration 實(shí)例返回的 CSS 值都是絕對(duì)單位。比如,長(zhǎng)度都是像素單位(返回值包括px后綴),顏色是rgb(#, #, #)rgba(#, #, #, #)格式。
  • CSS 規(guī)則的簡(jiǎn)寫形式無效。比如,想讀取margin屬性的值,不能直接讀,只能讀marginLeft、marginTop等屬性;再比如,font屬性也是不能直接讀的,只能讀font-size等單個(gè)屬性。
  • 如果讀取 CSS 原始的屬性名,要用方括號(hào)運(yùn)算符,比如styleObj['z-index'];如果讀取駱駝拼寫法的 CSS 屬性名,可以直接讀取styleObj.zIndex。
  • 該方法返回的 CSSStyleDeclaration 實(shí)例的cssText屬性無效,返回undefined。

CSS 偽元素

CSS 偽元素是通過 CSS 向 DOM 添加的元素,主要是通過:before:after選擇器生成,然后用content屬性指定偽元素的內(nèi)容。

下面是一段 HTML 代碼。

<div id="test">Test content</div>

CSS 添加偽元素:before的寫法如下。

#test:before {
  content: 'Before ';
  color: #FF0;
}

節(jié)點(diǎn)元素的style對(duì)象無法讀寫偽元素的樣式,這時(shí)就要用到window.getComputedStyle()。JavaScript 獲取偽元素,可以使用下面的方法。

var test = document.querySelector('#test');

var result = window.getComputedStyle(test, ':before').content;
var color = window.getComputedStyle(test, ':before').color;

此外,也可以使用 CSSStyleDeclaration 實(shí)例的getPropertyValue方法,獲取偽元素的屬性。

var result = window.getComputedStyle(test, ':before')
  .getPropertyValue('content');
var color = window.getComputedStyle(test, ':before')
  .getPropertyValue('color');

StyleSheet 接口

概述

StyleSheet接口代表網(wǎng)頁(yè)的一張樣式表,包括<link>元素加載的樣式表和<style>元素內(nèi)嵌的樣式表。

document對(duì)象的styleSheets屬性,可以返回當(dāng)前頁(yè)面的所有StyleSheet實(shí)例(即所有樣式表)。它是一個(gè)類似數(shù)組的對(duì)象。

var sheets = document.styleSheets;
var sheet = document.styleSheets[0];
sheet instanceof StyleSheet // true

如果是<style>元素嵌入的樣式表,還有另一種獲取StyleSheet實(shí)例的方法,就是這個(gè)節(jié)點(diǎn)元素的sheet屬性。

// HTML 代碼為 <style id="myStyle"></style>
var myStyleSheet = document.getElementById('myStyle').sheet;
myStyleSheet instanceof StyleSheet // true

嚴(yán)格地說,StyleSheet接口不僅包括網(wǎng)頁(yè)樣式表,還包括 XML 文檔的樣式表。所以,它有一個(gè)子類CSSStyleSheet表示網(wǎng)頁(yè)的 CSS 樣式表。我們?cè)诰W(wǎng)頁(yè)里面拿到的樣式表實(shí)例,實(shí)際上是CSSStyleSheet的實(shí)例。這個(gè)子接口繼承了StyleSheet的所有屬性和方法,并且定義了幾個(gè)自己的屬性,下面把這兩個(gè)接口放在一起介紹。

實(shí)例屬性

StyleSheet實(shí)例有以下屬性。

(1)StyleSheet.disabled

StyleSheet.disabled返回一個(gè)布爾值,表示該樣式表是否處于禁用狀態(tài)。手動(dòng)設(shè)置disabled屬性為true,等同于在<link>元素里面,將這張樣式表設(shè)為alternate stylesheet,即該樣式表將不會(huì)生效。

注意,disabled屬性只能在 JavaScript 腳本中設(shè)置,不能在 HTML 語(yǔ)句中設(shè)置。

(2)Stylesheet.href

Stylesheet.href返回樣式表的網(wǎng)址。對(duì)于內(nèi)嵌樣式表,該屬性返回null。該屬性只讀。

document.styleSheets[0].href

(3)StyleSheet.media

StyleSheet.media屬性返回一個(gè)類似數(shù)組的對(duì)象(MediaList實(shí)例),成員是表示適用媒介的字符串。表示當(dāng)前樣式表是用于屏幕(screen),還是用于打?。╬rint)或手持設(shè)備(handheld),或各種媒介都適用(all)。該屬性只讀,默認(rèn)值是screen。

document.styleSheets[0].media.mediaText
// "all"

MediaList實(shí)例的appendMedium方法,用于增加媒介;deleteMedium方法用于刪除媒介。

document.styleSheets[0].media.appendMedium('handheld');
document.styleSheets[0].media.deleteMedium('print');

(4)StyleSheet.title

StyleSheet.title屬性返回樣式表的title屬性。

(5)StyleSheet.type

StyleSheet.type屬性返回樣式表的type屬性,通常是text/css

document.styleSheets[0].type  // "text/css"

(6)StyleSheet.parentStyleSheet

CSS 的@import命令允許在樣式表中加載其他樣式表。StyleSheet.parentStyleSheet屬性返回包含了當(dāng)前樣式表的那張樣式表。如果當(dāng)前樣式表是頂層樣式表,則該屬性返回null。

if (stylesheet.parentStyleSheet) {
  sheet = stylesheet.parentStyleSheet;
} else {
  sheet = stylesheet;
}

(7)StyleSheet.ownerNode

StyleSheet.ownerNode屬性返回StyleSheet對(duì)象所在的 DOM 節(jié)點(diǎn),通常是<link><style>。對(duì)于那些由其他樣式表引用的樣式表,該屬性為null。

// HTML代碼為
// <link rel="StyleSheet" href="example.css" type="text/css" />
document.styleSheets[0].ownerNode // [object HTMLLinkElement]

(8)CSSStyleSheet.cssRules

CSSStyleSheet.cssRules屬性指向一個(gè)類似數(shù)組的對(duì)象(CSSRuleList實(shí)例),里面每一個(gè)成員就是當(dāng)前樣式表的一條 CSS 規(guī)則。使用該規(guī)則的cssText屬性,可以得到 CSS 規(guī)則對(duì)應(yīng)的字符串。

var sheet = document.querySelector('#styleElement').sheet;

sheet.cssRules[0].cssText
// "body { background-color: red; margin: 20px; }"

sheet.cssRules[1].cssText
// "p { line-height: 1.4em; color: blue; }"

每條 CSS 規(guī)則還有一個(gè)style屬性,指向一個(gè)對(duì)象,用來讀寫具體的 CSS 命令。

cssStyleSheet.cssRules[0].style.color = 'red';
cssStyleSheet.cssRules[1].style.color = 'purple';

(9)CSSStyleSheet.ownerRule

有些樣式表是通過@import規(guī)則輸入的,它的ownerRule屬性會(huì)返回一個(gè)CSSRule實(shí)例,代表那行@import規(guī)則。如果當(dāng)前樣式表不是通過@import引入的,ownerRule屬性返回null。

實(shí)例方法

(1)CSSStyleSheet.insertRule()

CSSStyleSheet.insertRule方法用于在當(dāng)前樣式表的插入一個(gè)新的 CSS 規(guī)則。

var sheet = document.querySelector('#styleElement').sheet;
sheet.insertRule('#block { color: white }', 0);
sheet.insertRule('p { color: red }', 1);

該方法可以接受兩個(gè)參數(shù),第一個(gè)參數(shù)是表示 CSS 規(guī)則的字符串,這里只能有一條規(guī)則,否則會(huì)報(bào)錯(cuò)。第二個(gè)參數(shù)是該規(guī)則在樣式表的插入位置(從0開始),該參數(shù)可選,默認(rèn)為0(即默認(rèn)插在樣式表的頭部)。注意,如果插入位置大于現(xiàn)有規(guī)則的數(shù)目,會(huì)報(bào)錯(cuò)。

該方法的返回值是新插入規(guī)則的位置序號(hào)。

注意,瀏覽器對(duì)腳本在樣式表里面插入規(guī)則有很多限制。所以,這個(gè)方法最好放在try...catch里使用。

(2)CSSStyleSheet.deleteRule()

CSSStyleSheet.deleteRule方法用來在樣式表里面移除一條規(guī)則,它的參數(shù)是該條規(guī)則在cssRules對(duì)象中的位置。該方法沒有返回值。

document.styleSheets[0].deleteRule(1);

實(shí)例:添加樣式表

網(wǎng)頁(yè)添加樣式表有兩種方式。一種是添加一張內(nèi)置樣式表,即在文檔中添加一個(gè)<style>節(jié)點(diǎn)。

// 寫法一
var style = document.createElement('style');
style.setAttribute('media', 'screen');
style.innerHTML = 'body{color:red}';
document.head.appendChild(style);

// 寫法二
var style = (function () {
  var style = document.createElement('style');
  document.head.appendChild(style);
  return style;
})();
style.sheet.insertRule('.foo{color:red;}', 0);

另一種是添加外部樣式表,即在文檔中添加一個(gè)<link>節(jié)點(diǎn),然后將href屬性指向外部樣式表的 URL。

var linkElm = document.createElement('link');
linkElm.setAttribute('rel', 'stylesheet');
linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('href', 'reset-min.css');

document.head.appendChild(linkElm);

CSSRuleList 接口

CSSRuleList 接口是一個(gè)類似數(shù)組的對(duì)象,表示一組 CSS 規(guī)則,成員都是 CSSRule 實(shí)例。

獲取 CSSRuleList 實(shí)例,一般是通過StyleSheet.cssRules屬性。

// HTML 代碼如下
// <style id="myStyle">
//   h1 { color: red; }
//   p { color: blue; }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var crl = myStyleSheet.cssRules;
crl instanceof CSSRuleList // true

CSSRuleList 實(shí)例里面,每一條規(guī)則(CSSRule 實(shí)例)可以通過rules.item(index)或者rules[index]拿到。CSS 規(guī)則的條數(shù)通過rules.length拿到。還是用上面的例子。

crl[0] instanceof CSSRule // true
crl.length // 2

注意,添加規(guī)則和刪除規(guī)則不能在 CSSRuleList 實(shí)例操作,而要在它的父元素 StyleSheet 實(shí)例上,通過StyleSheet.insertRule()StyleSheet.deleteRule()操作。

CSSRule 接口

概述

一條 CSS 規(guī)則包括兩個(gè)部分:CSS 選擇器和樣式聲明。下面就是一條典型的 CSS 規(guī)則。

.myClass {
  color: red;
  background-color: yellow;
}

JavaScript 通過 CSSRule 接口操作 CSS 規(guī)則。一般通過 CSSRuleList 接口(StyleSheet.cssRules)獲取 CSSRule 實(shí)例。

// HTML 代碼如下
// <style id="myStyle">
//   .myClass {
//     color: red;
//     background-color: yellow;
//   }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var ruleList = myStyleSheet.cssRules;
var rule = ruleList[0];
rule instanceof CSSRule // true

CSSRule 實(shí)例的屬性

(1)CSSRule.cssText

CSSRule.cssText屬性返回當(dāng)前規(guī)則的文本,還是使用上面的例子。

rule.cssText
// ".myClass { color: red; background-color: yellow; }"

如果規(guī)則是加載(@import)其他樣式表,cssText屬性返回@import 'url'

(2)CSSRule.parentStyleSheet

CSSRule.parentStyleSheet屬性返回當(dāng)前規(guī)則所在的樣式表對(duì)象(StyleSheet 實(shí)例),還是使用上面的例子。

rule.parentStyleSheet === myStyleSheet // true

(3)CSSRule.parentRule

CSSRule.parentRule屬性返回包含當(dāng)前規(guī)則的父規(guī)則,如果不存在父規(guī)則(即當(dāng)前規(guī)則是頂層規(guī)則),則返回null。

父規(guī)則最常見的情況是,當(dāng)前規(guī)則包含在@media規(guī)則代碼塊之中。

// HTML 代碼如下
// <style id="myStyle">
//   @supports (display: flex) {
//     @media screen and (min-width: 900px) {
//       article {
//         display: flex;
//       }
//     }
//  }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var ruleList = myStyleSheet.cssRules;

var rule0 = ruleList[0];
rule0.cssText
// "@supports (display: flex) {
//    @media screen and (min-width: 900px) {
//      article { display: flex; }
//    }
// }"

// 由于這條規(guī)則內(nèi)嵌其他規(guī)則,
// 所以它有 cssRules 屬性,且該屬性是 CSSRuleList 實(shí)例
rule0.cssRules instanceof CSSRuleList // true

var rule1 = rule0.cssRules[0];
rule1.cssText
// "@media screen and (min-width: 900px) {
//   article { display: flex; }
// }"

var rule2 = rule1.cssRules[0];
rule2.cssText
// "article { display: flex; }"

rule1.parentRule === rule0 // true
rule2.parentRule === rule1 // true

(4)CSSRule.type

CSSRule.type屬性返回一個(gè)整數(shù)值,表示當(dāng)前規(guī)則的類型。

最常見的類型有以下幾種。

  • 1:普通樣式規(guī)則(CSSStyleRule 實(shí)例)
  • 3:@import規(guī)則
  • 4:@media規(guī)則(CSSMediaRule 實(shí)例)
  • 5:@font-face規(guī)則

CSSStyleRule 接口

如果一條 CSS 規(guī)則是普通的樣式規(guī)則(不含特殊的 CSS 命令),那么除了 CSSRule 接口,它還部署了 CSSStyleRule 接口。

CSSStyleRule 接口有以下兩個(gè)屬性。

(1)CSSStyleRule.selectorText

CSSStyleRule.selectorText屬性返回當(dāng)前規(guī)則的選擇器。

var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].selectorText // ".myClass"

注意,這個(gè)屬性是可寫的。

(2)CSSStyleRule.style

CSSStyleRule.style屬性返回一個(gè)對(duì)象(CSSStyleDeclaration 實(shí)例),代表當(dāng)前規(guī)則的樣式聲明,也就是選擇器后面的大括號(hào)里面的部分。

// HTML 代碼為
// <style id="myStyle">
//   p { color: red; }
// </style>
var styleSheet = document.getElementById('myStyle').sheet;
styleSheet.cssRules[0].style instanceof CSSStyleDeclaration
// true

CSSStyleDeclaration 實(shí)例的cssText屬性,可以返回所有樣式聲明,格式為字符串。

styleSheet.cssRules[0].style.cssText
// "color: red;"
styleSheet.cssRules[0].selectorText
// "p"

CSSMediaRule 接口

如果一條 CSS 規(guī)則是@media代碼塊,那么它除了 CSSRule 接口,還部署了 CSSMediaRule 接口。

該接口主要提供media屬性和conditionText屬性。前者返回代表@media規(guī)則的一個(gè)對(duì)象(MediaList 實(shí)例),后者返回@media規(guī)則的生效條件。

// HTML 代碼如下
// <style id="myStyle">
//   @media screen and (min-width: 900px) {
//     article { display: flex; }
//   }
// </style>
var styleSheet = document.getElementById('myStyle').sheet;
styleSheet.cssRules[0] instanceof CSSMediaRule
// true

styleSheet.cssRules[0].media
//  {
//    0: "screen and (min-width: 900px)",
//    appendMedium: function,
//    deleteMedium: function,
//    item: function,
//    length: 1,
//    mediaText: "screen and (min-width: 900px)"
// }

styleSheet.cssRules[0].conditionText
// "screen and (min-width: 900px)"

window.matchMedia()

基本用法

window.matchMedia()方法用來將 CSS 的Media Query條件語(yǔ)句,轉(zhuǎn)換成一個(gè) MediaQueryList 實(shí)例。

var mdl = window.matchMedia('(min-width: 400px)');
mdl instanceof MediaQueryList // true

上面代碼中,變量mdl就是 mediaQueryList 的實(shí)例。

注意,如果參數(shù)不是有效的MediaQuery條件語(yǔ)句,window.matchMedia不會(huì)報(bào)錯(cuò),依然返回一個(gè) MediaQueryList 實(shí)例。

window.matchMedia('bad string') instanceof MediaQueryList // true

MediaQueryList 接口的實(shí)例屬性

MediaQueryList 實(shí)例有三個(gè)屬性。

(1)MediaQueryList.media

MediaQueryList.media屬性返回一個(gè)字符串,表示對(duì)應(yīng)的 MediaQuery 條件語(yǔ)句。

var mql = window.matchMedia('(min-width: 400px)');
mql.media // "(min-width: 400px)"

(2)MediaQueryList.matches

MediaQueryList.matches屬性返回一個(gè)布爾值,表示當(dāng)前頁(yè)面是否符合指定的 MediaQuery 條件語(yǔ)句。

if (window.matchMedia('(min-width: 400px)').matches) {
  /* 當(dāng)前視口不小于 400 像素 */
} else {
  /* 當(dāng)前視口小于 400 像素 */
}

下面的例子根據(jù)mediaQuery是否匹配當(dāng)前環(huán)境,加載相應(yīng)的 CSS 樣式表。

var result = window.matchMedia("(max-width: 700px)");

if (result.matches){
  var linkElm = document.createElement('link');
  linkElm.setAttribute('rel', 'stylesheet');
  linkElm.setAttribute('type', 'text/css');
  linkElm.setAttribute('href', 'small.css');

  document.head.appendChild(linkElm);
}

(3)MediaQueryList.onchange

如果 MediaQuery 條件語(yǔ)句的適配環(huán)境發(fā)生變化,會(huì)觸發(fā)change事件。MediaQueryList.onchange屬性用來指定change事件的監(jiān)聽函數(shù)。該函數(shù)的參數(shù)是change事件對(duì)象(MediaQueryListEvent 實(shí)例),該對(duì)象與 MediaQueryList 實(shí)例類似,也有mediamatches屬性。

var mql = window.matchMedia('(max-width: 600px)');

mql.onchange = function(e) {
  if (e.matches) {
    /* 視口不超過 600 像素 */
  } else {
    /* 視口超過 600 像素 */
  }
}

上面代碼中,change事件發(fā)生后,存在兩種可能。一種是顯示寬度從600像素以上變?yōu)橐韵?,另一種是從600像素以下變?yōu)橐陨希栽诒O(jiān)聽函數(shù)內(nèi)部要判斷一下當(dāng)前是哪一種情況。

MediaQueryList 接口的實(shí)例方法

MediaQueryList 實(shí)例有兩個(gè)方法MediaQueryList.addListener()MediaQueryList.removeListener(),用來為change事件添加或撤銷監(jiān)聽函數(shù)。

var mql = window.matchMedia('(max-width: 600px)');

// 指定監(jiān)聽函數(shù)
mql.addListener(mqCallback);

// 撤銷監(jiān)聽函數(shù)
mql.removeListener(mqCallback);

function mqCallback(e) {
  if (e.matches) {
    /* 視口不超過 600 像素 */
  } else {
    /* 視口超過 600 像素 */
  }
}

注意,MediaQueryList.removeListener()方法不能撤銷MediaQueryList.onchange屬性指定的監(jiān)聽函數(shù)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)