exportparts
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2020.
exportparts
グローバル属性 では、ネストしたシャドウツリー内に存在する要素をパーツ (part
) 名でエクスポートして、そのスタイルを選択できるようにすることができます。
シャドウツリーは、識別子、クラス、スタイルが、通常の DOM に属するセレクターやクエリーによって到達することができない孤立した構造体です。シャドウツリー要素に適用できる 2 つの HTML 属性があり、これを使用すると、外部からシャドウツリーに CSS スタイルを適用することができます。これらは、 part
および exportparts
です。
グローバル属性 part
は、シャドウツリー要素をその親 DOM から見えるようにします。パーツ名は、 ::part()
擬似要素の引数として使用されます。これにより、シャドウツリー外の要素に CSS スタイルを適用することができます。ただし、 ::part()
擬似要素は親 DOM からのみ表示されます。つまり、シャドウツリーが入れ子になっている場合、パーツは直接の親以外の祖先には表示されません。exportparts
属性は、この制限を解決します。
exportparts
属性は、シャドウツリーの一部をシャドウ DOM の外部から見えるようにします。この概念は「エクスポート」と呼ばれます。exportparts
属性は、シャドウツリーが関連付けられている要素である、要素のシャドウホストに配置されます。この属性の値は、シャドウツリー内に存在する part
名をカンマで区切ったリストです。これらの名前は、現在の構造の外部の DOM で利用可能になります。
<template id="ancestor-component">
<nested-component exportparts="part1, part2, part5"></nested-component>
</template>
part
をエクスポートする場合、以下のスニペットに示すように、そのパーツに別の名前を割り当てるオプションがあります。 exportparts
属性の値は、実際には、パーツ名と割り当てられた名前とのカンマ区切りのリストです。したがって、上記のコードスニペットの exportparts
属性は、 exportparts="part1:part1, part2:part2, part5:part5
と同等であり、それぞれ part
が同じ名前でエクスポートされることを示しています。それぞれの項目では、最初の文字列はシャドウツリー内のパーツの名前を指定し、2 つ目の文字列はパーツが外部に公開される名前を指定します。
<template id="ancestor-component">
<nested-component
exportparts="part1:exposed1, part2:exposed2"></nested-component>
</template>
例
基本的なコンポーネント
入れ子になった構成部分内の部品を対象とするために exportparts
がどのように使用されるかを示すために、構成部分を作成し、それを別の構成部分に入れ子にします。
HTML
まず、別の部分で囲むカード部分を作成しましょう。また、新しく作成した要素を使用し、スロットにプレーンテキストをコンテンツとして入力します。
<template id="card-component-template">
<style>
:host {
display: block;
}
</style>
<div class="base" part="base">
<div part="header"><slot name="header_slot"></slot></div>
<div part="body"><slot name="body_slot"></slot></div>
<div part="footer"><slot name="footer_slot"></slot></div>
</div>
</template>
<card-component>
<p slot="header_slot">This is the header</p>
<p slot="body_slot">This is the body</p>
<p slot="footer_slot">This is the footer</p>
</card-component>
JavaScript
JavaScript を使用して、上記の HTML で定義したウェブコンポーネントを定義します。
customElements.define(
"card-component",
class extends HTMLElement {
constructor() {
super(); // コンストラクターでは常に最初に super を呼び出してください。
const cardComponent = document.getElementById(
"card-component-template",
).content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardComponent.cloneNode(true));
}
},
);
CSS
<card-component>
シャドウツリーの各部分のスタイルを、 ::part
擬似要素を使用して設定します。
::part(body) {
color: red;
font-style: italic;
}
結果
入れ子のコンポーネント
上記の <card-component>
の例に続けて、<card-component>
を別のコンポーネント(この例では <card-wrapper>
コンポーネント)で囲んで、入れ子コンポーネントを作成します。次に、コンポーネントのシャドウツリーの外からスタイルを設定できるように、入れ子コンポーネントから exportparts
属性でエクスポートする部分を作成します。
HTML
<template id="card-wrapper">
<style>
:host {
display: block;
}
</style>
<card-component exportparts="base, header, body">
<slot name="H" slot="header_slot"></slot>
<slot name="B" slot="body_slot"></slot>
<slot name="F" slot="footer_slot"></slot>
</card-component>
</template>
比較のために、カスタム要素 <card-wrapper>
および <card-component>
を含めます。
<h2>Card wrapper</h2>
<card-wrapper>
<p slot="H">This is the header</p>
<p slot="B">This is the body</p>
<p slot="F">This is the footer</p>
</card-wrapper>
<h2>Card component</h2>
<card-component>
<p slot="header_slot">This is the header</p>
<p slot="body_slot">This is the body</p>
<p slot="footer_slot">This is the footer</p>
</card-component>
JavaScript
customElements.define(
"card-wrapper",
class extends HTMLElement {
constructor() {
super(); // コンストラクターでは、常に最初に super を呼び出す
const cardWrapper = document.getElementById("card-wrapper").content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardWrapper.cloneNode(true));
}
},
);
CSS
これで、<card-wrapper>
内に次のように入れ子にした場合、<card-component>
の部分を直接対象とすることができます。
h2 {
background-color: #dedede;
}
card-wrapper,
card-component {
border: 1px dashed blue;
width: fit-content;
}
::part(body) {
color: red;
font-style: italic;
}
::part(header),
::part(footer) {
font-weight: bold;
}
結果
footer
は、exportparts
に含まれていないため、入れ子にした場合、太字にはなりません。
対応付けられたパーツの公開
エクスポートしたパーツの名前を変更するには、割り当てられたパーツをカンマで区切ったリストを記載します。各割り当てられたパーツには、元の名とエクスポートした名前がコロン (:
) で区切られて含まれます。
HTML
以前の <card-wrapper>
カスタム要素を、再マッピング構文を使用して更新します (エクスポートされるパーツのリストから body
を省略します)。
<template id="card-wrapper">
<card-component
exportparts="
base:card__base,
header:card__header,
footer:card__footer
">
<span slot="header_slot"><slot name="H"></slot></span>
<span slot="body_slot"><slot name="B"></slot></span>
<span slot="footer_slot"><slot name="F"></slot></span>
</card-component>
</template>
JavaScript
customElements.define(
"card-wrapper",
class extends HTMLElement {
constructor() {
super(); // コンストラクターでは、常に最初に super を呼び出す
const cardWrapper = document.getElementById("card-wrapper").content;
const shadowRoot = this.attachShadow({
mode: "open",
});
shadowRoot.appendChild(cardWrapper.cloneNode(true));
}
},
);
CSS
<card-wrapper>
内から <card-component>
の部分をターゲットとして、エクスポートされた部分のみ、公開されている部分名を使用してスタイルを設定することができます。
/* エクスポートするパーツの名前を選択 */
::part(card__header) {
font-weight: bold;
}
/* 何も選択しない。これらのパーツ名はエクスポートされていない */
::part(footer),
::part(body) {
font-weight: bold;
}
結果
仕様書
Specification |
---|
CSS Shadow Parts # element-attrdef-html-global-exportparts |
ブラウザーの互換性
関連情報
- HTML の
part
属性 - HTML の
<template>
要素と<slot>
要素 - CSS の
::part
および::slotted
擬似要素 ShadowRoot
インターフェイスElement.part
プロパティ- テンプレートとスロットの使用
- CSS スコープモジュール