Spielen mit Shadow DOM

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Vor etwa einem Jahr kündigte Twitter an, dass eingebettete Tweets mit dem Shadow DOM statt mit einem <iframe> angezeigt werden, sofern der Browser Shadow DOM unterstützt.

Warum? Nun, Geschwindigkeit ist ein Grund.

Sie sagen

Viel geringere Speichernutzung im Browser und viel schnellere Renderzeiten. Tweets erscheinen schneller und Seiten scrollen flüssiger, selbst wenn mehrere Tweets auf derselben Seite angezeigt werden.

Warum die Wahl? Warum ist es notwendig, entweder iframes oder Shadow DOM zu verwenden? Warum nicht einfach den Inhalt auf die Seite injizieren?

Es ist ein absolut verständliches Bedürfnis nach *Kontrolle*. Ein eingebetteter Tweet sollte genau so aussehen und sich verhalten wie ein eingebetteter Tweet. Sie möchten sich keine Sorgen machen, dass die Stile der Seite eindringen und das durcheinander bringen.

Ein <iframe> macht die Stil-Einkapselung sehr einfach. Richten Sie die src des Iframes auf eine URL, die anzeigt, wie ein eingebetteter Tweet aussehen soll, und Sie sind fertig. Die einzigen Stile, die verwendet werden, sind die, die Sie in diesem Dokument enthalten.

Twitter führt diese iFrame-Injektion auf eine Weise durch, die für progressive Verbesserung und Syndizierung geeignet ist. Sie stellen eine <blockquote> mit dem Tweet und ein <script> bereit. Das Skript führt die iFrame-Injektion durch. Wenn das Skript nicht ausgeführt wird, ist das kein Problem, eine zufriedene Blockquote. Wenn das Skript ausgeführt wird, ein voll funktionsfähiger eingebetteter Tweet.

Dieses Skript ist hier der Schlüssel. Skripte können fast alles tun, und sie hosten es, sodass sie es jederzeit ändern können. So erkennen sie die Shadow DOM-Unterstützung und wählen stattdessen diesen Weg. Und wie wir bereits besprochen haben, ist Shadow DOM schneller zu rendern und benötigt weniger Speicher. Shadow DOM kann auch bei der Stil-Einkapselung helfen, die wir uns gleich ansehen werden.

Höhenflexibilität

Da ist noch etwas, das mir am Herzen liegt. Ein <iframe> passt seine Höhe nicht an seinen Inhalt an, wie Sie es von anderen Elementen erwarten. Sie legen eine Höhe fest und das war's. Es wird Scrollbalken haben, wenn Sie es zulassen und der Inhalt es benötigt. Früher bei Wufoo mussten wir viele Hürden überwinden, um eingebettete Formulare (in Frames) so hoch zu machen, wie sie sein mussten. Heute haben unsere eingebetteten Pens bei CodePen verstellbare Höhen, aber es gibt keine Option für "so hoch wie nötig". (Ich bin mir nicht sicher, ob das für CodePen-Embeds sinnvoll ist oder nicht, aber jedenfalls kann man es im Moment nicht tun.)

Ein Element mit Shadow DOM *ist* wie jedes andere Element, da es sich natürlich an den Inhalt anpasst. Ich bin sicher, dass auch Twitter das attraktiv findet. Wenn sie die Höhe falsch berechnen, riskieren sie, Inhalte abzuschneiden oder zumindest dafür zu sorgen, dass der eingebettete Tweet fehlerhaft aussieht.

Grundlegendste Verwendung

Hier ist das absolute Minimum, um einen Shadow DOM einzurichten und etwas hineinzulegen

Siehe den Pen Most basic shadow DOM von Chris Coyier (@chriscoyier) auf CodePen.

Beachten Sie, wie das Styling innerhalb des Shadow DOM nicht nach außen zum normalen Absatz-Element durchsickert? Beide Absätze wären rot, wenn sie es täten.

Und beachten Sie, wie der Absatz im Shadow DOM nicht serifenlos ist wie der außerhalb? Nun, normalerweise wäre er das. Geerbte Stile *erben immer noch* durch den Shadow DOM (daher ist er in dieser Hinsicht keine so starke Barriere wie ein iFrame). Aber wir erzwingen ihn absichtlich wieder in den Anfangszustand wie hier

:host {
  all: initial;
}

Behandlung dieses Fallbacks

Mein erster Gedanke zur Behandlung eines Fallbacks für Browser, die Shadow DOM nicht unterstützen, war, dass man denselben Inhalt, den man in den Shadow DOM packte, in einen iFrame mit srcdoc packen könnte, wie...

<iframe srcdoc="the same content">

Oder wahrscheinlicher ist dies etwas, das Sie in JavaScript tun, also würden Sie zuerst auf Unterstützung testen und dann entweder die Shadow DOM-Sachen machen oder den iFrame dynamisch erstellen

Siehe den Pen Shadow DOM Basic von Chris Coyier (@chriscoyier) auf CodePen.

Es stellt sich heraus, dass srcdoc (allein) nicht die beste Wahl für einen Fallback ist, da es keine IE- oder Edge-Unterstützung dafür gibt. Aber es ist auch kein großes Problem, einfach eine Daten-URL für die normale src zu verwenden. Hier ist ein Fork von Šime Vidas, in dem er das behoben hat

let content = `
  <style>
    body { /* for fallback iframe */
      margin: 0;
    }
    p { 
      border: 1px solid #ccc;
      padding: 1rem;
      color: red;
      font-family: sans-serif;
    }
  </style>

  <p>Element with Shadow DOM</p>
`;

let el = document.querySelector('.my-element');

if (document.body.attachShadow) {
  
  let shadow = el.attachShadow({ mode: 'open' }); // Allows JS access inside
  shadow.innerHTML = content;
  
} else {
  
  let newiframe = document.createElement('iframe');
  'srcdoc' in newiframe ?
    newiframe.srcdoc = content :
    newiframe.src = 'data:text/html;charset=UTF-8,' + content;
  
  let parent = el.parentNode;
  parent.replaceChild(newiframe, el);

}

TL;DR

  • Shadow DOM ist ziemlich cool.
  • Es ist in vielerlei Hinsicht mit einem iFrame vergleichbar, einschließlich der Stil-Einkapselung. Eingebettete Inhalte von Drittanbietern sind ein ziemlich guter Anwendungsfall.
  • Es ist möglich, es zu verwenden und gleichzeitig recht einfach auf einen iFrame zurückzufallen.
  • Es ist Teil der größeren Welt der Webkomponenten, aber Sie müssen sich nicht komplett darauf einlassen, wenn Sie nicht möchten.

Hier ist eine weitere einfache Demo (diesmal mit einem benutzerdefinierten Element), aber anstatt unsere eigene Rückunterstützung zu entwickeln, ist sie polygefüllt.