可構造樣式表 - 通過javascript來生成css的新方式
可構造樣式表是一種使用Shadow DOM進行建立和分發可重用樣式的新方法。
使用Javascript來建立樣式表是可能的。然而,這個過程在歷史上一直是使用document.createElement('style')來建立<style>元素,然後通過訪問其sheet屬性來獲得一個基礎的CSSStyleSheet例項的引用。這種方法可以生成重複的CSS,其會使得程式碼極速膨脹。無論是否存在臃腫,這種附加的動作會導致未樣式化內容的閃爍。CSSStyleSheet介面是CSS集合的根,被稱為CSSOM,提供一種程式化的方法去控制樣式,還有就是消除相關聯的舊程式碼的問題。
可構造的樣式表可以定義和準備共享的CSS樣式,然後輕鬆的吧這些樣式應用到多個Shadow Roots中或者是文件中,且無需重複。修改CSSStyleSheet以後,其相關聯的樣式也都會被改變。並且一旦載入了樣式表,其新樣式會很快且同步的載入到頁面中。
由Constructable Stylesheets建立的關聯很適合許多不同的應用程式。它可以被用於在多個不同的元件間提供一個集中的主題:主題可以傳遞到元件的是CSSStyleSheet的例項,當主題改變以後,會自動傳遞給元件。它可以不依賴樣式表,吧自定義CSS屬性分發給特定的DOM子樹中。它甚至可以直接用於瀏覽器解析器直接的介面,無需將他們注入到DOM就可以很輕易的載入樣式表。
構建一個樣式表
與引入一個新API不同,可構造樣式表規範使得其可以通過呼叫CSSStyleSheet()建構函式來強制建立樣式表。CSSStyleSheet物件的結果有兩個方法,這倆方法會使樣式表更安全的被新增和修改,其操作不會觸發無格式內容的閃光(FOUC)。replace()會返回一個Promise,一旦有外部引用(@import)被載入就會解析。而replaceSync()不允許外部引用。
const sheet = new CSSStyleSheet();// replace all styles synchronously: sheet.replaceSync('a { color: red; }');// this throws an exception:try { sheet.replaceSync('@import url("styles.css")');} catch (err) { console.error(err); // imports are not allowed}// replace all styles, allowing external resources: sheet.replace('@import url("styles.css")') .then(sheet => { console.log('Styles loaded successfully'); }) .catch(err => { console.error('Failed to load:', err); });
使用可構造樣式表
由可構造樣式表引入的第二個新功能是Shadow Roots和Documents中的adoptedStyleSheets屬性。這允許我們顯式的將由CSSStyleSheet定義的屬性應用到給定的DOM子樹中。為此,我們將屬性設定為一個具有一個或者多個樣式表的陣列,以用於該元素。
// Create our shared stylesheet:const sheet = new CSSStyleSheet(); sheet.replaceSync('a { color: red; }');// Apply the stylesheet to a document: document.adoptedStyleSheets = [sheet];// Apply the stylesheet to a Shadow Root:const node = document.createElement('div');const shadow = node.attachShadow({ mode: 'open' }); shadow.adoptedStyleSheets = [sheet];
注意我們是覆蓋了adoptedStyleSheets的值,而不是改變了陣列的值。這是必要的,因為這個陣列是被凍結的。像push()那樣改變值會丟擲一個異常,所以我們必須賦值一個新陣列。為了保留通過adoptedStyleSheets新增的已經存在樣式表。我們可以使用合併陣列的方式來建立一個新陣列,這個陣列包含已經存在的舊樣式,和新新增的新樣式。
const sheet = new CSSStyleSheet(); sheet.replaceSync('a { color: red; }');// Combine existing sheets with our new one: document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
總結
由於可構造樣式表,網站開發人員現在有一個建立CSS樣式表並且把他們應用到DOM樹中的一個明確的解決方案。我們有了一個新的基於Promise的API,用於從使用瀏覽器內建解析器和載入語義的CSS源字串中載入樣式表。最終,我們有一種機制,可以將樣式表更新應用於StyleSheet的所有用法,從而簡化主題更改和顏色首選項等操作。
展望未來
可構建樣式表的初始版本附帶了此處描述的API,但正在開展工作以使事情更容易使用。 有人建議使用專用方法擴充套件adoptStyleSheets FrozenArray以插入和刪除樣式表,這樣就不需要進行陣列克隆並避免可能的重複樣式表引用。
翻譯自: