3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今更ながら shadow dom の挿入方法について悩む

Last updated at Posted at 2025-12-07

おつかれさまです。スポンジ芸人です。

弊社のアドカレが空いてるようなので、小ネタで埋めます。

さて、掲題の件。

一体お前は何を言ってるんだ?という説明語彙力のカケラも無いタイトルで皆様を困惑させていますが、こういうこと↓です。

やりたいこと

もともとのHTML

<main>
  <article id="art1">
    <h2>閑話休題</h2>
    <p>この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。<br>
    どうせ大したこと書かないんだし、人工無能に任せることにする</p>
  </article>
</main>

#art1の真下(子要素ではなくあくまで兄弟要素として)にshadow domで突っ込みたいとします。
下記のような状態をイメージしています。

<main>
  <article id="art1">
    <h2>閑話休題</h2>
    <p>この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。<br>
    どうせ大したこと書かないんだし、人工無能に任せることにする</p>
  </article>
  <#shadow-root>
    <p>人口無能登場!</p>
  </#shadow-root>
</main>

さて、これどうやってやるんでしょうか?

やり方

やり方1 下に shadow-root用の要素を1つ作る

普通はこうやるかなー。という方法ですね。

まず、下記のようにshadow-root用の要素 #shadow1 を作っておきます。

<main id="main1">
  <article id="art1">
    <h2>閑話休題</h2>
    <p>この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。<br>
    どうせ大したこと書かないんだし、人工無能に任せることにする</p>
  </article>
  <div id="shadow1"></div>
</main>
.js
const $shadow1 = document.querySelector("#shadow1");
const shadow = $shadow1.attachShadow({mode:"open"});
shadow.innerHTML = "<p>人口無能登場!</p>";

表示

閑話休題
この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。
どうせ大したこと書かないんだし、人工無能に任せることにする
人口無能登場!

今回、#art1 の真下に shadow root を追加しましたが、上に追加したい場合は #shadow1 の位置をずらせばOK。

<main id="main1">
  <div id="shadow1"></div>
  <article id="art1">
    <h2>閑話休題</h2>
    <p>この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。<br>
    どうせ大したこと書かないんだし、人工無能に任せることにする</p>
  </article>
</main>

表示

人口無能登場!
閑話休題
この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。
どうせ大したこと書かないんだし、人工無能に任せることにする

これで、普通に順番入れ替わります。

やり方2 で制御する。

もう一つのやり方は、shadow dom 側に <slot> を記載することで制御する方法です。
この場合、元となるHTMLには shadow root 用の要素は不要で、直接 #main1 に対して shadow root を設定します。

<main id="main1">
  <article id="art1">
    <h2>閑話休題</h2>
    <p>この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。<br>
    どうせ大したこと書かないんだし、人工無能に任せることにする</p>
  </article>
</main>
const $main = document.querySelector("#main1");
const shadow = $main.attachShadow({mode:"open"});
shadow.innerHTML = "<slot></slot><p>人口無能登場!</p>";

こうすることで、冒頭の表示にできます。

表示

閑話休題
この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。
どうせ大したこと書かないんだし、人工無能に任せることにする
人口無能登場!

<slot></slot>の部分に元々 #main1 に含まれていた要素をそこにレンダリングしてくれるようになります。

では、下記のように <slot></slot> を設定しないとどうなるか?というと、#main1の内容は shadow root に設定する <p>人口無能登場!</p> で上書きされてしまいます。(DOMツリー上は残っているのですが表示されません)

.js
const $main = document.querySelector("#main1");
const shadow = $main.attachShadow({mode:"open"});
shadow.innerHTML = "<p>人口無能登場!</p>";

表示

人口無能登場!

これでは、ダメですね。

もちろん、<slot></slot> の位置を変えれば、shadow dom で追加する要素を前に挿入することもできます。

.js
const $main = document.querySelector("#main1");
const shadow = $main.attachShadow({mode:"open"});
shadow.innerHTML = "<p>人口無能登場!</p><slot></slot>";

表示

人口無能登場!
閑話休題
この酔っぱらいはアドカレ空いてるのに気づいて飲みながらなんか書き始めたぞ。
どうせ大したこと書かないんだし、人工無能に任せることにする

これでOK。

まとめ。 嬉しいことあるの?

shadow dom を挿入する方法について復習してみました。

今回はテキストのみの挿入なので、まーどっちでもいいかな?というのはありますが、
shadow dom で挿入するDOMがテキストだけのはずがない!

ということで、雑に下記のように考えました。

case : shadow dom で挿入する要素の親要素(全体のサイズなど)を挿入される HTML側で制御したい

→ これは やり方1ですね。

case : shadow dom で挿入する要素の全体サイズなど含めて 挿入される側で制御したい

→ これは 場合によっては、やり方2の方が向いてるかもしれません。

ただし <slot></slot> で親要素の位置を意識しているあたり、完全にコンポーネント化された設計とはいえないという気はしますので、汎用的なライブラリで使える方法か?というと違う気はします。

さて、あなたは <slot></slot>をどのように利用しますか?
コメントなどで教えていただけたら助かりますー

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?