LoginSignup
60
33

More than 3 years have passed since last update.

Shadow DOMを外部からスタイルできる新しい疑似要素「::part()」

Last updated at Posted at 2020-09-01

本稿では、Shadow DOMの内部の要素のスタイルを、外側からスタイリングできるようにするCSS Shadow Partsについて紹介する。

CSS Shadow Partsとは

  • Shadowホスト(Shadow DOMを使う側のHTML)から::part()を定義することで、Shadow DOM内部の要素にスタイルを適用できる。
  • 2018年11月15日にW3Cにドラフトが公開された仕様。
    • まだドラフトなので仕様変更があるかも知れない。
    • Chromeはバージョン73(2019年3月12日リリース)で対応されている。
  • この仕様に従ったShadow DOMは、スタイルをユーザが調整できる。
    • 例えば、サードパーティ製のボタンコンポーネントがあって、サイトのメインカラーが緑だったとき、そのボタンコンポーネントの色もサイトのメインカラーに合わせることができる。

非推奨になった ::shadow/deep/

  • Shadow DOMはDOMをカプセル化するための標準規格。
  • ::shadowセレクタと/deep/セレクタはShadow DOM内の要素をなんでも参照できてしまう仕様だった。
  • そのため、カプセル化を破壊してしまうので非推奨になった。
  • Chrome 63以降から::shadow/deep/は削除されている1

CSS Shadow Partsと::shadowのアプローチの違い

  • ::shadow: Shadow DOM内部の要素を何でもスタイリングできる。
    • プライベートAPI無理くり叩くようなアプローチ。
    • コンポーネント作者は、どんなセレクタで内部要素に依存されるか予想できないという問題があった。
    • コンポーネント利用者は、依存したセレクタがいつどう変更されるか分からず不安という問題があった。
  • CSS Shadow Parts: 明示的に公開されたShadow DOM内部要素のみスタイリングできる。
    • インターフェイスやパブリックメソッドを定義し、外部からはそれだけが使えるようにするのと似たアプローチ。
    • 公開する要素にはpart属性で名付けする。例: <button part="mybutton">
    • コンポーネント作者は、どこを公開できるかコントロールできる。(同時に何が公開されていて、スタイリングできるかはドキュメンテーションが大事になりそう)
    • コンポーネント利用者は、公開されたIDでアクセスできるので安心できるし、複雑なセレクターを書かなくて良くなる。

また、CSS Shadow Parts以外の外部からコンポーネントのスタイルを調整する手法として

があるが、本稿では割愛する。

CSS Shadow Partsを使ったサンプルコード

See the Pen CSS Shadow Parts by suin (@suin) on CodePen.

index.html
<link href="style.css" rel="stylesheet">
<script src="main.js"></script>

<h3>ホスト側の見出し3</h3>
<my-h3>シャドーDOM内の見出し3</my-h3>
<my-h3-no-part>シャドーDOM内の見出し3(partなし)</my-h3-no-part>
main.js
class MyH3 extends HTMLElement {
  constructor() {
    super();
    const node = this.attachShadow({ mode: "open" });
    node.innerHTML = `<h3 part="title"><slot/></h3>`;
  }
}

class MyH3NoPart extends HTMLElement {
  constructor() {
    super();
    const node = this.attachShadow({ mode: "open" });
    node.innerHTML = `<h3><slot/></h3>`; // この要素は外部からスタイリングできない
  }
}
customElements.define("my-h3", MyH3);
customElements.define("my-h3-no-part", MyH3NoPart);
style.css
h3 {
  color: blue;
}

/* my-h3はカスタム要素名、titleはmy-h3内部要素<h3>のpart属性を指す */
my-h3::part(title) {
  color: green;
}

実行結果

CSS_Shadow_Parts.png

参考

60
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
60
33