1. 使用樣式表
可以通過document.styleSheets屬性訪問文檔中可用的CSS樣式表,它會返回一組對象集合,這些對象代表了與文檔管理的各個樣式表。
每個樣式表 都由一個CSSStyleSheet 對象代表,它提供了一組屬性和方法來操作文檔里的樣式。
1.1 獲得樣式表的基本信息
第一步是獲得定義在文檔中的樣式表的一些基本信息。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>為DOM元素設置樣式</title> <style title="core styles"> p {border: medium double green; background-color: lightgray;} #block1 {color: white;} table {border: thin solid red;border-collapse: collapse; margin: 5px;float: left;} td {padding: 2px;} </style> <link rel="stylesheet" type="text/css" href="css/style.css" /> <style media="screen AND (min-width:500px)" type="text/css"> #block2 {color: yellow;font-style: italic;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱 </p> <p id="block2"> 一些年輕人,通過高端消費來營造自己高端收入的形象 </p> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); var sheets = document.styleSheets; for(var i= 0;i<sheets.length;i++){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); addRow(newElem,"Index",i); addRow(newElem,"href",sheets[i].href); addRow(newElem,"title",sheets[i].title); addRow(newElem,"type",sheets[i].type); addRow(newElem,"ownerNode",sheets[i].ownerNode.tagName); placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例枚舉了文檔內定義的所有樣式表,並為每個樣式都創建了一個table元素以容納可用的基本信息。這個文檔里有三個樣式表。其中兩個是用script元素定義的,另一個則包含在名為style.css的外部文件里,是通過link元素導入文檔中的。從下圖可以看到腳本輸出的結果:
請注意,不是所有的屬性都帶有值。舉個栗子,href 屬性只有在樣式表由外部文件載入時才會返回一個值。
1.2 使用媒介限制
當定義樣式表時可以使用media屬性來限制樣式應用的場合。可以使用CSSStyleSheet.media 屬性訪問這些限制,它會返回一個 MediaList 對象。下表介紹了MediaList對象的方法和屬性:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用MediaList對象</title> <style title="core styles"> p {border: medium double green; background-color: lightgray;} #block1 {color: white;} table {border: thin solid red;border-collapse: collapse; margin: 5px;float: left;} td {padding: 2px;} </style> <link rel="stylesheet" type="text/css" href="../css/style.css" /> <style media="screen AND (min-width:500px)" type="text/css"> #block2 {color: yellow;font-style: italic;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱 </p> <p id="block2"> 一些年輕人,通過高端消費來營造自己高端收入的形象 </p> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); var sheets = document.styleSheets; for(var i = 0; i < sheets.length; i++){ if(sheets[i].media.length > 0){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); addRow(newElem,"Media Count",sheets[i].media.length); addRow(newElem,"Media Text",sheets[i].media.mediaText); for(var j = 0;j < sheets[i].media.length; j++){ addRow(newElem,"Media " + j, sheets[i].media.item(j)); } placeholder.appendChild(newElem); } } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例中,為所有具備media屬性的樣式表分別創建了一張表格,並枚舉了其中的各個媒介、屬性值里的媒介總數和整個media字符串。
1.3 禁用樣式表
CSSStyleSheet.disabled屬性可以用來一次性啟動和禁用某個樣式表里的所有樣式。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>啟用和禁用樣式表</title> <style title="core styles"> p {border: medium double green; background-color: lightgray;} #block1 {color: white;border: thick solid green; background-color: gray;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div><button id="pressme">Press Me</button></div> <script> document.getElementById("pressme").onclick = function(){ document.styleSheets[0].disabled = !document.styleSheets[0].disabled; } </script> </body> </html>
此例中,點擊按鈕會切換(唯一一個)樣式表上disabled屬性的值。一旦樣式表被禁用,它所包含的任何樣式都不會被應用到元素上。
1.4 CSSRuleList對象的成員
CSSStyleSheet.cssRules屬性會返回一個CSSRuleList對象,它允許你訪問樣式表里的各種樣式。下表介紹了這個對象的成員。
樣式表里的每一種CSS樣式都由一個CSSStyleRule對象代表。
下面的例子展示了CSSRuleList對象的用法和CSSStyleRule對象的基本屬性。這里說的基本是因為style屬性所返回的CSSStyleDeclaration對象可以深入樣式內部,而且給某個元素應用樣式時用的也是這個對象。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用CSSRuleList和CSSStyleRule對象</title> <style title="core styles"> p {border: medium double green; background-color: lightgray;} #block1 {color: white;} table {border: thin solid red;border-collapse: collapse; margin: 5px;float: left;} td {padding: 2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <p id="block2"> 一些年輕人,通過高端消費來營造自己高端收入的形象。 </p> <div><button id="pressme">Press Me</button> </div> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); processStyleSheet(); document.getElementById("pressme").onclick = function(){ document.styleSheets[0].cssRules.item(1).selectorText = "#block2"; if(placeholder.hasChildNodes()){ var childCount = placeholder.childNodes.length; for(var i = 0; i < childCount; i++){ placeholder.removeChild(placeholder.firstChild); } } processStyleSheet(); } function processStyleSheet(){ var ruleList = document.styleSheets[0].cssRules; for(var i = 0; i < ruleList.length; i++){ var rule = ruleList.item(i); var newElem = document.createElement("table"); newElem.setAttribute("border","1"); addRow(newElem,"parentStyleSheet",rule.parentStyleSheet.title); addRow(newElem,"selectorText",rule.selectorText); addRow(newElem,"cssText",rule.cssText); placeholder.appendChild(newElem); } } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例對這些對象做了兩件事。第一件事是簡單地獲取已定義樣式的信息,報告它的父樣式表、選擇器和樣式所包含的各條規則聲明。
這段腳本還演示了如何輕松改變某個樣式。點擊button后,其中一個樣式的選擇器會從#block1變成#block2,產生的效果是改變了此樣式所應用的p元素。就像其他對DOM的改動一樣,瀏覽器會立即反映出新選擇器並更新樣式應用的方式。
2. 使用元素樣式
要獲取某個元素的style屬性所定義的樣式屬性,需要讀取HTMLElement對象里定義的style屬性值。style屬性會返回一個CSSStyleDeclaration對象,它和通過樣式表所獲取的對象屬於同一類型。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>從一個HTMLElement上獲取CSSStyleDeclaration對象</title> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div><button id="pressme">Press Me</button> </div> <div id="placeholder"></div> <script> var placeholder = $("placeholder"); var targetElem = $("block1"); displayStyle(); $("pressme").onclick = function(){ targetElem.style.cssText = "color:green;" displayStyle(); } function displayStyle(){ if(placeholder.hasChildNodes()){ placeholder.removeChild(placeholder.firstChild); } var newElem = document.createElement("table"); addRow(newElem,"Element CSS",targetElem.style.cssText); placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } function $(id){ return document.getElementById(id); } </script> </body> </html>
這段腳本會顯示某個元素的style屬性值,並且button被點擊后還會修改這個值以應用另一種樣式。
3. 使用CSSStyleDeclaration對象
處理的是樣式表還是某個元素的style屬性並不重要。要通過DOM完全控制CSS,必須使用CSSStyleDeclaration對象。
除了item方法,大多數瀏覽器還支持數組風格的表示法,因此 item(4) 和 item[4] 是等價的。
3.1 使用便捷屬性
操作CSSStyleDeclaration 對象最簡單的方式是使用便捷屬性,它們分別對應各個CSS屬性。可以通過讀取對象屬性來確定對應CSS屬性的當前值,並通過給對象屬性指派新值來改變CSS的值。
PS:此節里讀取和修改的值屬於設置值(configured value)。實際讀取和修改的是定義在HTML文檔中的值,它們或者位於樣式表中,或者直接被應用到元素上。當瀏覽器准備顯示某個元素時,它會生成一組計算值(computed value),通過模型來處理瀏覽器樣式、樣式表和style屬性的層疊和繼承。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用CSSStyleDeclaration對象的便捷屬性</title> <style title="core styles"> #block1 {color: white;border:thick solid green;background-color: gray;} p {border: medium double blue; background-color: lightgray;} table {border: thin solid red;border-collapse: collapse;margin: 5px;float: left;} td {padding: 2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <p id="block2" style="border:medium dashed yellow;color: red;padding: 2px;"> 一些年輕人,通過高端消費來營造自己高端收入的形象。 </p> <div><button id="pressme">Press Me</button> </div> <div id="placeholder"></div> <script> var placeholder = $("placeholder"); displayStyles(); $("pressme").onclick = function(){ document.styleSheets[0].cssRules.item(1).style.paddingTop = "10px"; document.styleSheets[0].cssRules.item(1).style.paddingRight = "12px"; document.styleSheets[0].cssRules.item(1).style.paddingLeft = "5px"; document.styleSheets[0].cssRules.item(1).style.paddingBottom = "5px"; displayStyles(); } function displayStyles(){ if(placeholder.hasChildNodes()){ var childCount = placeholder.childNodes.length; for(var i=0;i<childCount;i++){ placeholder.removeChild(placeholder.firstChild); } } displayStyleProperties(document.styleSheets[0].cssRules.item(1).style); displayStyleProperties($("block2").style); } function displayStyleProperties(style){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); addRow(newElem,"border",style.border); addRow(newElem,"color",style.color); addRow(newElem,"padding",style.padding); addRow(newElem,"paddingTop",style.paddingTop); placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } function $(id){ return document.getElementById(id); } </script> </body> </html>
此例的腳本顯示了4個CSSStyleDeclaration便捷屬性的值。它們分別讀取自從樣式表獲得的對象和元素的 style屬性,以此演示獲得這些對象的兩種方式。
便捷屬性border、color 和 padding 各自對應於同名CSS屬性。便捷屬性 paddingTop 對應於CSS的padding-top 屬性。這就是多單詞CSS屬性的一般命名模式:去掉連字符,然后大寫第二個及之后單詞的首字母。簡寫的CSS屬性和單獨屬性都有着對應的便捷屬性(比如,padding 和 paddingTop)。如果沒有給CSS屬性設置值,那么對應的便捷屬性就會返回一個空白字符串(" ")。
當按鈕被按下后,腳本會修改各個單獨的內邊距屬性值,具體做法是使用來自文檔第一個樣式表的CSSStyleDeclaration對象上的便捷屬性 paddingTop、paddingBottom、paddingLeft 和 paddingRight。從上面的顯示效果中,可以看到這些值的變動不僅立即影響了文檔的外觀,而且還與簡寫和單獨便捷屬性進行了同步,使它們反映出這些新值。
3.2 使用常規屬性
如果明確知道需要處理的CSS屬性名稱,而且存在相應的便捷屬性,那么使用便捷屬性是件很簡單的事。如果需要以程序方式探索CSS屬性,或者需要獲取/設置某個沒有對應便捷屬性的CSS屬性,那么CSSStyleDeclaration對象的其他成員可能會派上用場。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用CSSStyleDeclaration對象的常規屬性</title> <style title="core styles"> p {color: white; border: medium double green;background-color: lightgray;padding-top: 5px;} table {border: thin solid red;border-collapse: collapse;margin: 5px;float: left;} td {padding: 2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div><button id="pressme">Press Me</button> </div> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); displayStyles(); document.getElementById("pressme").onclick = function(){ var styleDeclr = document.styleSheets[0].cssRules[0].style; styleDeclr.setProperty("background-color","gray"); styleDeclr.setProperty("padding-top","20px") styleDeclr.setProperty("color","blue"); displayStyles(); } function displayStyles(){ if(placeholder.hasChildNodes()){ var childCount = placeholder.childNodes.length; for(var i=0;i<childCount;i++){ placeholder.removeChild(placeholder.firstChild); } } var newElem = document.createElement("table"); newElem.setAttribute("border","1"); var style = document.styleSheets[0].cssRules[0].style; addRow(newElem,"border",style.getPropertyValue("border")); addRow(newElem,"color",style.getPropertyValue("color")); addRow(newElem,"padding-top",style.getPropertyValue("padding-top")); addRow(newElem,"background-color",style.getPropertyValue("background-color")); placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例只從一個來源讀取樣式屬性:樣式表。使用getPropertyValue方法來獲得某個CSS屬性的值,並用setProperty方法定義新值。請注意在這些方法中要使用真正的CSS屬性名,而非便捷屬性的名稱。
(1)以程序方式探索屬性
到目前為止,在示例里都顯示指定了想要操作的CSS屬性名稱。如果在事先不知情的情況下獲取已應用哪些屬性的信息,就必須通過CSSStyleDeclaration的成員進行探索。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>以程序方式探索CSS屬性</title> <style title="core styles"> p {color:white;background-color: gray;padding: 5px;} table {border: thin solid orange;border-collapse: collapse;margin: 5px;float: left;} td {padding:2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); displayStyles(); function displayStyles(){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); var style = document.styleSheets[0].cssRules[0].style; for(var i=0;i<style.length;i++){ addRow(newElem,style[i],style.getPropertyValue(style[i])); } placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例中的腳本枚舉了樣式表第一條樣式的所有屬性。
(2)獲知樣式屬性的重要性
可以應用 !important 到某條屬性聲明上,讓瀏覽器優先使用這個值顯示元素。操作CSSStyleDeclaration 對象時可以使用 getPropertyPrority 方法來查看!important是否已被應用到某個屬性上。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>獲知某個屬性的重要性</title> <style> p {color: white;background-color: gray !important;padding: 5px !important;} table {border: thin solid orange;border-collapse: collapse;margin: 5px;float: left;} td {padding: 2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); displayStyles(); function displayStyles(){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); var style = document.styleSheets[0].cssRules[0].style; for(var i=0;i<style.length;i++){ addRow(newElem,style[i],style.getPropertyPriority(style[i])); } placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
getPropertyPriority 方法對高優先級的值會返回 important ,如果沒有指定重要性則會返回一個空白字符串(" ")。
PS:可以使用setProperty方法來指定某個值是否重要。如果要想給某個值應用!important,可以將important作為第三個參數指給setProperty方法。
4. 使用計算樣式
目前為止的例子都把焦點放在了樣式表或style屬性中指定的CSS屬性值上。這對確定文檔里直接包含了什么很有用,但瀏覽器會從多個來源匯聚樣式以計算出該用哪個值來顯示某一元素。這里包括了沒有為其顯示指定值的那些屬性,沒有指定的原因或是值是繼承的,或是某種瀏覽器樣式慣例。
瀏覽器用於顯示某個元素的CSS屬性值集合被稱為計算樣式。可以通過 document.default.getComputedStyle 方法獲取包含某一元素計算樣式的CSSStyleDeclaration對象。用這個方法獲得的對象包含了瀏覽器用來顯示元素的所有屬性細節,以及各個屬性的值。
PS:無法通過以 getComputedStyle方法獲得的CSSStyleDeclaration 對象修改計算樣式。要做到這一點,必須修改樣式表,或者通過元素的style屬性直接給它應用樣式屬性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用某個元素的計算樣式</title> <style> p {padding: 7px !important;} table {border: thin solid orange;border-collapse: collapse;margin: 5px;float: left;} td {padding: 2px;} </style> </head> <body> <p id="block1"> 你承受的苦難並不比他人多太多,痛苦主要來自敏感和脆弱。 </p> <div id="placeholder"></div> <script> var placeholder = document.getElementById("placeholder"); displayStyles(); function displayStyles(){ var newElem = document.createElement("table"); newElem.setAttribute("border","1"); var targetElem = document.getElementById("block1"); var style = document.defaultView.getComputedStyle(targetElem); addRow(newElem,"Property Count",style.length); addRow(newElem,"margin-top",style.getPropertyValue("margin-top")); addRow(newElem,"font-size",style.getPropertyValue("font-size")); addRow(newElem,"font-family",style.getPropertyValue("font-family")); placeholder.appendChild(newElem); } function addRow(elem,header,value){ elem.innerHTML += "<tr><td>" + header + ":</td><td>" + value + "</td></tr>"; } </script> </body> </html>
此例中,展示了一些未曾定義過的屬性值。下圖可以看到它的效果。表格的第一行報告了計算樣式含有多少屬性。這個數字根據瀏覽器的不同會有所增減。