🙌

Web Componentのcssプロパティを外部からカスタム可能にする

2024/01/10に公開

Element.shadowRootにアクセスすれば改変は可能ですが。基本的にShadow DOM内部の中のstyleは上書き不可能です。特定の色・サイズ・フォントなど、コンポーネントの利用者がカスタム可能な部分を提供する方法です。

外部からカスタム可能にする方法

明示的・暗黙的にinheritする

内部のプロパティが暗黙的、または明示的にinheritである場合はLightDOM->ShadowDOMであろうと親要素のプロパティを継承します。至極単純なコンポーネントであるならこの手法も十分有効です。勿論ShadowDOM内部が複雑になってくるとこの手法は効かないため、後述する2つの方法が必要になってきます。

CSS variable

Web Componentに記述される:hostは、とても弱いCSSセレクターです。

:host {
  background: blue;
}

これは

x-button {
  background: black;
}

これで上書きできます。
この弱さを利用して、上書き可能なCSS variablesを設定することでカスタム可能なWeb Componentを適用できます。

:host {
  --x-button-text-color: #fff;
  --x-button-backgrund-color: #000;
}

.button {
  color: var(--x-button-text-color);
  background: var(--x-button-background-color);
}
x-button {
  --x-button-color: #fff;
  --x-button-background-color: #000;
}

この方法はカスタム可能か不可能かをCSS variableで定義したもののみに限定します。そのためWeb Componentの開発者にとっては消費者に意図した変更のみを許す方法でしょう。

不便な点としては、例えばボタンについて定義しようとしたら、デフォルト状態、:hover, :active, :focusについて全て変数化しなければいけないということです。

CSS :part selector

コンポーネント側が対応していれば自由に特定の要素のstyleを変更可能です。

::part() - CSS: カスケーディングスタイルシート | MDN

<x-button>
  <button part="button">
    <slot></slot>
  </button>
</x-button>

Shadow DOM内のcssをカスタマイズ可能にしたい要素へpartattributeで名付けすれば、外から改変可能。

x-button::part(button) {
  background: #000;
}

partはセレクタ全体をカスタム可能になるため、原型の残らない変更も可能になる自由度の高い手法です。意図した利用になるかどうか見極めて提供するのが良いでしょう。

以上、Shadow DOM内のCSSをカスタム可能にする2つの方法でした。

Discussion