Back

Flexible Web Components mit Slots entwickeln

Flexible Web Components mit Slots entwickeln

Web Components sind mächtig, aber das Übergeben komplexer Inhalte kann schnell unübersichtlich werden. Stellen Sie sich vor, Sie möchten eine Card-Komponente erstellen, die ein Header-Bild, einen Titel, Fließtext und Action-Buttons benötigt – all das in Attribute zu packen würde ein unlesbares Durcheinander schaffen. Hier kommen Slots ins Spiel und transformieren die Art, wie wir flexible, wiederverwendbare UI-Komponenten entwickeln.

Dieser Artikel zeigt Ihnen, wie Sie Slots verwenden, um Web Components zu erstellen, die reichhaltige Inhalte akzeptieren und dabei sauberes, deklaratives Markup beibehalten. Sie lernen, wie Slots mit dem Shadow DOM funktionieren, wie Sie sowohl Default- als auch Named Slots implementieren und wie Sie Slot-Inhalte effektiv stylen.

Wichtige Erkenntnisse

  • Slots ermöglichen es Web Components, komplexe HTML-Inhalte zu akzeptieren, anstatt alles in Attribute zu packen
  • Named Slots bieten präzise Kontrolle über die Inhaltsplatzierung, während Default Slots nicht spezifizierten Inhalt handhaben
  • Das ::slotted() Pseudo-Element ermöglicht das Styling von Slot-Inhalten aus dem Shadow DOM heraus
  • Slots bieten exzellente Performance, da sie DOM-Knoten projizieren anstatt sie zu kopieren

Das Problem: Komplexe Inhalte in Web Components

Traditionelle HTML-Attribute funktionieren gut für einfache Werte:

<user-avatar src="profile.jpg" size="large"></user-avatar>

Aber was passiert, wenn Sie strukturierte Inhalte übergeben müssen? Betrachten Sie eine Card-Komponente:

<!-- Das wird schnell unübersichtlich -->
<product-card 
  title="Premium Kopfhörer"
  description="<p>Hochwertige Audioqualität mit <strong>Geräuschunterdrückung</strong></p>"
  price="299€"
  button-text="In den Warenkorb"
  image-src="headphones.jpg">
</product-card>

Dieser Ansatz hat mehrere Probleme:

  • HTML innerhalb von Attributen erfordert Escaping
  • Komplexe Layouts werden unmöglich zu verwalten
  • Die Verwendung der Komponente entspricht nicht den Standard-HTML-Mustern

Wie Slots funktionieren: Die Grundlagen

Slots ermöglichen es Ihnen, Inhalte direkt zwischen den Tags Ihrer Komponente zu übergeben, genau wie bei nativen HTML-Elementen. So transformieren sie das vorherige Beispiel:

<product-card>
  <h2 slot="title">Premium Kopfhörer</h2>
  <div slot="description">
    <p>Hochwertige Audioqualität mit <strong>Geräuschunterdrückung</strong></p>
  </div>
  <button slot="action">In den Warenkorb</button>
</product-card>

Innerhalb Ihrer Web Component definieren Sie mit dem <slot>-Element, wo dieser Inhalt erscheint:

class ProductCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    
    shadow.innerHTML = `
      <style>
        .card {
          border: 1px solid #ddd;
          border-radius: 8px;
          padding: 16px;
        }
      </style>
      <div class="card">
        <slot name="title">Unbenanntes Produkt</slot>
        <slot name="description">Keine Beschreibung verfügbar</slot>
        <slot name="action"></slot>
      </div>
    `;
  }
}

customElements.define('product-card', ProductCard);

Der Inhalt innerhalb jedes <slot>-Tags dient als Fallback-Inhalt – er erscheint, wenn kein passender Slot-Inhalt bereitgestellt wird.

Default vs Named Slots

Web Components unterstützen zwei Arten von Slots:

Default Slots

Jeder Inhalt ohne slot-Attribut geht in den Default-Slot (unbenannten Slot):

// Komponenten-Definition
shadow.innerHTML = `
  <article>
    <h2>Artikel-Titel</h2>
    <slot></slot> <!-- Default Slot -->
  </article>
`;
<!-- Verwendung -->
<my-article>
  <p>Dieser Absatz geht in den Default Slot</p>
  <p>Dieser auch</p>
</my-article>

Named Slots

Named Slots geben Ihnen präzise Kontrolle über die Inhaltsplatzierung:

// Komponenten-Definition
shadow.innerHTML = `
  <div class="profile">
    <slot name="avatar"></slot>
    <div class="info">
      <slot name="name">Anonym</slot>
      <slot name="bio">Keine Biografie angegeben</slot>
    </div>
  </div>
`;
<!-- Verwendung -->
<user-profile>
  <img slot="avatar" src="jane.jpg" alt="Jane">
  <h3 slot="name">Jane Developer</h3>
  <p slot="bio">Entwickelt großartige Web Components</p>
</user-profile>

Praxisbeispiel: Entwicklung einer flexiblen Card-Komponente

Lassen Sie uns eine produktionsreife Card-Komponente entwickeln, die Slots in Aktion demonstriert:

class FlexCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    
    shadow.innerHTML = `
      <style>
        :host {
          display: block;
          border: 1px solid #e0e0e0;
          border-radius: 8px;
          overflow: hidden;
          background: white;
        }
        
        .header {
          padding: 16px;
          border-bottom: 1px solid #e0e0e0;
        }
        
        .content {
          padding: 16px;
        }
        
        .footer {
          padding: 16px;
          background: #f5f5f5;
        }
        
        /* Leere Bereiche ausblenden, wenn kein Slot-Inhalt vorhanden */
        .header:empty {
          display: none;
        }
        
        .footer:empty {
          display: none;
        }
      </style>
      
      <div class="header">
        <slot name="header"></slot>
      </div>
      <div class="content">
        <slot></slot>
      </div>
      <div class="footer">
        <slot name="footer"></slot>
      </div>
    `;
  }
}

customElements.define('flex-card', FlexCard);

Jetzt können Sie sie mit jeder beliebigen Inhaltsstruktur verwenden:

<flex-card>
  <h2 slot="header">Produktdetails</h2>
  
  <p>Hauptinhalt geht in den Default Slot</p>
  <ul>
    <li>Feature 1</li>
    <li>Feature 2</li>
  </ul>
  
  <div slot="footer">
    <button>Jetzt kaufen</button>
    <button>Für später speichern</button>
  </div>
</flex-card>

Styling von Slot-Inhalten

Das Styling von Slot-Inhalten erfordert spezielle Pseudo-Elemente:

Verwendung von ::slotted()

Das ::slotted() Pseudo-Element zielt auf Elemente ab, die in Slots platziert wurden:

/* Innerhalb des Shadow DOM Ihrer Komponente */
::slotted(h2) {
  color: #333;
  margin: 0;
}

::slotted(button) {
  background: #007bff;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
}

/* Spezifische Slots ansprechen */
::slotted([slot="header"]) {
  font-size: 1.2em;
}

Wichtige Einschränkung: ::slotted() zielt nur auf das direkte Slot-Element ab, nicht auf dessen Kinder.

Verwendung von :host

Die :host Pseudo-Klasse stylt die Komponente selbst:

:host {
  display: block;
  margin: 16px 0;
}

/* Styling basierend auf Attributen */
:host([variant="primary"]) {
  border-color: #007bff;
}

/* Styling basierend auf Kontext */
:host-context(.dark-theme) {
  background: #333;
  color: white;
}

Performance-Überlegungen

Slots sind hochperformant, da sie DOM-Knoten nicht kopieren – sie projizieren sie. Der Slot-Inhalt verbleibt im Light DOM, wird aber gerendert, als wäre er Teil des Shadow DOM. Das bedeutet:

  • Event Listener auf Slot-Inhalten funktionieren weiterhin
  • Styles aus dem Dokument können weiterhin angewendet werden (außer sie werden vom Shadow DOM blockiert)
  • Der Browser dupliziert keine Knoten im Speicher

Browser-Unterstützung und Polyfills

Web Components Slots haben exzellente Browser-Unterstützung in modernen Browsern. Für ältere Browser sollten Sie die Web Components Polyfills in Betracht ziehen.

Fazit

Slots transformieren Web Components von einfachen Custom Elements zu mächtigen, flexiblen Bausteinen für wiederverwendbare UI. Durch die Trennung von Struktur und Inhalt ermöglichen sie es Ihnen, Komponenten zu erstellen, die sowohl hochgradig anpassbar als auch einfach zu verwenden sind. Ob Sie ein Design System entwickeln oder Ihren Code besser organisieren – die Beherrschung von Slots ist essentiell für die moderne Web Component-Entwicklung.

Bereit, flexiblere Web Components zu erstellen? Beginnen Sie damit, eine Ihrer bestehenden Komponenten zu refactoring, um Slots zu verwenden. Konzentrieren Sie sich auf Bereiche, wo Sie derzeit HTML durch Attribute übergeben oder komplexe Prop-Strukturen verwenden. Ihr zukünftiges Ich (und Ihr Team) wird Ihnen für den saubereren, wartbareren Code danken.

Häufig gestellte Fragen

Props (Attribute) eignen sich am besten für einfache Werte wie Strings, Zahlen oder Booleans. Slots sind hervorragend geeignet für komplexe HTML-Inhalte, mehrere Elemente oder beliebige Markup-Strukturen. Verwenden Sie Props für Konfiguration und Slots für Inhalte.

Ja, Sie können Slot-Inhalte jederzeit ändern, da sie im Light DOM verbleiben. Selektieren Sie einfach die Elemente mit Slot-Attributen und aktualisieren Sie sie wie jede anderen DOM-Elemente. Die Änderungen werden sofort in der gerenderten Komponente sichtbar.

Slot-Inhalte verbleiben im Light DOM und sind daher vollständig für Suchmaschinen und Screen Reader zugänglich. Das ist ein großer Vorteil gegenüber Shadow DOM-Inhalten, die für Crawler schwerer zu indexieren sein können.

Alle Elemente mit demselben Slot-Namen erscheinen in diesem Slot in Dokumentenreihenfolge. Das ist nützlich für flexible Layouts, wo Benutzer mehrere Elemente zu einem einzigen Slot-Bereich hinzufügen können.

Nein, Slots benötigen Shadow DOM um zu funktionieren. Sie sind speziell dafür entwickelt, Light DOM-Inhalte in Shadow DOM-Templates zu projizieren. Ohne Shadow DOM müssten Sie andere Content-Distribution-Muster verwenden.

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers