共有スタイルシートを使用したWebコンポーネントのスタイリング

公開: 2022-03-10
クイックサマリー↬Webコンポーネントは、Webの驚くべき新機能であり、開発者が独自のカスタムHTML要素を定義できるようにします。 Webコンポーネントをスタイルガイドと組み合わせると、コンポーネントAPIを作成できます。これにより、開発者はコードスニペットのコピーと貼り付けを停止し、代わりにDOM要素を使用できます。 Shadow DOMを使用することで、Webコンポーネントをカプセル化でき、ページ上の他のスタイルシートとの特異性の戦争について心配する必要がなくなります。 ただし、現在、Webコンポーネントとスタイルガイドは互いに対立しているようです。

Webコンポーネントは、Webの驚くべき新機能であり、開発者が独自のカスタムHTML要素を定義できるようにします。 Webコンポーネントをスタイルガイドと組み合わせると、コンポーネントAPIを作成できます。これにより、開発者はコードスニペットのコピーと貼り付けを停止し、代わりにDOM要素を使用できます。 Shadow DOMを使用することで、Webコンポーネントをカプセル化でき、ページ上の他のスタイルシートとの特異性の戦争について心配する必要がなくなります。

ただし、現在、Webコンポーネントとスタイルガイドは互いに対立しているようです。 一方では、スタイルガイドは、ページにグローバルに適用され、Webサイト全体の一貫性を確保する一連のルールとスタイルを提供します。 一方、Shadow DOMを使用するWebコンポーネントは、グローバルスタイルがカプセル化に浸透するのを防ぎ、スタイルガイドがそれらに影響を与えるのを防ぎます。

SmashingMagの詳細

  • コンポーネントベースのシステムでのベストプラクティスの実施
  • よりスマートなスタイルシートのためにLESSCSSプリプロセッサを使用する方法
  • AdobeEdgeリフローの詳細

では、シャドウDOMを使用するWebコンポーネントに対しても、グローバルスタイルガイドが一貫性​​とスタイルを提供し続けることで、この2つをどのように共存させることができるでしょうか。 ありがたいことに、現在機能しているソリューションがあり、今後さらに多くのソリューションがあり、グローバルスタイルガイドがWebコンポーネントにスタイルを提供できるようになります。 (この記事の残りの部分では、「Webコンポーネント」という用語を使用して、Shadow DOMを使用するカスタム要素を指します。)

ジャンプした後もっと! 以下を読み続けてください↓

Webコンポーネントのグローバルスタイルガイドスタイルはどうあるべきですか?

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コンポーネント

ただし、すべてのWebコンポーネントを完全にカプセル化すると、特にネイティブ要素のタイポグラフィとスタイル設定を設定する場合に、必然的に多くの重複したCSSが発生します。 開発者がWebコンポーネントで段落、アンカータグ、または入力フィールドを使用する場合は、Webサイトの他の部分と同じようにスタイルを設定する必要があります。

Webコンポーネントに必要なすべてのスタイルを完全にカプセル化すると、段落、アンカータグ、入力フィールドなどのスタイルを設定するためのCSSが、それらを使用するすべてのWebコンポーネントに複製されます。 これにより、メンテナンスコストが増加するだけでなく、ユーザーのダウンロードサイズが大幅に大きくなります。

Webコンポーネントは、すべてのスタイルをカプセル化するのではなく、固有のスタイルのみをカプセル化し、共有スタイルのセットに依存して他のすべてのスタイルを処理する必要があります。 これらの共有スタイルは、本質的に一種のNormalize.cssになり、Webコンポーネントは、ネイティブ要素がスタイルガイドに従ってスタイル設定されていることを確認するために使用できます。

前の例では、ログインフォームのWebコンポーネントは、 .container.footnoteの2つの固有のクラスに対してのみスタイルを宣言します。 残りのスタイルは共有スタイルシートに属し、段落、アンカータグ、入力フィールドなどのスタイルを設定します。

つまり、スタイルガイドはWebコンポーネントのスタイルを設定するのではなく、Webコンポーネントが一貫した外観を実現するために使用できる共有スタイルのセットを提供する必要があります。

以前は外部スタイルシートを使用してShadowDOMをスタイリングする方法

Webコンポーネント(バージョン0として知られている)の初期仕様では、 ::shadowまたは/deep/ CSSセレクターを使用して、外部スタイルシートがシャドウDOMに浸透することを許可していました。 ::shadow/deep/を使用すると、Webコンポーネントで必要かどうかに関係なく、スタイルガイドがShadow DOMに浸透し、共有スタイルを設定できるようになりました。

 /* Style all p tags inside a web components shadow DOM */ login-form::shadow p { color: red; }

Webコンポーネント仕様の最新バージョン(バージョン1と呼ばれる)の出現により、作成者は外部スタイルシートがShadow DOMに浸透する機能を削除し、代替手段を提供していません。 代わりに、哲学はドラゴンを使用してWebコンポーネントをスタイリングすることから、代わりにブリッジを使用することへと変化しました。 言い換えると、Webコンポーネントの作成者は、強制的に許可するのではなく、コンポーネントのスタイルを設定できる外部スタイルルールを管理する必要があります。

残念ながら、その哲学はまだWebに追いついていないため、少し厄介なことになります。 幸いなことに、現在利用可能ないくつかのソリューションと、それほど遠くない将来に登場するいくつかのソリューションにより、共有スタイルシートでWebコンポーネントのスタイルを設定できるようになります。

今日できること

Webコンポーネントがスタイルを共有できるようにするために、今日使用できる3つの手法があります。 @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コンポーネントに直接埋め込む場合よりも、ページのレンダリングが最大0.5秒遅くなることがわかりました。

注: HTMLインポートのポリフィルの動作はネイティブHTMLインポートとは異なるため、WebPagetest.orgは、HTMLインポートをネイティブにサポートするブラウザー(Chromeなど)で信頼できる結果を提供するためにのみ使用できます。

ネイティブWebコンポーネントのパフォーマンスの棒グラフ。
3つのパフォーマンステストの結果は、 @importを使用すると、スタイルをWebコンポーネントに直接埋め込む場合よりも、ブラウザーのレンダリングが最大0.5秒遅くなることを示しています。

結局、 @importは依然としてアンチパターンであり、Webコンポーネントのパフォーマンスの問題になる可能性があります。 したがって、これは優れたソリューションではありません。

ShadowDOMを使用しないでください

Webコンポーネントに共有スタイルを提供しようとする際の問題は、Shadow DOMを使用することに起因するため、問題を完全に回避する1つの方法は、ShadowDOMを使用しないことです。

Shadow DOMを使用しないことで、Webコンポーネントの代わりにカスタム要素を作成することになります(以下の脇を参照)。唯一の違いは、ShadowDOMとスコープがないことです。 あなたの要素はページのスタイルに左右されますが、今日はすでにそれを処理する必要があるので、処理方法がわからないことは何もありません。 カスタム要素は、優れたブラウザサポートを備えたwebcomponentjspolyfillによって完全にサポートされています。

カスタム要素の最大の利点は、今日それらを使用してパターンライブラリを作成できることと、共有スタイルの問題が解決されるまで待つ必要がないことです。 また、Webコンポーネントとカスタム要素の唯一の違いはシャドウDOMであるため、共有スタイルのソリューションが利用可能になったら、カスタム要素でシャドウDOMをいつでも有効にできます。

カスタム要素を作成する場合は、カスタム要素とWebコンポーネントのいくつかの違いに注意してください。

まず、カスタム要素のスタイルはページスタイルの対象であり、その逆もあるため、セレクターによって競合が発生しないようにする必要があります。 ページですでにスタイルガイドを使用している場合は、カスタム要素のスタイルをスタイルガイドに残し、要素に期待されるDOMとクラス構造を出力させます。

スタイルガイドにスタイルを残すことで、開発者は以前と同じようにスタイルガイドを引き続き使用できるため、スムーズな移行パスを作成できますが、可能な場合は新しいカスタム要素の使用にゆっくりと移行します。 全員がカスタム要素を使用したら、スタイルを移動して要素内に配置し、スタイルをまとめて、後でWebコンポーネントに簡単にリファクタリングできるようにすることができます。

次に、JavaScriptコードを即時呼び出し関数式(IFFE)内にカプセル化して、変数をグローバルスコープにブリードしないようにしてください。 CSSスコープを提供しないことに加えて、カスタム要素はJavaScriptスコープを提供しません。

3番目に、カスタム要素のconnectedCallback関数を使用して、テンプレートDOMを要素に追加する必要があります。 Webコンポーネントの仕様によると、カスタム要素はコンストラクター関数の実行中に子を追加しないようにする必要があるため、ConnectedCallback関数へのDOMの追加を延期connectedCallback必要があります。

最後に、 <slot>要素はシャドウ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要素のみを使用します)。 今日使用できるすべてのテクニックの中で、これははるかに高速です。

カスタム要素のパフォーマンスの棒グラフ。
2つのパフォーマンステストの結果は、カスタム要素がWebコンポーネントをまったく使用しない場合とほぼ同じくらい高速であることを示しています。

余談ですが、カスタム要素は、すべての目的と目的のためのWebコンポーネントです。 「Webコンポーネント」という用語は、カスタム要素、テンプレートタグ、HTMLインポート、ShadowDOMの4つの別個のテクノロジーを表すために使用されます。

残念ながら、この用語は、4つのテクノロジーの任意の組み合わせを使用するものを表すために使用されています。 これは、人々が「Webコンポーネント」と言うときの意味について多くの混乱を招きました。 Rob Dodsonが発見したように、シャドウDOMがある場合とない場合のカスタム要素について話すときに、さまざまな用語を使用すると便利であることがわかりました。

私が話した開発者のほとんどは、「Webコンポーネント」という用語をシャドウDOMを使用するカスタム要素に関連付ける傾向があります。 したがって、この記事の目的のために、Webコンポーネントとカスタム要素を人為的に区別しました。

Webコンポーネントライブラリの使用

現在使用できるもう1つのソリューションは、Polymer、SkateJS、X-TagなどのWebコンポーネントライブラリです。 これらのライブラリは、今日のサポートの穴を埋めるのに役立ち、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コンポーネントと比較して、ページのレンダリング時間を最大0.5秒遅らせることができます。 スタイルを埋め込むスタイルモジュールは、スタイルをリンクするスタイルモジュールよりも少し遅く、スタイルをWebコンポーネントに直接埋め込むのは、スタイルモジュールを使用するのと同じくらい高速です。

繰り返しになりますが、Polymerはレンダリング時間を遅くするために特に何もしません。 Polymerライブラリをダウンロードし、そのすばらしい機能をすべて処理し、さらにすべてのテンプレートバインディングを作成するには、時間がかかります。 これは、Webコンポーネントライブラリを使用するために必要なトレードオフにすぎません。

ポリマーウェブコンポーネントのパフォーマンスの棒グラフ。

パフォーマンステストの結果は、Polymerを使用すると、WebコンポーネントのレンダリングがネイティブWebコンポーネントよりも最大0.5秒遅くなることを示しています。

未来の約束

現在の解決策のどれもあなたのために働かない場合でも、絶望しないでください。 すべてがうまくいけば、数か月から数年以内に、いくつかの異なるアプローチを使用して共有スタイルを使用できるようになります。

カスタムプロパティ

カスタムプロパティ(または、呼び出された場合は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>

カスタムプロパティを非常に強力にする1つの点は、シャドウDOMを貫通する機能です。 これは、 /deep/および::shadowセレクターと同じ考え方ではありません。これらは、Webコンポーネントに強制的に組み込まれないためです。 代わりに、Webコンポーネントの作成者は、CSSを適用するためにCSSでカスタムプロパティを使用する必要があります。 これは、Webコンポーネントの作成者が、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なしでは機能するポリフィルがないことです。webcomponentjsポリフィルの背後にあるチームは現在それを追加するために取り組んでいますが、まだリリースされておらず、ビルドされた状態です。つまり、本番用にアセットをハッシュすると、それを使用できなくなります。 私の理解では、来年初めにリリースされる予定です。

それでも、カスタムプロパティは、Webコンポーネント間でスタイルを共有するための適切な方法ではありません。 これらは単一のプロパティ値を宣言するためにのみ使用できるため、Webコンポーネントは、値が変数に置き換えられていても、スタイルガイドのすべてのスタイルを埋め込む必要があります。

カスタムプロパティは、共有スタイルよりもテーマオプションに適しています。 このため、カスタムプロパティは私たちの問題に対する実行可能な解決策ではありません。

/ *カスタムプロパティを使用します* / input {background:var(–main-bg-color); } </ style>

カスタムプロパティを非常に強力にする1つの点は、シャドウDOMを貫通する機能です。 これは、 /deep/および::shadowセレクターと同じ考え方ではありません。これらは、Webコンポーネントに強制的に組み込まれないためです。 代わりに、Webコンポーネントの作成者は、CSSを適用するためにCSSでカスタムプロパティを使用する必要があります。 これは、Webコンポーネントの作成者が、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なしでは機能するポリフィルがないことです。webcomponentjsポリフィルの背後にあるチームは現在それを追加するために取り組んでいますが、まだリリースされておらず、ビルドされた状態です。つまり、本番用にアセットをハッシュすると、それを使用できなくなります。 私の理解では、来年初めにリリースされる予定です。

それでも、カスタムプロパティは、Webコンポーネント間でスタイルを共有するための適切な方法ではありません。 これらは単一のプロパティ値を宣言するためにのみ使用できるため、Webコンポーネントは、値が変数に置き換えられていても、スタイルガイドのすべてのスタイルを埋め込む必要があります。

カスタムプロパティは、共有スタイルよりもテーマオプションに適しています。 このため、カスタムプロパティは私たちの問題に対する実行可能な解決策ではありません。

@applyルール

カスタムプロパティに加えて、CSSは@applyルールも取得しています。 適用ルールは、基本的にCSSの世界のミックスインです。 これらはカスタムプロパティと同様の方法で宣言されますが、プロパティ値だけでなく、プロパティのグループを宣言するために使用できます。 カスタムプロパティと同様に、それらの値は継承およびオーバーライドでき、機能するにはセレクター内で宣言する必要があります。

 <style> /* Declare rule */ html { --typography: { font: 16px Arial, sans-serif; color: #333333; } } /* Use rule */ input { @apply --typography; } </style>

@applyルールのブラウザサポートは基本的に存在しません。 Chromeは現在、機能フラグ(私は見つけることができませんでした)の背後でそれをサポートしていますが、それはそれについてです。 カスタムプロパティのポリフィルがないのと同じ理由で、機能するポリフィルもありません。 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コンポーネント間でスタイルを共有するための優れたソリューションになるとは思いません。 ただし、これらはテーマ設定に最適なソリューションです。

ShadowDOMで

Webコンポーネントの仕様によると、ブラウザーはシャドウDOM内の<link rel=“stylesheet”>タグを無視し、ドキュメントフラグメント内の場合と同じように扱います。 これにより、Webコンポーネント内の共有スタイルでリンクできなくなりました。これは残念なことでした。つまり、数か月前、Webコンポーネントワーキンググループが<link rel=“stylesheet”>タグが機能するように提案したときまでです。シャドウDOM。 わずか1週間の議論の後、全員が同意し、数日後に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タグをShadowDOMで機能させることは、実際には少なくとも3年前に提案されましたが、パフォーマンスに問題がないことを確認できるまで、バックログされていました。

提案の受け入れが十分に刺激的でない場合、Chrome 55(現在はChrome Canary)は、 linkタグをシャドウDOMで機能させる最初の機能を追加しました。 この機能は現在のバージョンのChromeにも搭載されているようです。 SafariでさえSafari18にこの機能を実装しています。

共有スタイルでリンクできることは、Webコンポーネント間でスタイルを共有するための最も便利な方法です。 linkタグを作成するだけで、追加の作業を必要とせずに、すべてのネイティブ要素がそれに応じてスタイル設定されます。

もちろん、ブラウザメーカーがこの機能を実装する方法によって、このソリューションが実行可能かどうかが決まります。 これを正しく機能させるには、 linkタグを重複排除する必要があります。これにより、同じCSSファイルを要求する複数のWebコンポーネントによって、HTTP要求が1つだけ発生します。 また、CSSを1回だけ解析する必要があるため、Webコンポーネントの各インスタンスは共有スタイルを再計算する必要はなく、代わりに計算されたスタイルを再利用します。

Chromeはすでにこれらの両方を実行しています。 したがって、他のすべてのブラウザーメーカーが同じ方法で実装している場合、Shadow DOMで機能するlinkタグは、Webコンポーネント間でスタイルを共有する方法の問題を確実に解決します。

構築可能なスタイルシート

まだ入手していないため、信じがたいかもしれませんが、ShadowDOMで機能するlinkタグは長期的な解決策ではありません。 代わりに、それは私たちを本当の解決策、つまり構築可能なスタイルシートに導くための短期的な解決策にすぎません。

構築可能なスタイルシートは、コンストラクター関数を介してJavaScriptでStyleSheetオブジェクトを作成できるようにするための提案です。 構築されたスタイルシートは、APIを介してShadow DOMに追加できます。これにより、ShadowDOMで一連の共有スタイルを使用できるようになります。

残念ながら、これが私が提案から集めることができたすべてです。 Webコンポーネントワーキンググループに質問して、構築可能なスタイルシートについて詳しく調べようとしましたが、W3CのCSSワーキンググループのメーリングリストにリダイレクトされ、そこでもう一度質問しましたが、誰も応答しませんでした。 2年以上更新されていないため、提案の進捗状況すらわかりませんでした。

それでも、Webコンポーネントワーキンググループは、Webコンポーネント間でスタイルを共有するためソリューションとしてそれを使用します。 うまくいけば、提案が更新されるか、Webコンポーネントワーキンググループが提案とその採用に関する詳細情報を公開するでしょう。 それまでは、「長期的な」解決策は、予見可能な将来には起こらないように思われます。

学んだ教訓

何ヶ月にもわたる研究とテストを経て、私は将来に非常に期待しています。 Webコンポーネント間でスタイルを共有するためのソリューションが何年もなかった後、最終的に答えがあることを知って安心しています。 それらの答えはあと数年は確立されないかもしれませんが、少なくともそれらはそこにあります。

今日、共有スタイルガイドを使用してWebコンポーネントのスタイルを設定する場合は、Shadow DOMを使用せずにカスタム要素を作成するか、スタイルの共有をポリフィルでサポートするWebコンポーネントライブラリを使用できます。 どちらのソリューションにも長所と短所があるため、プロジェクトに最適な方を使用してください。

Webコンポーネントを詳しく調べる前にしばらく待つことにした場合は、数年以内に、それらの間でスタイルを共有するための優れたソリューションがいくつかあるはずです。 だから、それがどのように進行しているかをチェックし続けてください。

心に留めておくべきこと

今日、カスタム要素またはWebコンポーネントを使用する場合は、いくつかの点に注意してください。

最も重要なことは、Webコンポーネントの仕様がまだ活発に開発されていることです。つまり、状況は変わる可能性があり、変わるでしょう。 Webコンポーネントはまだ非常に最先端であるため、Webコンポーネントを使用して開発するときは、常に注意を払う準備をしてください。

Shadow DOMを使用する場合は、ポリフィルされたブラウザーでは非常に遅く、パフォーマンスが低いことを知っておいてください。 このため、Polymerの開発者は日陰のDOM実装を作成し、それをデフォルトにしました。

Chrome、Opera、そして最近ではSafariがShadow DOMバージョン0をサポートする唯一のブラウザーです。Firefoxはバージョン29以降の実験の背後でサポートされていますが、まだ開発中です。MicrosoftはまだEdgeでそれを検討しており、ロードマップの優先度が高い。

ただし、shadowDOMバージョン0は古い仕様です。 Shadow DOMバージョン1は新しいバージョンであり、Chrome、Safari、Operaのみが完全にサポートしています。 言うまでもなく、カスタム要素バージョン0も同じアップグレードを経ており、Chromeのみがカスタム要素バージョン1を完全にサポートしていますが、Safariテクニカルプレビューはバージョン17の時点でサポートしています。カスタム要素バージョン1では、Webコンポーネントの記述方法に大きな変更があります。したがって、それが何を伴うのかを完全に理解するようにしてください。

最後に、webcomponentjs polyfillは、ShadowDOMとカスタム要素のバージョン0の実装のみをサポートします。 ポリフィルのバージョン1ブランチはバージョン1をサポートしますが、まだリリースされていません。