Web Components (Custom Elements) の基礎と実践
HTML5におけるカスタムタグ(Custom Elements)の定義、実装方法、ベストプラクティス、およびフレームワークとの比較についてのまとめ。(by Google Gemini)
概要
Web Components規格の一部であるCustom Elements(カスタム要素)を指す
開発者が独自の要素名を定義しブラウザに新しいHTMLタグとして認識させる仕組み
主な使い方
HTMLElementクラスを継承したJavaScriptクラスを作成する
customElements.define('要素名', クラス名)でブラウザに登録する
ライフサイクルメソッド(connectedCallback等)で挙動を定義する
サンプルコード
code:sample.js
class MyCounter extends HTMLElement {
constructor() {
super();
this.count = 0;
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
}
increment() {
this.count++;
this.render();
}
render() {
this.shadowRoot.innerHTML = `
<style>
button { padding: 10px; }
span { font-weight: bold; }
</style>
<span>Count: ${this.count}</span>
<button id="btn">Increment</button>
`;
this.shadowRoot.querySelector('#btn').onclick = () => this.increment();
}
}
customElements.define('my-counter', MyCounter);
ベストプラクティスと注意点
ネーミングルール
既存タグとの衝突回避のため必ずハイフン(-)を含める必要がある
カプセル化
Shadow DOMを活用してスタイルやDOMの干渉を防ぐ
アクセシビリティ (A11y)
必要に応じてrole属性やaria-*属性を付与する
SEOとレンダリング
JS実行が必要なためSEOリスクがある(SSRや宣言的Shadow DOMでの対策を検討)
初期化のタイミング
JS読み込み前に記述されたタグは登録後にアップグレードされる
画期的な使い方と実際のユースケース
マイクロフロントエンド
異なるフレームワークで作られた部品を共通のカスタムタグとして共存させる
実際の採用事例
GitHub: relative-timeタグによる日時表示の自動ローカライズ
YouTube: UIの多くをWeb Componentsで構築
Adobe / Salesforce: デザインシステムをカスタム要素で提供
React との比較・共存
比較
Reactはライブラリ依存だが、Custom Elementsはブラウザ標準機能
データの受け渡しにおいてCustom Elementsは属性(文字列)が基本となる
共存
React 19以降はカスタム要素との親和性が大幅に向上し直接利用が容易
デザインシステムをカスタム要素で作ることでReact外でも再利用可能
実装におけるクラス構文の必要性
標準仕様(V1)ではclass構文の使用が必須
HTMLElementを継承する仕組み上、functionによる定義はエラーとなる
関数型で書きたい場合
Atomico等のライブラリを使用すれば内部的にclassへ変換して登録してくれる
実務における選択肢(Vanilla vs Lit)
素のカスタム要素 (Vanilla JS)
属性同期やDOM更新をすべて手動で書く必要があり実装が複雑になりやすい
超軽量な装飾用タグや依存をゼロにしたい場合に適している
Lit (Google製ライブラリ)
Web Componentsの面倒な部分(効率的な描画、属性同期)を解決する薄い皮
実務で状態を持つUIコンポーネントを作る際のデファクトスタンダード