影DOMの風変わりとそれらを利用する方法


Disclaimer:

During this article I'll be referring to the "normal" DOM as "Light DOM" to make it clear when I'm talking about it.


シャドウDOMは何ですか?


シャドウDOMは、Webコンポーネントを構成するコア標準の一つと見なされますが
実際にブラウザのようにネイティブのHTML要素としてかなりの間<video>それを使用して、それはちょうどそれがWebコンポーネントの標準に組み込まれている前に開発者が使用できませんでした.
そして今、そのエッジはクロムのDOM DOMを含むすべてのWebコンポーネントの標準に基づいている、すべてのモダンなブラウザで利用可能です!🎉
シャドウDOMの全体の考えは、私たちが孤立したDOM木をつくることを可能にするということです
光DOMから、しかし、それは光DOMに追加されることができて、それと一緒にレンダリングされることができます.
私は、このイメージがよりよくそれを理解するのを助けるかもしれないように、ちょっと混乱しているということを知っています:

Source: "Using Shadow DOM" by Mozilla Contributors


この分離はシャドウDOMの主要な特徴であり、他のアプローチが実際に解決できない問題を解決します.
  • シャドウDOM内部のノードは、document.querySelector() だから、他のスクリプトから不要な変更を防ぐことができます.
  • シャドウDOMのすべてのCSSは、いくつかの大きな利点を持っています.
  • 影DOMのスタイルは、光DOMに漏れません
  • 光DOMのスタイルは、影DOM *に出血しません
  • これらの2つのようなスーパーシンプルなセレクタを使用することができますbutton or #someid 何かを恐れることなく、これはシャドウDOMがCSSを修正すると言う最大の理由です.
  • さて、あなたは私が光DOMスタイルが影DOMに吹き飛ばされないと言及したとき、私がアスタリスクを置くことに気がつきました.
    あなたは、影DOMが光DOMから様式化される方法を持たないのを見て、それが少しの制限があまりに制限して、themingと光カスタマイズのような多くの一般的なユースケースのためになるでしょう.
    シャドウDOMコンテンツは、ある場合には光DOMから様式化できる理由です.
    多くのCSS関連のものと同様に、これらを読むだけで少し理解するのが難しいので、私はこの記事の残りの部分のようなクイズのようなアプローチを取るつもりです.

    1 -継承はどのようにここで働いていますか?


    これは私たちの最初の影DOMのマークアップです.
    <style>
      .some-class {
        font-family: Arial;
        font-size: 14px;
        color: blue;
      }
    </style>
    
    <div>
      This is some text
    </div>
    <div class="some-class">
      And here's some more text
    </div>
    
    そして、これは光のDOMです
    <style>
      .container {
        font-family: Helvetica;
        font-size: 16px;
        color: green;
        padding: 2em;
      }
    
      .container .some-class {
        color: red;
      }
    </style>
    <div class="container">
      <!--
      The Shadow DOM from the previous snippet is
      in this web component
      -->
      <question-one></question-one>
    </div>
    
    これはどうやってレンダリングすると思いますか?自分を甘やかすな😉.

    アンサー


    < div >

    なぜ?


    デフォルトでシャドウDOM内部のノードには特別なスタイルはありません.font-family or color は、DOM DOMの先祖から値を継承するp >
    あなたが見ることができるようにsome-class 我々は実際に定義しているfont-family , font-size , and color その部分はスタイルを継承しません.p >
    あなたがそれに気づいたならば.container .some-class 光DOMのセレクターは基本的に役に立たない影の内部のノードに影響を与えようとしています.p >

    2 -あなたはスタイルをホストできますか?


    シャドウDOMは< br/>です
    <> P >
    クラスをハイライト表示する
    <style>
      /*
      This selector basically applies to the root
      of our shadow DOM
      */
      :host {
        display: block;
        width: 30px;
        border: 1px dotted black;
      }
    </style>
    
    <div>1</div>
    <div>2</div>
    <div>3</div>
    
    < div >
    そしてここでは光DOM : < br/>
    <> P >
    クラスをハイライト表示する
    <style>
      .some-class {
        display: flex;
        flex-flow: row-reverse;
        width: 100%;
        border: 1px solid red;
      }
    </style>
    <question-two></question-two>
    <question-two class="some-class"></question-two>
    
    < div >
    もう一度、どうやってこれをレンダリングすると思いますか?準備ができましたか?p >

    アンサー


    < divクラス= "グリッチ埋め込みラップ"スタイル=高さ: 450 px ;幅: 100 %;マージン: 1 em auto 1.3 em "
    < iframe sandbox ="同じ起源を許可すると、スクリプトがフォームを許可し、ユーザのアクティベーションでトップナビゲーションを許可しますhttps://glitch.com/embed/#!シャドウドムクイズ?previewsize = 100 & amp ;パス=質問2.グリット「スタイル=」高さの上のHTML幅:100 %;ボーダー0マージン: 0パディング: 0 "load ="lazy "/>
    < div >

    なぜ?


    子供ノードに適用されるスタイルと異なり、シャドウDOMのホストレベルのスタイルは、ライトDOMから上書きできます.p >
    基本的に、あなたが直接ホストのために定義するものはデフォルトのスタイルではありません.したがって、実際にあるスタイルを強制したいなら、代わりにコンテナノードを子供とスタイルとして追加したいと思います.p >

    3 - CSS変数は適用されますか?


    もう一度は、ここに影DOM
    <> P >
    クラスをハイライト表示する
    <style>
      div {
        color: var(--my-color, blue);
      }
    </style>
    
    <div>
      Some text
    </div>
    
    < div >
    そしてここでは光DOM : < br/>
    <> P >
    クラスをハイライト表示する
    <style>
      .custom-color {
        --my-color: red;
      }
    </style>
    
    <question-three></question-three>
    <question-three class="custom-color"></question-three>
    
    < div >
    これで何が起こるのですか?p >

    アンサー


    < divクラス= "グリッチ埋め込みラップ"スタイル=高さ: 450 px ;幅: 100 %;マージン: 1 em auto 1.3 em "
    < iframe sandbox ="同じ起源を許可すると、スクリプトがフォームを許可し、ユーザのアクティベーションでトップナビゲーションを許可しますhttps://glitch.com/embed/#!シャドウドムクイズ?previewsize = 100 & amp ;パス=質問3.グリット「スタイル=」高さの上のHTML幅:100 %;ボーダー0マージン: 0パディング: 0 "load ="lazy "/>
    < div >

    なぜ?


    CSSカスタムのプロパティ(またはCSS変数はほとんどの人が呼び出しています)はシャドウDOMの中で自由にノードを設定することができます.p >
    もちろん、この例のように、シャドウDOMで使用されるスタイルは、どの変数を使用したいのか、どこで定義しているかを定義しなければなりません.p >

    For more information on CSS Variables this article should help as a starting point.


    4 -子供ノードに何が起こりますか?


    もう一つの質問の準備ができていますか?影DOMはここにあります
    <> P >
    クラスをハイライト表示する
    <style>
      /*
      the ::slotted(selector) selector applies to
      any nodes appended in the indicated slot
      that match the given selector
      */
      header ::slotted(*) {
        text-decoration: underline;
      }
      article ::slotted(div.special) {
        color: turquoise;
      }
    </style>
    
    <section>
      <header>
        <h3><slot name="header">Default Header</slot></h3>
      </header>
      <article>
        <slot></slot>
      </article>
    </section>
    
    < div >
    そしてここでは光DOM : < br/>
    <> P >
    クラスをハイライト表示する
    <style>
      .some-class .header {
        color: red;
      }
    
      .some-class div {
        color: mediumvioletred;
      }
    </style>
    
    <question-four>
      <div>1</div>
      <div class="special">2</div>
      <div>3</div>
    </question-four>
    
    <question-four class="some-class">
      <div>4</div>
      <div class="special">5</div>
      <div>6</div>
      <span class="header" slot="header">
        Second Element Header
      </span>
    </question-four>
    
    < div >
    この1つは、あなたの時間を取るので、どのようにレンダリングすると思いますか?p >

    アンサー


    < divクラス= "グリッチ埋め込みラップ"スタイル=高さ: 450 px ;幅: 100 %;マージン: 1 em auto 1.3 em "
    < iframe sandbox ="同じ起源を許可すると、スクリプトがフォームを許可し、ユーザのアクティベーションでトップナビゲーションを許可しますhttps://glitch.com/embed/#!シャドウドムクイズ?previewsize = 100 & amp ;パス=質問4.グリット「スタイル=」高さの上のHTML幅:100 %;ボーダー0マージン: 0パディング: 0 "load ="lazy "/>
    < div >

    なぜ?


    これがあなたの最初の時にシャドウDOMについて読んでいるならば、私はあなたにこれを得ないならば、あなたを非難しません、しかし、私と耐えてください、私はこれを説明するために最善を尽くしますp >
    あなたは、影DOMで、特別なものがあります<slot> 基本的に、この要素の子要素の一部がどのような部分に追加されるかを示すタグです.p >
    あなたが使ったならchildren Vueの反応またはスロットでは、おそらくこの概念に基づいている(Vueのスロットはこの規格に基づいている).p >
    現在、シャドウDOMで定義されたスタイルでは、スロットを通して追加された子供たちにスタイルを適用しようとすることができます::slotted() セレクタp >
    しかし、あなたが見ることができるように、これはホストレベルのスタイルがどのようにカップル質問をしたかに本当に似ています.適用されるスタイル::slotted() また、基本的にデフォルトのスタイルは、ライトDOMから来るスタイルと結合するが、ライトDOMスタイルは優先度が高い.p >

    5 -あなたはいくつかの部分だけをスタイルできますか?


    最後の質問!準備ができましたか.影DOMはここにあります
    <> P >
    クラスをハイライト表示する
    <style>
      :host {
        display: flex;
      }
      img {
        width: 64px;
        height: 64px;
      }
      div {
        font-family: Arial;
        color: seagreen;
      }
    </style>
    
    <img part="avatar" src="https://via.placeholder.com/64x64.jpg?text=Avatar" />
    <div part="name">
      Some Name
    </div>
    
    < div >
    そしてここでは光DOM : < br/>
    <> P >
    クラスをハイライト表示する
    <style>
      question-five.custom-part::part(avatar) {
        border-radius: 50%;
      }
    
      question-five.custom-part::part(name) {
        font-family: Verdana;
        color: mediumpurple;
      }
    </style>
    
    <question-five></question-five>
    <question-five class="custom-part"></question-five>
    
    < div >
    最後に、この部分はどうやってレンダリングするのでしょうかp >

    回答5


    < divクラス= "グリッチ埋め込みラップ"スタイル=高さ: 450 px ;幅: 100 %;マージン: 1 em auto 1.3 em "
    < iframe sandbox ="同じ起源を許可すると、スクリプトがフォームを許可し、ユーザのアクティベーションでトップナビゲーションを許可しますhttps://glitch.com/embed/#!シャドウドムクイズ?previewsize = 100 & amp ;パス=質問5.グリット「スタイル=」高さの上のHTML幅:100 %;ボーダー0マージン: 0パディング: 0 "load ="lazy "/>
    < div >

    なぜ?


    現在、我々はすべての最新のブラウザーで利用できるすべての4つの前の質問の内容と違って、最先端の根拠に入っています、この最後のものはSafariでまだ利用できません(それはテクノロジープレビューで、そして、私のテストで、それがちょうどうまく働いたので、多分すぐに来るでしょう)、しかし、それはすべてのクロムベースのブラウザー(Chrome、EDGE、Opera、その他)とFirefoxで利用可能ですp >

    Update: As of October 2020, Safari has implemented this standard so now it works on all modern browsers!


    このデモのためにシャドウ部分の標準を使用し、名前が示すように、私たちは私たちの影DOMの中の“部品”を宣言することができます ::part() pseudo element .


    <高橋潤子>**この項目の翻訳は古いバージョンが元になっています::part() ライトDOMスタイルが最優先され、シャドウDOMに設定されたスタイルがフォールバックとして動作します.p >

    閉じる


    シャドウDOMはWeb標準の本当に強力な部分ですが、一見したところでは明らかではありません.p >
    <小野寺>この小さなクイズでは、Shadow DOMがどのように機能しているのか、どのようにして自分自身のWebコンポーネントを作成するか、あるいは自分自身のWebコンポーネントを作成するときにどのように利用できるかを理解してくれました.p >

    詳しい情報


    < P >https://developers.google.com/web/fundamentals/web-components/shadowdom

    https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM