<ncss-container>
js/ncss-container.js kapselt ncss-Inhalte in einem echten Shadow-DOM-Baum, um sie innerhalb eines FREMDEN Frameworks/CSS-Systems (Bootstrap, UIkit, Tailwind, ein CMS-Theme, ...) laufen zu lassen, ohne dass Styles in beide Richtungen durchsickern.
Einbindung
<script src="js/ncss-container.js" defer></script>
<ncss-container src="dist/ncss.css">
<div class="ncss-card">
<div class="ncss-card-body">Isolierter Inhalt</div>
</div>
</ncss-container>
| Attribut | Zweck |
|---|---|
src | Pflicht (oder data-ncss-src auf dem Loader-<script> als Seiten-Default) - Pfad zu ncss.css, ganz normaler <link>, keine ncss-Sonderregel |
theme | Optional, zusätzliches Stylesheet, NACH src geladen - für einen Container mit anderer Markenfarbe/Radien/Schrift als die restliche Seite |
Zwei technische Voraussetzungen
1. Token-Isolation
ncss' Tokens sind in colors.css/tokens.css/theme.css/webawesome-bridge.css bewusst als :root, :host { ... } deklariert (statt nur :root) - :root trifft immer das echte Seiten-Wurzelelement, niemals einen Shadow Host; :host dagegen nur den Host-Knoten eines Shadow-Trees und ist außerhalb eines Shadow-Trees wirkungslos. Dieselbe Datei liefert dadurch, unverändert, eine komplett eigenständige Token-Kopie, sobald sie in einem Shadow Root statt am Seiten-<head> geladen wird - keine zweite, duplizierte Token-Datei, kein Build-Schritt. Per echtem Test bestätigt: ein .ncss-btn--primary im Container zeigt die korrekte Markenfarbe, obwohl die Host-Seite selbst gar kein ncss geladen hat.
2. Inhalts-Isolation
Der eigene Inhalt wird nicht per <slot> eingebunden, sondern beim Verbinden einmalig per JS in den Shadow Root verschoben (echte appendChild-Umhängung). Ein <slot> würde die Kind-Elemente nur im Shadow Root anzeigen - sie blieben aber Teil des Light DOM und dadurch weiterhin von den globalen Stylesheets der äußeren Seite getroffen (z.B. ein Framework-Reset oder !important-Regeln). Per echtem Test bestätigt: ein <slot>-basierter Button übernahm eine äußere !important-Regel unverändert, ein per Verschieben eingebetteter Button blieb komplett unberührt.
Kehrseite bewusst in Kauf genommen: kein automatisches Nachziehen bei späteren dynamischen DOM-Änderungen am Original-Markup - für einen fertig eingebetteten Inhaltsblock kein praktischer Nachteil.
Live-Demo: UIkit 3 + isolierter Container
Bidirektional getestet: eine komplette Seite auf UIkit 3 mit einem <ncss-container> samt Stacked Cards mitten drin. UIkits button/h1-h6-Reset erreicht den Container nicht, ncss' eigener Reset (* { margin: 0 } u.a.) beeinflusst UIkit-Inhalt vor/nach dem Container nicht. Auch scroll-gekoppelte Effekte (position:sticky, animation-timeline: view()) funktionieren normal über die Shadow-Grenze hinweg - reine Layout-/Rendering-Mechanik, von der DOM-/Style-Kapselung unberührt.
Demo: demo/uikit-integration.html.
Opt-in-Scripts funktionieren auch im Container
code-block.js, events.js, downloads.js, scroll-stack-fallback.js, hide-on-scroll-fallback.js und wa-close-on-scroll.js suchen ihre Elemente nicht mehr per einfachem document.querySelectorAll(...) (durchquert Shadow-Grenzen standardmäßig nicht), sondern per deepQueryAll() - steigt rekursiv in jeden offenen Shadow Root ab (also auch in jeden <ncss-container>) und verhält sich ohne Shadow DOM auf der Seite exakt wie querySelectorAll. code-block.js ruft dafür zusätzlich Prism.highlightElement() pro gefundenem Block statt des document-globalen Prism.highlightAll() auf.
Einbindung immer gleich, egal ob mit oder ohne <ncss-container> - einfach das jeweilige Script wie gewohnt auf der Seite laden, es findet seine Elemente unabhängig davon, ob sie in einem Shadow Root stecken. Einzige Ausnahme: wa-close-on-scroll.js läuft bei jedem Scroll-Event und sucht deshalb gezielt nur innerhalb <ncss-container>-Elementen statt eines vollen DOM-Walks (Performance), zusätzlich per requestAnimationFrame gedrosselt.