CSS-Kapselung ohne Shadow DOM: wie unsere Widgets es lösen und wo es hakt
Widget-Storm-Widgets landen ohne Shadow DOM direkt in Ihrer Seite. So bleibt ihr CSS bei sich, so sieht das im Browser aus, und in diesen Fällen hakt es.
Beim DevHunt-Launch kam eine gute Frage. Wenn Widgets direkt in die Seite rendern, wie verhindert man, dass ihr CSS auf den Rest der Seite übergreift? Shadow DOM oder etwas Leichteres? Und was passiert, wenn es schiefgeht?
Kurz gesagt nutzen wir kein Shadow DOM. Im ganzen Code von Widget Storm gibt es kein attachShadow und kein Custom Element. Hier steht, was wir stattdessen machen, wie es im Browser aussieht und wo es hakt. Wer noch zwischen iframe und direkter Einbettung schwankt, findet den Vergleich in Native Widgets vs. iframe-Embeds.
Warum kein Shadow DOM
Shadow DOM trennt sauber. Was drin ist, bleibt drin, und was draußen ist, kommt nicht hinein. Für viele Komponenten ist das richtig.
Für unsere Widgets ist es das Falsche. Ein Widget soll aussehen wie ein Teil Ihrer Seite. Hinter einem Shadow Root kommt Ihr Stylesheet aber nicht mehr an das Widget heran. Jede Stelle, die Sie anpassen wollen, müssten wir einzeln über CSS-Variablen oder ::part freigeben. Und wer serverseitig rendert, muss den Shadow Root zusätzlich im HTML deklarieren.
Deshalb lebt ein Widget bei uns ganz normal in Ihrem DOM, und Ihr CSS gilt dort auch.
Wie das CSS des Widgets bei sich bleibt
Dafür sorgen zwei Konventionen. Eine Sandbox ist keine davon.
Die erste ist ein Platzhalter. Der Autor eines Widgets schreibt ##self##, und vor der Auslieferung ersetzen wir ihn durch den Namen des Widgets und einen Hash der Instanz. Aus dieser Regel
.##self## .title { font-weight: 600; }wird im Browser zum Beispiel diese:
.wg_countdownb3e2705351409f2245a80616cb683a45 .title { font-weight: 600; }Den Namen haben wir nicht erfunden. So heißt unser Countdown, wenn Sie ihn ohne Parameter per Script-Tag einbinden. Binden Sie ihn auf derselben Seite ein zweites Mal genauso ein, bekommt die zweite Kopie …cb683a45_2. Das gilt für CSS, HTML und JavaScript gleichermaßen. Zwei gleiche Widgets kommen sich also nicht in die Quere.
Die zweite Konvention ist ein fester Präfix. Unser Support-Chat setzt wg-ch vor jede Regel. Kein Selektor darin trifft ein einfaches button oder p auf Ihrer Seite.
Beim JavaScript gilt dasselbe. Jedes unserer Widgets sucht nur nach Elementen mit seinem eigenen Namen, der Chat nur nach seinen eigenen wg-ch-Containern. Eine allgemeine Klasse Ihrer Seite fasst keines an.
Wo es hakt
Ein Autor kann trotzdem eine globale Regel schreiben. Steht im CSS eines Widgets button { … }, trifft das jeden Button Ihrer Seite. Verhindern können wir das nicht. Die Kapselung hält nur, wenn jeder Selektor den Platzhalter oder einen Präfix trägt. Bei unseren eigenen Widgets ist das so. Bei einem Widget eines anderen Autors müssen Sie es prüfen.
Serverseitig teilen sich Kopien einen Namen, solange Sie keinen vergeben. Ohne eigene ID heißen alle Kopien eines Widgets auf dem Server gleich, auch mit verschiedenen Parametern. Sollen sie verschieden aussehen, geben Sie jeder eine eigene ID als fünftes Argument von $wg->get(). Das funktioniert ab Handler-Version 4.3, die steht oben in der wghandler.php. Ist Ihre älter, laden Sie sie in der Station neu herunter.
Ihr CSS wirkt im Widget, und das ist gewollt. Eine breite Regel wie div { padding: 2rem } landet auch dort. Unser Chat setzt deshalb box-sizing, Schriftgrößen, Zeilenhöhe und Abstände selbst, statt sie von Ihrer Seite zu erben. Gegen jede Regel kann sich ein Widget trotzdem nicht wehren.
Wenn Sie selbst Widgets schreiben
Diese vier Punkte halten Ihr Widget aus fremden Seiten heraus:
- Jeder Selektor beginnt mit
.##self##oder einem eigenen Präfix. Kein einfachesbutton,poder*. - Das JavaScript sucht nur im eigenen Container, etwa mit
document.querySelectorAll('[data-wg-self="##self##"]'), und nie mitdocument.querySelector('.title'). - Was das Layout braucht, setzt das Widget selbst:
box-sizing, Schriftgröße, Zeilenhöhe. - Wer ein Widget mehrfach auf dem Server einbindet, gibt jeder Kopie eine eigene ID als fünftes Argument.
Was Sie dafür bekommen
Das Widget übernimmt Ihre Schriften. Sie färben es mit Ihrem eigenen Stylesheet um, ohne eine API zu lernen. Serverseitig gerendert steht es schon im ersten HTML und wartet nicht auf JavaScript. Und es gibt kein iframe, dessen Höhe, Scrollen und Zustand Sie nachführen müssten.
Für fremden Code, dem Sie nicht trauen, sind Shadow DOM oder ein iframe der richtige Weg. Für Widgets, die wie ein Teil Ihrer Seite wirken sollen, halten wir eine strikte Namenskonvention für den besseren Kompromiss.
Kennen Sie einen Fall, in dem das richtig schiefgeht? Schreiben Sie uns an info@widget-storm.de.
Widget Storm ausprobieren
Die Widgets laufen als Live-Demo direkt auf der Seite. Öffentliche Widgets können registrierte Nutzer frei in eigene Projekte einbinden.
Widgets ansehen Support-Chat ohne iframe: 4,99 € einmalig
Gesamtpreis · gemäß § 19 UStG keine USt