Cours Svelte et SvelteKit · Module 2: Composants

Les styles en Svelte

3 min de lecture ·
Dans cette leçon5

Les styles en Svelte sont scoped par défaut : ils ne fonctionnent qu'à l'intérieur du composant où ils sont définis. C'est comme un sort runique de protection !

Styles Scoped

<h1>Titre dans un composant</h1>

<style>
  /* Ce style s'applique UNIQUEMENT à ce composant */
  h1 {
    color: gold;
    font-size: 2rem;
  }
</style>

Svelte ajoute des attributs uniques aux éléments :

<!-- Résultat dans le navigateur -->
<h1 class="svelte-abc123">Titre dans un composant</h1>

Styles globaux

Parfois, tu as besoin de styles globaux. Utilise :global() :

<style>
  /* Uniquement dans ce composant */
  h1 {
    color: gold;
  }

  /* Globalement - partout dans l'application */
  :global(body) {
    margin: 0;
    font-family: 'Norse', serif;
  }

  /* Global à l'intérieur d'un sélecteur */
  .container :global(h1) {
    color: silver;
  }
</style>

Classes dynamiques

La directive class:

<script>
  let isActive = $state(true);
  let isWarrior = $state(true);
  let status = $state('ready');
</script>

<!-- Ajouter une classe sous condition -->
<div class:active={isActive}>
  Guerrier actif
</div>

<!-- Raccourci quand le nom de la classe = le nom de la variable -->
<div class:isWarrior>
  Guerrier
</div>

<!-- Plusieurs classes -->
<div
  class:active={isActive}
  class:warrior={isWarrior}
  class:status-ready={status === 'ready'}
>
  Viking
</div>

Un objet dans l'attribut class (Svelte 5.16+)

Depuis Svelte 5.16, l'attribut class accepte aussi un objet : la clé est le nom de la classe, et la valeur indique s'il faut l'ajouter. La documentation de Svelte recommande cette forme dans le nouveau code, tandis que la directive class: fonctionne toujours et que tu la croiseras dans beaucoup de projets :

<script>
  let isActive = $state(true);
  let isWarrior = $state(false);
</script>

<!-- Pareil que class:active={isActive} class:warrior={isWarrior} -->
<div class={{ active: isActive, warrior: isWarrior }}>
  Viking
</div>

<!-- Un tableau combine classes fixes et conditionnelles -->
<div class={['card', isActive && 'active']}>
  Carte de guerrier
</div>

Attribut class dynamique

<script>
  let type = $state('warrior');
  let isActive = $state(false);
</script>

<div class="viking {type}">
  Type : {type}
</div>

<!-- Expression ternaire -->
<div class={isActive ? 'active' : 'inactive'}>
  Statut
</div>

Variables CSS (Custom Properties)

<script>
  let primaryColor = $state('#d4af37');
  let size = $state(24);
</script>

<div class="viking-badge" style="--color: {primaryColor}; --size: {size}px">
  <span>ᛏ</span>
</div>

<style>
  .viking-badge {
    color: var(--color);
    font-size: var(--size);
    padding: calc(var(--size) / 2);
  }
</style>

Styles inline conditionnels

<script>
  let health = $state(75);
</script>

<div
  class="health-bar"
  style="width: {health}%; background: {health > 50 ? 'green' : 'red'}"
>
  {health}%
</div>
Code de cette leçon : App.svelte
<script>
  // Styles in Svelte - isolated like the nine worlds
  let isElite = $state(true);
  let theme = $state('dark');
</script>

<div class="demo" class:elite={isElite}>
  <h1>Styles in Svelte</h1>

  <p>Styles are <strong>scoped</strong> by default!</p>

  <div class="controls">
    <label>
      <input type="checkbox" bind:checked={isElite} />
      Elite warrior (class:elite)
    </label>

    <select bind:value={theme}>
      <option value="dark">Dark</option>
      <option value="light">Light</option>
    </select>
  </div>

  <div class="card {theme}">
    <p>Dynamic class: {theme}</p>
  </div>
</div>

<style>
  .demo {
    font-family: 'Georgia', serif;
    max-width: 500px;
    margin: 2rem auto;
    padding: 2rem;
    background: #1a0f0a;
    color: #e8d5b7;
    border-radius: 8px;
  }

  h1 {
    color: #d4af37;
  }

  /* Conditional class */
  .demo.elite {
    border: 3px solid #ffd700;
    box-shadow: 0 0 20px rgba(255, 215, 0, 0.3);
  }

  .controls {
    margin: 1rem 0;
    padding: 1rem;
    background: rgba(0,0,0,0.3);
    border-radius: 4px;
  }

  label {
    display: block;
    margin-bottom: 0.5rem;
  }

  select {
    padding: 0.5rem;
    background: #2c1810;
    color: #e8d5b7;
    border: 1px solid #d4af37;
    border-radius: 4px;
  }

  .card {
    padding: 1rem;
    border-radius: 4px;
    margin-top: 1rem;
  }

  .card.dark {
    background: #0a0a0a;
    color: #e8d5b7;
  }

  .card.light {
    background: #f5f5f5;
    color: #1a1a1a;
  }
</style>

Entrées de la documentation utilisées dans cette leçon

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Que signifie le fait que les styles dans Svelte sont « scoped » (isolés) ?

  2. 2. Comment définir un style global dans un composant Svelte ?

  3. 3. Comment utiliser la syntaxe raccourcie class: quand le nom de la classe est identique au nom de la variable ?

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète le code pour que la classe « active » soit ajoutée quand isActive vaut true

Articles utiles