🦊

WEB Components入門

2021/09/12に公開

概要

Web Componentsは、カプセル化されたコンポーネントを定義し、これを再利用するための技術です。コンポーネントは、HTML、CSS、JavaScriptなどから構成されます。

大きく分けて次の3つの技術を組み合わせて、コンポーネント化を実現します。

  • Shadow DOM
  • Custom Elements
  • HTML Template

※以前はHTML importsがありましたが、廃止となりました。

Shadow DOM

通常のDOMとは切り離されカプセル化された、DOMツリーを作成するためのAPIです。カプセル化されているため、スタイルシートなどのスコープも切り離されるため、他と干渉しなくなります。(詳細

Shadow DOMを作成するには、attachShadow()を利用します。

Custom Elements

独自のHTML要素を作れるAPIです。Custom Elementsを作成するには、customElements.define()を利用します。

HTML Template

HTML要素を自作するためのAPIです。<template></template>の間にHTMLマークアップや、スタイルを定義します。※今回の記事では詳しく触れません

簡単な実装

JSでWEBページに文字列「Hello」を出力するだけのWEB Componentsを作成します。

index.js
import './styles.css'

class HelloElement extends HTMLElement {
  constructor() {
    super()

    const element = document.createElement('p')
    element.textContent = 'Hello'

        // part属性を付与し、ShadowDOM内部の要素にスタイルを適用できるようにする
    element.setAttribute('part', 'wrapper')

    // shadowDOMを作成する。modeがopenの場合、shadowRootプロパティでアクセスできる
    this.shadow = this.attachShadow({ mode: 'open' })
    this.shadow.append(element)
  }
}

const main = () => {
  customElements.define('hello-element', HelloElement)
}

main()
index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script src="src/index.js"></script>
  </head>
  <body>
    <hello-element></hello-element>
  </body>
</html>
styles.css
hello-element::part(wrapper) {
  color: red;
}

以下のスクショは、ディペロッパーツールのElementsを確認したものです。shadow DOMツリーの根の部分であるshadow rootが存在している事がわかります。

CSS Shadow Partsについて

先ほどのJSのコードでelement.setAttribute('part', 'wrapper')でpart属性を付与していました。これはShadowツリー内の要素に対して、外部からスタイルを指定できるようにする仕組みです。Shadow DOMによりスタイルシートのスコープが隔離されたために、普通にClassを与えるとスタイルが当たりません。この問題を解決するのが、CSS Shadow Partsです。

※ステータスはドラフトの状態なので仕様変更があるかも知れません。(詳細

ライブラリ

WEB Componentsにはライブラリがあり、webcomponents.orgに一覧があります。

最近ではメルカリがLitを採用したと言っていました。

Web Componentsを構築するためのライブラリはLit (採用の時点ではLitElement)を採用しています。これはシンプルな分カスタムが効きやすいという判断です。

引用元: 新しいメルカリDesign System Web | メルカリエンジニアリング

以上です。

参考

https://developer.mozilla.org/ja/docs/Web/Web_Components/Using_shadow_DOM
https://tech.uzabase.com/entry/2020/11/18/090000
https://qiita.com/suin/items/72b85e7d4465719aa4e8

Discussion