使用JavaScript動態新增CSS樣式規則
原文連結: Add Rules to Stylesheets with JavaScript
原文日期: 2014-09-04
翻譯日期: 2014-09-05
翻譯人員: 鐵錨
現在Web應用中有大量的JavaScript程式碼,而我們也一直在追尋各種使他們更快的解決方案。
- 我們通過 事件代理(event delegation) 讓事件監聽更高效,
- 我們利用 函式降頻技術(function debouncing) 來限制一段時間內給定方法被呼叫的次數,請參考: 如何防止事件函式的高頻觸發(中文翻譯)
- 我們使用 JavaScript載入器 來載入我們確實需要的那部分資源,等等。
還有一種方式,可以讓我們的頁面更加的快速和高效.那就是直接通過JS動態地新增和刪除樣式表中的某些樣式,用來取代不斷地查詢DOM元素,並應用各種樣式。下面是它的工作原理。
獲取樣式表
你可以選擇任意的樣式表來新增樣式規則。如果你有確定的樣式表,則可以在HTML頁面中給 <link> 或 <style> 標籤新增ID屬性,然後直接通過這個DOM元素的 sheet 屬性就可以取得 CSSStyleSheet 物件。樣式表也可以通過 document.styleSheets 遍歷到:
// 返回一個類似陣列的(Array-like)樣式列表 StyleSheetList var sheets = document.styleSheets; /* 返回值類似下面這樣: StyleSheetList { 0: CSSStyleSheet, 1: CSSStyleSheet, 2: CSSStyleSheet, 3: CSSStyleSheet, 4: CSSStyleSheet, length: 5, item: function } */ // 獲取第一個sheet, 先不管 media屬性 var sheet = document.styleSheets[0];
需要特別注意的是樣式表的media屬性 —— 當你想在螢幕上顯示的時候,你肯定不能把CSS規則加到列印樣式表中。你可以仔細的看一下CSSStyleSheet物件的屬性資訊:
// 控制檯輸出第一個樣式表的資訊 console.log(document.styleSheets[0]); /* 返回值: CSSStyleSheet cssRules: CSSRuleList[物件] disabled: false href: "http://davidwalsh.name/somesheet.css" media: MediaList[物件] ownerNode: link[物件] ownerRule: null parentStyleSheet: null rules: CSSRuleList[物件] title: null type: "text/css" */ // 獲取媒體型別(media type) console.log(document.styleSheets[0].media.mediaText) /* 返回值可能是: "all" 或者 "print" 或者是其他應用到此樣式表的 media */
在各種情況下,你肯定都有辦法來獲取到要新增規則的樣式表。
建立一個新樣式表
在許多情況下,最好的方法可能是建立一個新的 <style> 元素來存放這些動態規則。這也很簡單:
var sheet = (function() { // 建立 <style> 標籤 var style = document.createElement("style"); // 可以新增一個媒體(/媒體查詢,media query)屬性 // style.setAttribute("media", "screen") // style.setAttribute("media", "only screen and (max-width : 1024px)") // 對WebKit hack ? style.appendChild(document.createTextNode("")); // 將 <style> 元素加到頁面中 document.head.appendChild(style); return style.sheet; })();
悲劇的是WebKit需要一點hack手段才能正確建立,但我們只需要關心這個sheet。
插入規則
在早期版本的IE中 Stylesheets 的 insertRule方法並不可用,雖然現在這是規則注入的標準。insertRule 方法需要編寫整個CSS規則,和在樣式表中是一樣的寫法:
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);
這個JavaScript API方法雖然看起來有點土,但它確實就是這樣執行的。第二個引數 index 表示要插入規則的位置(索引)。這也是非常有用的,這樣你就可以插入同樣的規則/程式碼,這可以讓靠後的規則生效。預設的index是 -1 ,代表整個集合的末尾。如果想要有額外的/懶惰控制規則,你也可以新增 !important 標記到某條規則後,以避免索引的問題。
新增規則 —— 非標準的 addRule 方法
CSSStyleSheet 物件有一個 addRule 方法,允許你註冊CSS規則到樣式表中。 addRule 方法接受三個引數: 第一個引數是選擇器(selector)、第二個引數是CSS規則程式碼, 第三個則是從0開始的整數索引,表示樣式的位置(在同一個選擇器中):
sheet.addRule("#myList li", "float: left; background: red !important;", 1);
addRule方法的返回值總是 -1,所以這個值並沒有什麼實際意義.
記住,這種方式的優點在於,從頁面新增的元素自動擁有了應用於他們的樣式,也就是說你不必將它們新增到具體的元素上,而是直接注入到頁面中。當然效率更高!
安全應用規則
因為並不是所有的瀏覽器都支援 insertRule 方法, 所以最好建立一個包裝函式來處理規則應用。下面是一個快速的土方法:
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); } } // 使用方式 addCSSRule(document.styleSheets[0], "header", "float: left");
這個工具方法應該涵蓋了新增style規則的所有情況。如果你擔心在應用中出錯, 那麼應該將該方法的程式碼用一個 try{} catch(e){} 塊包起來。
插入媒體查詢規則
媒體查詢規則的新增有兩種方式。第一個是使用標準 insertRule 方法:
sheet.insertRule( "@media only screen and (max-width : 1140px) { header { display: none; } }" );
當然,因為IE老版本不支援 insertRule,所以另一種方法就是建立一個 STYLE 元素,並指定適當的 media 屬性,然後將樣式新增到新的樣式表中。這可能需要使用多個 STYLE 元素,但也是很容易的。我可能會建立一個物件,指定媒體查詢以及索引,並那樣建立/獲取他們。
動態新增規則到樣式表是高效的手段,可能比你想象的還要簡單。請記住這種方案,可能在你的下一個大應用中需要使用,因為它能在程式碼和元素處理這兩方面避免你掉進坑裡。
相關文章
- javascript 動態修改css樣式JavaScriptCSS
- JavaScript動態建立div並新增樣式JavaScript
- 001---css樣式規則及css字型樣式CSS
- CSS樣式規則-CSS結構的特點CSS
- CSS樣式規則之CSS結構的特點CSS
- Vue 動態繫結CSS樣式VueCSS
- JavaScript動態更改引入樣式表JavaScript
- js動態改變css偽類樣式JSCSS
- JavaScript動態新增li元素JavaScript
- Vue 框架-05-動態繫結 css 樣式Vue框架CSS
- JavaScript新增class樣式類程式碼JavaScript
- CSS新規範:樣式查詢CSS
- 使用CSS /動態表示式修復內容CSS
- JavaScript動態為table表格新增行JavaScript
- JavaScript 動態新增與刪除元素JavaScript
- 常用CSS樣式2:浮動CSS
- CSS使用者介面樣式CSS
- CSS規則物件概述CSS物件
- JavaScript動態新增或者刪除HTML元素JavaScriptHTML
- JavaScript動態新增和刪除div元素JavaScript
- lit動態修改樣式
- drools動態增加、修改、刪除規則
- JavaScript this 繫結規則JavaScript
- 事件繫結和樣式規定的原則事件
- 1.7 常用CSS樣式2:浮動CSS
- 純css美化滾動條樣式CSS
- css樣式CSS
- 什麼樣的問題應該使用動態規劃動態規劃
- CSS @page語法規則CSS
- AndroidJava動態修改CheckBox樣式AndroidJava
- 動態變更vue樣式Vue
- 使用 addRouteMiddleware 動態新增中間
- Java中動態規則的實現方式Java
- Drools與動態載入規則檔案
- SAP QM Dynamic Modification Rule (動態修改規則)
- javascript動態改變css3的animationJavaScriptCSSS3
- git 新增 gitignore 規則無效Git
- QT新增樣式表QSS/CSS檔案後不起作用QTCSS
- JavaScript中記憶體使用規則--堆和棧JavaScript記憶體