2017-07-12 2 views
1

Ich habe ein benutzerdefiniertes Element (ohne Shadow-DOM), das ich überall verwenden könnte, auch innerhalb eines anderen benutzerdefinierten Elements, das möglicherweise Shadow-DOM verwendet . Ich bin mir jedoch nicht sicher, wie ich die Stile an beiden Orten zum Laufen bringen kann.Verwenden eines benutzerdefinierten Shadow-DOM-Elements innerhalb und außerhalb des Schattens DOM

Zum Beispiel können sagen, dass ich ein einfaches fancy-button Element erstellen:

class fancyButton extends HTMLElement { 
 
    constructor() { 
 
    super(); 
 

 
    this.innerHTML = ` 
 
     <style> 
 
     fancy-button button { 
 
     padding: 10px 15px; 
 
     background: rgb(62,118,194); 
 
     color: white; 
 
     border: none; 
 
     border-radius: 4px 
 
     } 
 
     </style> 
 
     <button>Click Me</button>`; 
 
    } 
 
} 
 

 
customElements.define('fancy-button', fancyButton);
<fancy-button></fancy-button>

Innerhalb eines Schatten DOM-Element, das eingesetzt Style-Tag ermöglicht die fancy-button Arten zu arbeiten. Wenn diese Komponente jedoch außerhalb eines Schatten-DOM-Elements verwendet wird, wird das Stil-Tag bei jeder Verwendung des Elements dupliziert.

Wenn ich stattdessen das style-Tag als Teil der HTML-Importdatei hinzufüge, funktionieren die Stile nur außerhalb des Schatten-DOM, aber sie werden nur einmal deklariert.

<!-- fancy-button.html --> 
<style> 
fancy-button button { 
    padding: 10px 15px; 
    background: rgb(62,118,194); 
    color: white; 
    border: none; 
    border-radius: 4px 
} 
</style> 

<script> 
class fancyButton extends HTMLElement { 
    constructor() { 
    super(); 

    this.innerHTML = `<button>Click Me</button>`; 
    } 
} 

customElements.define('fancy-button', fancyButton); 
</script> 

Wie fügen Sie am besten benutzerdefinierte Elementstile hinzu, die sowohl innerhalb als auch außerhalb des Schatten-DOM verwendet werden können?

+1

Der beste Weg ist die erste Lösung, weil sie die einzige ist, die funktioniert. Eine andere Möglichkeit besteht darin, zu testen, ob Sie sich in einem Shadow-DOM befinden und den Stil bei Bedarf hinzufügen. – Supersharp

Antwort

1

So konnte ich dank Supersharp-Vorschlägen zur Überprüfung, ob wir im Schatten-DOM sind, eine Lösung finden.

Zuerst fügen Sie die Stile als Teil der Importdatei hinzu, sodass die Stile standardmäßig außerhalb des Schatten-DOM angewendet werden. Wenn dann Element zum DOM hinzugefügt wird, prüfen wir getRootNode(), um festzustellen, ob es zu einem ShadowRoot-Knoten hinzugefügt wurde. Wenn dies der Fall ist und die Stile nicht bereits in den Stamm eingefügt wurden, können wir die Stile manuell einfügen.

var div = document.createElement('div'); 
 
var shadow = div.attachShadow({mode: 'open'}); 
 
shadow.innerHTML = '<fancy-button></fancy-button>'; 
 

 
document.body.appendChild(div);
<style data-fs-dialog> 
 
    fancy-button button { 
 
    padding: 10px 15px; 
 
    background: rgb(62,118,194); 
 
    color: white; 
 
    border: none; 
 
    border-radius: 4px 
 
    } 
 
</style> 
 

 
<script> 
 
class fancyButton extends HTMLElement { 
 
    constructor() { 
 
    super(); 
 
    } 
 
    
 
    connectedCallback() { 
 
    this.innerHTML = `<button>Click Me</button>`; 
 
    
 
    var root = this.getRootNode(); 
 

 
    // In polyfilled browsers there is no shadow DOM so global styles still style 
 
    // the "fake" shadow DOM. We need to test for truly native support so we know 
 
    // when to inject styles into the shadow dom. The best way I've found to do that 
 
    // is to test the toString output of a shadowroot since `instanceof ShadowRoot` 
 
    // returns true when it's just a document-fragment in polyfilled browsers 
 
    if (root.toString() === '[object ShadowRoot]' && !root.querySelector('style[data-fs-dialog]')) { 
 
     var styles = document.querySelector('style[data-fs-dialog]').cloneNode(true); 
 
     root.appendChild(styles); 
 
    } 
 
    } 
 
} 
 

 
customElements.define('fancy-button', fancyButton); 
 
</script> 
 

 
<fancy-button></fancy-button>

Wenn alle Browser <link rel=stylesheet> im Schatten DOM, dann ist das Inline-Skript unterstützt in ein externes Stylesheet drehen kann als robdodson vorgeschlagen, und der Code ist ein bisschen sauberer.

1

Wahrscheinlich möchten Sie die Stile in eine separate CSS-Datei einfügen, die Sie zusammen mit dem JS Ihres Elements verkaufen. Wenn Sie jedoch das Element in das Shadow-DOM eines anderen Elements einfügen, funktionieren die Stile in diesem Bereich nicht. Aus diesem Grund ist es normalerweise am besten, nur eine Schattenwurzel zu erstellen und Ihre Stile dort einzufügen. Irgendein Grund warum du das nicht willst?

+0

Meistens ist es ein tiefes Tauchexperiment, um zu sehen, ob Sie benutzerdefinierte Elemente ohne Schatten-DOM erstellen können, die geteilt werden können (da sie leichter zu überschreiben sind und keine CSS-Variablen benötigen). Aber wenn das Formatieren des Elements Schatten-DOM benötigt, nur damit es im Schatten-DOM funktioniert, dann bin ich mir nicht sicher, wann Sie ein nicht-schattiertes DOM-Element schreiben möchten, was bedauerlich erscheint. –

Verwandte Themen