Back

Créer des composants web flexibles avec les slots

Créer des composants web flexibles avec les slots

Les composants web sont puissants, mais transmettre du contenu complexe peut rapidement devenir désordonné. Imaginez essayer de créer un composant carte qui nécessite une image d’en-tête, un titre, du texte de corps et des boutons d’action—entasser tout cela dans des attributs créerait un désordre illisible. C’est là que les slots interviennent, transformant la façon dont nous construisons des composants UI flexibles et réutilisables.

Cet article vous montre comment utiliser les slots pour créer des composants web qui acceptent du contenu riche tout en maintenant un balisage propre et déclaratif. Vous apprendrez comment les slots fonctionnent avec le shadow DOM, comment implémenter à la fois les slots par défaut et nommés, et comment styliser efficacement le contenu slotté.

Points clés à retenir

  • Les slots permettent aux composants web d’accepter du contenu HTML complexe au lieu de tout entasser dans des attributs
  • Les slots nommés offrent un contrôle précis sur le placement du contenu, tandis que les slots par défaut gèrent le contenu non spécifié
  • Le pseudo-élément ::slotted() permet de styliser le contenu slotté depuis le shadow DOM
  • Les slots maintiennent d’excellentes performances en projetant les nœuds DOM plutôt qu’en les copiant

Le problème : contenu complexe dans les composants web

Les attributs HTML traditionnels fonctionnent bien pour des valeurs simples :

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

Mais que se passe-t-il quand vous devez transmettre du contenu structuré ? Considérez un composant carte :

<!-- Cela devient rapidement désordonné -->
<product-card 
  title="Casque Premium"
  description="<p>Audio haute qualité avec <strong>réduction de bruit</strong></p>"
  price="299€"
  button-text="Ajouter au panier"
  image-src="headphones.jpg">
</product-card>

Cette approche présente plusieurs problèmes :

  • Le HTML dans les attributs nécessite un échappement
  • Les mises en page complexes deviennent impossibles à gérer
  • L’utilisation du composant ne correspond pas aux patterns HTML standards

Comment fonctionnent les slots : les bases

Les slots vous permettent de passer du contenu directement entre les balises de votre composant, comme les éléments HTML natifs. Voici comment ils transforment l’exemple précédent :

<product-card>
  <h2 slot="title">Casque Premium</h2>
  <div slot="description">
    <p>Audio haute qualité avec <strong>réduction de bruit</strong></p>
  </div>
  <button slot="action">Ajouter au panier</button>
</product-card>

À l’intérieur de votre composant web, vous définissez où ce contenu apparaît en utilisant l’élément <slot> :

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">Produit sans titre</slot>
        <slot name="description">Aucune description disponible</slot>
        <slot name="action"></slot>
      </div>
    `;
  }
}

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

Le contenu à l’intérieur de chaque balise <slot> sert de contenu de fallback—il apparaît quand aucun contenu slotté correspondant n’est fourni.

Slots par défaut vs slots nommés

Les composants web supportent deux types de slots :

Slots par défaut

Tout contenu sans attribut slot va dans le slot par défaut (sans nom) :

// Définition du composant
shadow.innerHTML = `
  <article>
    <h2>Titre de l'article</h2>
    <slot></slot> <!-- Slot par défaut -->
  </article>
`;
<!-- Utilisation -->
<my-article>
  <p>Ce paragraphe va dans le slot par défaut</p>
  <p>Celui-ci aussi</p>
</my-article>

Slots nommés

Les slots nommés vous donnent un contrôle précis sur le placement du contenu :

// Définition du composant
shadow.innerHTML = `
  <div class="profile">
    <slot name="avatar"></slot>
    <div class="info">
      <slot name="name">Anonyme</slot>
      <slot name="bio">Aucune bio fournie</slot>
    </div>
  </div>
`;
<!-- Utilisation -->
<user-profile>
  <img slot="avatar" src="jane.jpg" alt="Jane">
  <h3 slot="name">Jane Développeuse</h3>
  <p slot="bio">Créer d'incroyables composants web</p>
</user-profile>

Exemple concret : construire un composant carte flexible

Construisons un composant carte prêt pour la production qui démontre les slots en action :

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;
        }
        
        /* Masquer les sections vides quand aucun contenu slotté */
        .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);

Maintenant vous pouvez l’utiliser avec n’importe quelle structure de contenu :

<flex-card>
  <h2 slot="header">Détails du produit</h2>
  
  <p>Le contenu principal va dans le slot par défaut</p>
  <ul>
    <li>Fonctionnalité 1</li>
    <li>Fonctionnalité 2</li>
  </ul>
  
  <div slot="footer">
    <button>Acheter maintenant</button>
    <button>Sauvegarder pour plus tard</button>
  </div>
</flex-card>

Styliser le contenu slotté

Styliser le contenu slotté nécessite des pseudo-éléments spéciaux :

Utiliser ::slotted()

Le pseudo-élément ::slotted() cible les éléments placés dans les slots :

/* À l'intérieur du shadow DOM de votre composant */
::slotted(h2) {
  color: #333;
  margin: 0;
}

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

/* Cibler des slots spécifiques */
::slotted([slot="header"]) {
  font-size: 1.2em;
}

Limitation importante : ::slotted() ne cible que l’élément slotté direct, pas ses enfants.

Utiliser :host

La pseudo-classe :host stylise le composant lui-même :

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

/* Styliser selon les attributs */
:host([variant="primary"]) {
  border-color: #007bff;
}

/* Styliser selon le contexte */
:host-context(.dark-theme) {
  background: #333;
  color: white;
}

Considérations de performance

Les slots sont très performants car ils ne copient pas les nœuds DOM—ils les projettent. Le contenu slotté reste dans le light DOM mais se rend comme s’il faisait partie du shadow DOM. Cela signifie :

  • Les écouteurs d’événements sur le contenu slotté continuent de fonctionner
  • Les styles du document peuvent toujours s’appliquer (sauf s’ils sont bloqués par le shadow DOM)
  • Le navigateur ne duplique pas les nœuds en mémoire

Support navigateur et polyfills

Les slots des composants web ont un excellent support dans les navigateurs modernes. Pour les navigateurs plus anciens, considérez l’utilisation des polyfills Web Components.

Conclusion

Les slots transforment les composants web de simples éléments personnalisés en blocs de construction puissants et flexibles pour une UI réutilisable. En séparant la structure du contenu, ils vous permettent de créer des composants à la fois hautement personnalisables et faciles à utiliser. Que vous construisiez un système de design ou organisiez mieux votre code, maîtriser les slots est essentiel pour le développement moderne de composants web.

Prêt à créer des composants web plus flexibles ? Commencez par refactoriser l’un de vos composants existants pour utiliser les slots. Concentrez-vous sur les zones où vous transmettez actuellement du HTML via des attributs ou utilisez des structures de propriétés complexes. Votre futur vous (et votre équipe) vous remercieront pour le code plus propre et plus maintenable.

FAQ

Les props (attributs) sont idéales pour des valeurs simples comme les chaînes, nombres ou booléens. Les slots excellent à accepter du contenu HTML complexe, plusieurs éléments ou toute structure de balisage. Utilisez les props pour la configuration et les slots pour le contenu.

Oui, vous pouvez modifier le contenu slotté à tout moment puisqu'il reste dans le light DOM. Sélectionnez simplement les éléments avec des attributs slot et mettez-les à jour comme n'importe quels autres éléments DOM. Les changements se reflètent immédiatement dans le composant rendu.

Le contenu slotté reste dans le light DOM, le rendant entièrement accessible aux moteurs de recherche et aux lecteurs d'écran. C'est un avantage majeur par rapport au contenu shadow DOM, qui peut être plus difficile à indexer pour les crawlers.

Tous les éléments avec le même nom de slot apparaissent dans ce slot dans l'ordre du document. C'est utile pour créer des mises en page flexibles où les utilisateurs peuvent ajouter plusieurs éléments à une seule zone de slot.

Non, les slots nécessitent le shadow DOM pour fonctionner. Ils sont spécifiquement conçus pour projeter le contenu light DOM dans les templates shadow DOM. Sans shadow DOM, vous devriez utiliser différents patterns de distribution de contenu.

Listen to your bugs 🧘, with OpenReplay

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