使用共享樣式表設置 Web 組件樣式
已發表: 2022-03-10Web 組件是 Web 的一項驚人的新功能,允許開發人員定義自己的自定義 HTML 元素。 當與樣式指南結合使用時,Web 組件可以創建組件 API,它允許開發人員停止複制和粘貼代碼片段,而只需使用 DOM 元素。 通過使用 shadow DOM,我們可以封裝 Web 組件,而不必擔心與頁面上的任何其他樣式表發生特異性戰爭。
但是,Web 組件和样式指南目前似乎相互矛盾。 一方面,樣式指南提供了一組全局應用於頁面的規則和样式,並確保整個網站的一致性。 另一方面,帶有影子 DOM 的 Web 組件會阻止任何全局樣式穿透它們的封裝,從而防止樣式指南影響它們。
關於 SmashingMag 的進一步閱讀:
- 在基於組件的系統中實施最佳實踐
- 如何使用 LESS CSS 預處理器實現更智能的樣式表
- 深入了解 Adobe Edge 回流
那麼,如果全球樣式指南繼續提供一致性和样式,甚至對於帶有影子 DOM 的 Web 組件,這兩者如何共存呢? 值得慶幸的是,現在有一些可行的解決方案,而且還會有更多的解決方案,使全球樣式指南能夠為 Web 組件提供樣式。 (在本文的其餘部分,我將使用術語“Web 組件”來指代具有影子 DOM 的自定義元素。)
Web 組件中的全局樣式指南樣式應該是什麼?
在討論如何獲得全局樣式指南來設置 Web 組件的樣式之前,我們應該討論它應該和不應該嘗試設置什麼樣式。
首先,當前 Web 組件的最佳實踐表明 Web 組件(包括其樣式)應該被封裝,以便它不依賴任何外部資源來運行。 這使得它可以在網站內外的任何地方使用,即使樣式指南不可用。
下面是一個簡單的登錄表單 Web 組件,它封裝了它的所有樣式。
<template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } p { margin: 0; } p + p { margin-top: 20px; } a { color: #1f66e5; } label { display: block; margin-bottom: 5px; } input[type="text"], input[type="password"] { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } input[type="submit"] { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <div class="container"> <form action="#"> <p> <label for="username">User Name</label> <input type="text" name="username"> </p> <p> <label for="password">Password</label> <input type="password" name="password"> </p> <p> <input type="submit" value="Login"> </p> <p class="footnote">Not registered? <a href="#">Create an account</a></p> </form> </div> </template> <script> const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); const root = this.attachShadow({mode: 'closed'}); const temp = document.importNode(template.content, true); root.appendChild(temp); } }); </script>
注意:代碼示例是在 Web 組件的版本 1 規範中編寫的。
然而,完全封裝每個 Web 組件將不可避免地導致大量重複的 CSS,尤其是在設置原生元素的排版和样式時。 如果開發人員想在其 Web 組件中使用段落、錨標記或輸入字段,則其樣式應與網站的其餘部分一樣。
如果我們完全封裝了 Web 組件所需的所有樣式,那麼用於樣式化段落、錨標記、輸入字段等的 CSS 將在所有使用它們的 Web 組件中復制。 這不僅會增加維護成本,還會導致用戶下載量大得多。
Web 組件不應封裝所有樣式,而應僅封裝其獨特的樣式,然後依賴一組共享樣式來處理其他所有樣式的樣式。 這些共享樣式本質上將成為一種 Normalize.css,Web 組件可以使用它來確保根據樣式指南對本機元素進行樣式設置。
在前面的示例中,登錄表單 Web 組件將僅聲明其兩個唯一類的樣式: .container
和.footnote
。 其餘樣式將屬於共享樣式表,並對段落、錨標記、輸入字段等進行樣式設置。
簡而言之,樣式指南不應該嘗試設置 Web 組件的樣式,而是應該提供一組共享樣式,Web 組件可以使用這些樣式來實現一致的外觀。
過去如何使用外部樣式表對 Shadow DOM 進行樣式化
Web 組件的初始規範(稱為版本 0)允許任何外部樣式表通過使用::shadow
或/deep/
CSS 選擇器來穿透 shadow DOM。 ::shadow
和/deep/
的使用使您能夠有一個樣式指南穿透 shadow DOM 並設置共享樣式,無論 Web 組件是否希望您這樣做。
/* Style all p tags inside a web components shadow DOM */ login-form::shadow p { color: red; }
隨著最新版本的 Web 組件規範(稱為版本 1)的出現,作者已經刪除了外部樣式表穿透影子 DOM 的能力,並且他們沒有提供替代方案。 取而代之的是,哲學已經從使用龍來設計 Web 組件樣式轉變為使用橋接器。 換句話說,Web 組件作者應該負責允許哪些外部樣式規則對其組件進行樣式設置,而不是被迫允許它們。
不幸的是,這種哲學還沒有真正趕上網絡,這讓我們有點不知所措。 幸運的是,今天有一些可用的解決方案,以及在不久的將來會出現的一些解決方案,將允許共享樣式表來設置 Web 組件的樣式。
你今天可以做什麼
您現在可以使用三種技術來允許 Web 組件共享樣式: @import
、自定義元素和 Web 組件庫。
使用@import
今天將樣式表引入 Web 組件的唯一本地方法是使用@import
。 雖然這可行,但它是一種反模式。 然而,對於 Web 組件,這是一個更大的性能問題。
<template> <style> @import "styleguide.css" </style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>
通常,@ @import
是一種反模式,因為它以串行方式而不是並行方式下載所有樣式表,尤其是在它們嵌套的情況下。 在我們的情況下,連續下載單個樣式表是無濟於事的,所以理論上應該沒問題。 但是當我在 Chrome 中對此進行測試時,結果顯示使用@import
導致頁面的渲染速度比將樣式直接嵌入 Web 組件時慢了半秒。
注意:由於 HTML 導入的 polyfill 與原生 HTML 導入的工作方式不同,WebPagetest.org 只能用於在原生支持 HTML 導入的瀏覽器(即 Chrome)中提供可靠的結果。
最後,@ @import
仍然是一種反模式,並且可能是 Web 組件中的性能問題。 所以,這不是一個很好的解決方案。
不要使用 Shadow DOM
因為嘗試為 Web 組件提供共享樣式的問題源於使用影子 DOM,所以完全避免該問題的一種方法是不使用影子 DOM。
通過不使用 shadow DOM,您將創建自定義元素而不是 Web 組件(見下文),唯一的區別是缺少 shadow DOM 和範圍。 您的元素將受頁面樣式的影響,但我們今天已經必須處理它,所以我們不知道如何處理。 webcomponentjs polyfill 完全支持自定義元素,它具有很好的瀏覽器支持。
自定義元素的最大好處是您今天可以使用它們創建模式庫,而不必等到共享樣式的問題得到解決。 並且因為 web 組件和自定義元素之間的唯一區別是 shadow DOM,所以一旦共享樣式的解決方案可用,您總是可以在自定義元素中啟用 shadow DOM。
如果您決定創建自定義元素,請注意自定義元素和 Web 組件之間的一些差異。
首先,因為自定義元素的樣式受頁面樣式的影響,反之亦然,您需要確保您的選擇器不會引起任何衝突。 如果您的頁面已經使用樣式指南,則將自定義元素的樣式保留在樣式指南中,並讓元素輸出預期的 DOM 和類結構。
通過將樣式保留在樣式指南中,您將為您的開發人員創建一條平滑的遷移路徑,因為他們可以像以前一樣繼續使用樣式指南,但隨後在能夠使用新的自定義元素時慢慢遷移到使用。 一旦每個人都在使用自定義元素,您可以將樣式移動到元素內部,以便將它們保持在一起,並允許以後更輕鬆地重構 Web 組件。
其次,確保將任何 JavaScript 代碼封裝在立即調用的函數表達式 (IFFE) 中,這樣您就不會將任何變量洩漏到全局範圍內。 除了不提供 CSS 範圍之外,自定義元素不提供 JavaScript 範圍。
第三,您需要使用自定義元素的connectedCallback
函數將模板 DOM 添加到元素。 根據 Web 組件規範,自定義元素不應在構造函數期間添加子元素,因此您需要將 DOM 添加到connectedCallback
函數中。
最後, <slot>
元素不能在 shadow DOM 之外工作。 這意味著您必須使用不同的方法為開發人員提供一種將他們的內容插入到您的自定義元素中的方法。 通常,這需要自己操作 DOM 以將其內容插入到您想要的位置。
然而,由於陰影 DOM 和帶有自定義元素的光照 DOM 之間沒有分離,因此您還必須非常小心,不要為插入的 DOM 設置樣式,因為您的元素是層疊樣式。
<!-- login-form.html --> <template> <style> login-form .container { max-width: 300px; padding: 50px; border: 1px solid grey; } login-form .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> (function() { const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); } // Without the shadow DOM, we have to manipulate the custom element // after it has been inserted in the DOM. connectedCallback() { const temp = document.importNode(template.content, true); this.appendChild(temp); } }); })(); </script>
<!-- index.html --> <link rel="stylesheet" href="styleguide.css"> <link rel="import" href="login-form.html"> <login-form></login-form>
在性能方面,自定義元素幾乎與未使用的 Web 組件一樣快(即在head
鏈接共享樣式表並僅使用本機 DOM 元素)。 在您今天可以使用的所有技術中,這是迄今為止最快的。
另外:自定義元素仍然是所有意圖和目的的 Web 組件。 術語“Web 組件”用於描述四種獨立的技術:自定義元素、模板標籤、HTML 導入和影子 DOM。
不幸的是,該術語已被用來描述使用這四種技術的任意組合的任何事物。 這導致人們對人們所說的“Web 組件”的含義產生了很多混淆。 正如 Rob Dodson 發現的那樣,我發現在討論帶有和不帶有 shadow DOM 的自定義元素時使用不同的術語很有幫助。
與我交談過的大多數開發人員都傾向於將術語“Web 組件”與使用影子 DOM 的自定義元素聯繫起來。 因此,出於本文的目的,我在 Web 組件和自定義元素之間進行了人為的區分。
使用 Web 組件庫
您今天可以使用的另一個解決方案是 Web 組件庫,例如 Polymer、SkateJS 或 X-Tag。 這些庫有助於填補當今支持的漏洞,還可以簡化創建 Web 組件所需的代碼。 它們通常還提供使編寫 Web 組件更容易的附加功能。
例如,Polymer 讓您只需幾行 JavaScript 就可以創建一個簡單的 Web 組件。 另一個好處是 Polymer 提供了使用影子 DOM 和共享樣式表的解決方案。 這意味著您現在可以創建共享樣式的 Web 組件。
為此,請創建他們所謂的樣式模塊,其中包含所有共享樣式。 它可以是內聯共享樣式的<style>
標記,也可以是指向共享樣式表的<link rel=“import”>
標記。 在任何一種情況下,使用<style include>
標記在您的 Web 組件中包含樣式,然後 Polymer 將解析樣式並將它們作為內聯<style>
標記添加到您的 Web 組件中。
<!-- shared-styles.html --> <dom-module> <!-- Link to a shared style sheet --> <!-- <link rel="import" href="styleguide.css"> --> <!-- Inline the shared styles --> <template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } /* Rest of shared CSS */ </style> </template> </dom-module>
<!-- login-form.html --> <link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../shared-styles/shared-styles.html"> <dom-module> <template> <!-- Include the shared styles --> <style include="shared-styles"></style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> Polymer({ is: 'login-form' }); </script> </dom-module>
使用庫的唯一缺點是它會延遲 Web 組件的渲染時間。 這應該不足為奇,因為下載庫的代碼並處理它需要時間。 在庫完成處理之前,頁面上的任何 Web 組件都無法開始呈現。
在 Polymer 的案例中,與原生 Web 組件相比,它可以將頁面渲染時間最多延遲半秒。 嵌入樣式的樣式模塊比鏈接樣式的樣式模塊稍慢,並且將樣式直接嵌入到 Web 組件中與使用樣式模塊一樣快。
同樣,Polymer 並沒有做任何特別的事情來使渲染時間變慢。 下載 Polymer 庫並處理其所有出色的功能,以及創建所有模板綁定,都需要時間。 這只是使用 Web 組件庫必須做出的權衡。
性能測試結果表明,使用 Polymer,Web 組件的渲染速度將比原生 Web 組件慢半秒。
未來的承諾
如果當前的解決方案都不適合您,請不要絕望。 如果一切順利,在幾個月到幾年內,我們將能夠使用幾種不同的方法來使用共享樣式。
自定義屬性
自定義屬性(或稱為 CSS 變量)是在 CSS 中設置和使用變量的一種方式。 這個概念對於 CSS 預處理器來說並不新鮮,但作為原生 CSS 功能,自定義屬性實際上比預處理器變量更強大。
要聲明自定義屬性,請使用自定義屬性表示法–my-variable: value
,並使用property: var(–my-variable)
訪問該變量。 自定義屬性像任何其他 CSS 規則一樣級聯,因此它的值繼承自其父級並且可以被覆蓋。 對自定義屬性的唯一警告是,它們必須在選擇器中聲明,並且不能單獨聲明,這與預處理器變量不同。
<style> /* Declare the custom property */ html { --main-bg-color: red; } /* Use the custom property */ input { background: var(--main-bg-color); } </style>
使自定義屬性如此強大的一件事是它們能夠穿透影子 DOM。 這與/deep/
和::shadow
選擇器不同,因為它們不會強行進入 Web 組件。 相反,Web 組件的作者必須在其 CSS 中使用自定義屬性才能應用它。 這意味著 Web 組件作者可以創建自定義屬性 API,Web 組件的消費者可以使用該 API 來應用他們自己的樣式。
<template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>
瀏覽器對自定義屬性的支持出奇的好。 它不是您今天可以使用的解決方案的唯一原因是沒有自定義元素版本 1 就沒有可用的 polyfill。webcomponentjs polyfill 背後的團隊目前正在努力添加它,但它尚未發布並處於構建狀態,這意味著如果您將資產散列用於生產,則無法使用它。 據我了解,它將於明年初的某個時候發布。
即便如此,自定義屬性也不是在 Web 組件之間共享樣式的好方法。 因為它們只能用於聲明單個屬性值,所以 Web 組件仍然需要嵌入樣式指南的所有樣式,儘管它們的值被替換為變量。
自定義屬性更適合主題選項,而不是共享樣式。 因此,自定義屬性不是我們問題的可行解決方案。
/* 使用自定義屬性 */ input { background: var(–main-bg-color); } </style>
使自定義屬性如此強大的一件事是它們能夠穿透影子 DOM。 這與/deep/
和::shadow
選擇器不同,因為它們不會強行進入 Web 組件。 相反,Web 組件的作者必須在其 CSS 中使用自定義屬性才能應用它。 這意味著 Web 組件作者可以創建自定義屬性 API,Web 組件的消費者可以使用該 API 來應用他們自己的樣式。
<template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>
瀏覽器對自定義屬性的支持出奇的好。 它不是您今天可以使用的解決方案的唯一原因是沒有自定義元素版本 1 就沒有可用的 polyfill。webcomponentjs polyfill 背後的團隊目前正在努力添加它,但它尚未發布並處於構建狀態,這意味著如果您將資產散列用於生產,則無法使用它。 據我了解,它將於明年初的某個時候發布。
即便如此,自定義屬性也不是在 Web 組件之間共享樣式的好方法。 因為它們只能用於聲明單個屬性值,所以 Web 組件仍然需要嵌入樣式指南的所有樣式,儘管它們的值被替換為變量。
自定義屬性更適合主題選項,而不是共享樣式。 因此,自定義屬性不是我們問題的可行解決方案。
@apply 規則
除了自定義屬性之外,CSS 還獲得了@apply
規則。 應用規則本質上是 CSS 世界的 mixin。 它們以與自定義屬性類似的方式聲明,但可用於聲明屬性組而不僅僅是屬性值。 就像自定義屬性一樣,它們的值可以被繼承和覆蓋,並且它們必須在選擇器中聲明才能工作。
<style> /* Declare rule */ html { --typography: { font: 16px Arial, sans-serif; color: #333333; } } /* Use rule */ input { @apply --typography; } </style>
瀏覽器對@apply
規則的支持基本上是不存在的。 Chrome 目前在功能標誌後面支持它(我找不到),但僅此而已。 與沒有用於自定義屬性的 polyfill 相同的原因,也沒有可用的 polyfill。 webcomponentjs polyfill 團隊也在努力添加@apply
規則以及自定義屬性,因此一旦新版本發布,兩者都將可用。
與自定義屬性不同, @apply
規則是共享樣式的更好解決方案。 因為它們可以設置一組屬性聲明,所以您可以使用它們為所有原生元素設置默認樣式,然後在 Web 組件中使用它們。 為此,您必須為每個原生元素創建一個@apply
規則。
但是,要使用樣式,您必須手動將它們應用到每個原生元素,這仍然會在每個 Web 組件中重複樣式聲明。 雖然這比嵌入所有樣式要好,但也不是很方便,因為它會成為每個 Web 組件頂部的樣板,您必須記住添加這些樣板才能使樣式正常工作。
/* styleguide.css */ html { --typography: { color: #333333; font: 16px Arial, sans-serif; } --paragraph: { margin: 0; } --label { display: block; margin-bottom: 5px; } --input-text { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } --input-submit { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } /* And so on for every native element */ }
<!-- login-form.html --> <template> <style> :host { @apply --typography; } p { @apply --paragraph; } label { @apply --label; } input-text { @apply --input-text; } .input-submit { @apply --input-submit; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template>
由於需要大量樣板文件,我不認為@apply
規則會成為在 Web 組件之間共享樣式的好解決方案。 不過,它們是主題化的絕佳解決方案。
在 Shadow DOM 中
根據 web 組件規範,瀏覽器會忽略 shadow DOM 中的任何<link rel=“stylesheet”>
標籤,就像在文檔片段中一樣對待它們。 這使我們無法在我們的 Web 組件中鏈接任何共享樣式,這是不幸的——也就是說,直到幾個月前,當 Web 組件工作組提議<link rel=“stylesheet”>
標籤應該在影子 DOM。 經過一周的討論,他們都同意應該這樣做,幾天后他們將其添加到 HTML 規範中。
<template> <link rel="stylesheet" href="styleguide.css"> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>
如果這對於工作組就規範達成一致來說聽起來有點太快了,那是因為它不是一個新提案。 讓link
標籤在影子 DOM 中工作實際上是至少三年前提出的,但它被積壓,直到他們能夠確保它不會成為性能問題。
如果提案的接受還不夠令人興奮,Chrome 55(目前是 Chrome Canary)添加了使link
標籤在影子 DOM 中工作的初始功能。 甚至似乎這個功能已經登陸當前版本的 Chrome。 甚至 Safari 也已在 Safari 18 中實現了該功能。
能夠在共享樣式中鏈接是迄今為止在 Web 組件之間共享樣式的最方便的方法。 您所要做的就是創建link
標籤,所有原生元素都將被相應地設置樣式,而無需任何額外的工作。
當然,瀏覽器製造商實現該功能的方式將決定該解決方案是否可行。 為使其正常工作,需要對link
標籤進行重複數據刪除,以便多個 Web 組件請求同一個 CSS 文件時只會產生一個 HTTP 請求。 CSS 也只需要解析一次,這樣 Web 組件的每個實例就不必重新計算共享樣式,而是重用計算的樣式。
Chrome 已經做到了這兩點。 因此,如果所有其他瀏覽器製造商都以相同的方式實現它,那麼在 shadow DOM 中工作的link
標籤肯定會解決如何在 Web 組件之間共享樣式的問題。
可構造樣式表
你可能很難相信,因為我們還沒有得到它,但是在影子 DOM 中工作的link
標籤並不是一個長期的解決方案。 相反,它只是讓我們得到真正解決方案的短期解決方案:可構造樣式表。
可構造樣式表是允許通過構造函數在 JavaScript 中創建StyleSheet
對象的提議。 然後可以通過 API 將構建的樣式表添加到影子 DOM,這將允許影子 DOM 使用一組共享樣式。
不幸的是,這就是我能從提案中收集到的全部信息。 我試圖通過詢問 Web 組件工作組來了解有關可構造樣式表的更多信息,但他們將我重定向到 W3C 的 CSS 工作組的郵件列表,我再次詢問,但沒有人回應。 我什至無法弄清楚該提案的進展情況,因為它已經兩年多沒有更新了。
儘管如此,Web Components Working Group 還是使用它作為在 Web 組件之間共享樣式的解決方案。 希望提案將得到更新,或者 Web 組件工作組將發布有關它及其採用的更多信息。 在那之前,“長期”解決方案似乎不會在可預見的未來發生。
得到教訓
經過幾個月的研究和測試,我對未來充滿希望。 令人欣慰的是,在多年沒有在 Web 組件之間共享樣式的解決方案之後,終於有了答案。 這些答案可能還要再過幾年才能確定,但至少它們在那裡。
如果您現在想使用共享樣式指南來設置 Web 組件的樣式,您可以不使用 shadow DOM 而是創建自定義元素,或者您可以使用 polyfill 支持共享樣式的 Web 組件庫。 兩種解決方案各有利弊,因此請選擇最適合您的項目的解決方案。
如果您決定在深入研究 Web 組件之前稍等片刻,那麼幾年後我們應該有一些很好的解決方案來在它們之間共享樣式。 因此,請繼續檢查它的進展情況。
要記住的事情
如果您今天決定使用自定義元素或 Web 組件,請記住幾件事。
最重要的是,Web 組件規範仍在積極開發中,這意味著事情可以並且將會改變。 Web 組件在很大程度上仍然是最前沿的,因此請準備好在使用它進行開發時保持警惕。
如果您決定使用 shadow DOM,請知道它在 polyfill 瀏覽器中非常緩慢且性能不佳。 正是出於這個原因,Polymer 的開發人員創建了他們的 shady DOM 實現並將其設為默認值。
Chrome、Opera 和最近的 Safari 是唯一支持 shadow DOM 版本 0 的瀏覽器。Firefox 仍在開發中,儘管它從版本 29 開始在實驗中支持它。微軟仍在考慮將它用於 Edge 並將其作為其路線圖上的高度優先事項。
但是,shadow DOM 版本 0 是舊規範。 Shadow DOM 版本 1 是新版本,只有 Chrome、Safari 和 Opera 完全支持它。 更不用說自定義元素版本 0 經歷了相同的升級,只有 Chrome 完全支持自定義元素版本 1,而 Safari 技術預覽版從版本 17 開始支持它。自定義元素版本 1 在 Web 組件的編寫方式上有一些重大變化,所以一定要完全理解這意味著什麼。
最後,webcomponentjs polyfill 僅支持 shadow DOM 和自定義元素的版本 0 實現。 polyfill 的版本 1 分支將支持版本 1,但尚未發布。