コンテンツにスキップ

スタイリング

スコープ付きスタイルを安全に実現する方法は2つあります。

  1. スタイルオブジェクトを使う方法
  2. Shadow DOMとconstructableスタイルシートを使う方法

パフォーマンスの面でブラウザがより支援しやすくなるため、2番目の方法を強く推奨します。

タグ付きテンプレート用の組み込み html 関数を使うとき、Partial<CSSStyleDeclaration> 型のスタイルオブジェクトを任意の要素の style 属性に渡すことができます。これにより、計算されたスタイルや条件付きスタイルが可能になります。スタイルオブジェクトについて詳しくはMDNを参照してください。

今すぐこのCodePenの例 ↗で試すか、実際に動く様子はこちら: スタイルオブジェクトデモ ↗

import { WebComponent } from 'https://esm.sh/web-component-base@latest'
class StyledElement extends WebComponent {
static props = {
emphasize: false,
type: 'warn',
}
#typeStyles = {
warn: {
backgroundColor: 'yellow',
border: '1px solid orange',
},
error: {
backgroundColor: 'orange',
border: '1px solid red',
},
}
get template() {
return html`
<div
style=${{
...this.#typeStyles[this.props.type],
padding: '1em',
}}
>
<p style=${{ fontStyle: this.props.emphasize && 'italic' }}>Wow!</p>
</div>
`
}
}
customElements.define('styled-elements', StyledElement)

Shadow DOMとConstructableスタイルシートを使う

Section titled “Shadow DOMとConstructableスタイルシートを使う”

Shadow DOMを使う場合、static styles プロパティを追加できます。これは shadowRootadoptedStylesheetsに追加されます。文字列、CSSStyleSheet、またはそのいずれかの配列を受け付けます。

今すぐこのCodePenの例 ↗で試すか、実際に動く様子はこちら: Constructableスタイルデモ ↗

class StyledElement extends WebComponent {
static shadowRootInit = {
mode: 'open',
}
static styles = `
div {
background-color: yellow;
border: 1px solid black;
padding: 1em;
p {
text-decoration: underline;
}
}
`
get template() {
return html`
<div>
<p>Wow!?</p>
</div>
`
}
}
customElements.define('styled-elements', StyledElement)

複数のスタイルシートを合成する

Section titled “複数のスタイルシートを合成する”

複数のシートを採用するには配列を渡します。これらは順番どおりに適用されるため、同じ詳細度であれば後の項目が優先されます。共有のトークンやベースシートを先に置き、コンポーネントごとのスタイルをその後に置いてください。

// tokens.js: すべてのコンポーネントで共有
export const tokens = `
:host {
--cozy-radius: 6px;
--cozy-accent: rebeccapurple;
}
`
// cozy-button.js
import { tokens } from './tokens.js'
class CozyButton extends WebComponent {
static shadowRootInit = { mode: 'open' }
static styles = [
tokens,
`
button {
border-radius: var(--cozy-radius);
background: var(--cozy-accent);
}
`,
]
}

各項目は文字列でも、あらかじめ作成されたCSSStyleSheetオブジェクトでもよく、両者を混在させることもできます。CSSStyleSheet は再作成されるのではなく、そのまま採用されるため、共有インスタンスを一度だけ構築し、それを採用するすべてのコンポーネントで再利用できます。

const base = new CSSStyleSheet()
base.replaceSync(tokens)
class CozyBadge extends WebComponent {
static shadowRootInit = { mode: 'open' }
static styles = [base, `span { font-size: 0.8em; }`]
}

単一の文字列は、これまでどおりそのまま機能します。配列形式は追加的なものです。