Back

Comment implémenter le glisser-déposer dans Svelte

Comment implémenter le glisser-déposer dans Svelte

Le glisser-déposer semble simple jusqu’à ce que vous essayiez de le construire. Le navigateur vous fournit une API native, mais elle présente de vraies limitations : pas d’animations fluides, support tactile incohérent et comportement imprévisible selon les navigateurs. Si vous avez déjà vu des éléments se positionner maladroitement lors du dépôt, vous connaissez le problème.

Ce guide couvre deux approches pratiques pour implémenter le glisser-déposer dans Svelte — en utilisant l’API native HTML5 et en utilisant une bibliothèque — afin que vous puissiez choisir l’outil adapté à ce que vous construisez réellement.

Points clés à retenir

  • L’API native HTML5 Drag and Drop fonctionne pour le réordonnancement simple de listes sans aucune dépendance, mais manque d’animations fluides, de support tactile et de comportement cohérent entre navigateurs.
  • Les runes Svelte 5 ($state()) et la syntaxe d’attribut ondragstart simplifient le glisser-déposer réactif par rapport à Svelte 3/4.
  • Pour un glisser-déposer animé, multi-listes, tactile ou accessible, svelte-dnd-action est un choix de bibliothèque pratique.
  • Les événements de glissement sont côté client uniquement — dans SvelteKit avec SSR, protégez la logique de glissement avec onMount ou une vérification browser.

Comprendre les deux approches

Avant d’écrire du code, il est utile de comprendre ce entre quoi vous choisissez.

L’API native HTML5 Drag and Drop utilise des événements intégrés au navigateur : dragstart, dragover, dragenter, dragleave et drop. Elle ne nécessite aucune dépendance et fonctionne bien pour les cas d’usage simples. Le compromis est que les animations nécessitent un travail manuel, le support tactile est incohérent selon les appareils, et le retour visuel pendant le glissement est limité. Vous pouvez en savoir plus sur l’API dans la documentation MDN Drag and Drop.

Les solutions basées sur des bibliothèques comme svelte-dnd-action ou Neodrag gèrent les parties difficiles — animations FLIP fluides, support tactile et interactions accessibles — prêtes à l’emploi. Elles ajoutent un léger coût en termes de bundle mais économisent un temps d’implémentation significatif pour tout ce qui dépasse une liste triable basique.

Implémenter le glisser-déposer dans Svelte 5 avec l’API native

Voici un exemple propre de réordonnancement de liste unique utilisant la syntaxe des runes Svelte 5 :

<script>
  let items = $state(['Svelte', 'SvelteKit', 'Vite', 'TypeScript']);
  let dragIndex = $state(null);

  function handleDragStart(event, index) {
    dragIndex = index;
    event.dataTransfer.effectAllowed = 'move';
  }

  function handleDragOver(event, index) {
    event.preventDefault();
    if (dragIndex === null || dragIndex === index) return;

    const updated = [...items];
    const [moved] = updated.splice(dragIndex, 1);
    updated.splice(index, 0, moved);

    items = updated;
    dragIndex = index;
  }

  function handleDragEnd() {
    dragIndex = null;
  }
</script>

<ul>
  {#each items as item, index (item)}
    <li
      draggable="true"
      class:dragging={dragIndex === index}
      ondragstart={(e) => handleDragStart(e, index)}
      ondragover={(e) => handleDragOver(e, index)}
      ondragend={handleDragEnd}
    >
      {item}
    </li>
  {/each}
</ul>

<style>
  li {
    padding: 10px 16px;
    margin: 6px 0;
    background: #f1f1f1;
    cursor: grab;
    list-style: none;
    border-radius: 4px;
  }
  .dragging {
    opacity: 0.4;
  }
</style>

Quelques points à noter concernant ce pattern Svelte 5 :

  • $state() remplace les anciennes déclarations de variables réactives de Svelte 3/4.
  • Svelte 5 supporte également la syntaxe d’attribut ondragstart en plus de la directive d’événement traditionnelle on:dragstart.
  • La liste se met à jour pendant le glissement (sur dragover), pas seulement au dépôt — cela donne aux utilisateurs un retour visuel en temps réel.

Note SvelteKit : Les événements de glissement sont côté client uniquement. Si vous utilisez SvelteKit avec SSR, enveloppez toute logique liée au glissement dans onMount ou protégez-la avec une vérification browser depuis $app/environment.

Quand utiliser svelte-dnd-action à la place

L’approche native fonctionne pour les scénarios simples de réordonnancement de liste. Mais dès que vous avez besoin de l’un des éléments suivants, utilisez svelte-dnd-action :

  • Animations FLIP fluides entre les positions de liste
  • Glisser-déposer multi-listes (tableaux de type Kanban)
  • Support tactile et mobile sans code supplémentaire
  • Interactions clavier accessibles intégrées

Le pattern svelte-dnd-action est simple — vous appliquez une action use:dndzone à votre conteneur, passez votre tableau d’éléments, et gérez les événements consider et finalize pour mettre à jour l’état. Chaque élément nécessite une propriété id unique. Associez-le à l’animation flip intégrée de Svelte et vous obtenez des interactions de glissement de qualité production en moins de 20 lignes.

BesoinUtiliser
Réordonnancement simple de liste, sans animationsAPI native
Animations fluides, multi-listes, tactilesvelte-dnd-action
Glissement libre d’élémentsNeodrag

Conclusion

Pour un réordonnancement basique de liste en glisser-déposer dans Svelte, l’API native du navigateur avec les runes Svelte 5 vous permet d’y arriver sans dépendances. Pour tout ce qui est plus complexe — tableaux Kanban animés, support tactile ou interactions accessibles — svelte-dnd-action est le choix pratique. Commencez par l’approche native pour comprendre les mécanismes, puis passez à une bibliothèque lorsque vos exigences le demandent.

FAQ

Pas de manière fiable. Le support des événements de glissement sur les appareils tactiles est incohérent selon les navigateurs mobiles. Pour supporter correctement le mobile, vous avez besoin soit d'un polyfill comme mobile-drag-drop, soit d'une bibliothèque telle que svelte-dnd-action qui gère nativement les interactions tactiles.

Oui. svelte-dnd-action fonctionne avec Svelte 5. Vous déclarez votre tableau d'éléments avec $state() et le mettez à jour dans les gestionnaires d'événements consider et finalize. La directive use:dndzone reste la même. Assurez-vous simplement que chaque élément de votre tableau possède une propriété id unique pour que la bibliothèque puisse suivre correctement les éléments.

Le navigateur génère une image fantôme par défaut à partir de l'apparence de l'élément glissé. Vous avez un contrôle limité sur cela avec l'API native. Vous pouvez la personnaliser en utilisant event.dataTransfer.setDragImage() pour fournir un élément personnalisé ou un instantané canvas, mais pour un contrôle visuel complet pendant le glissement, une bibliothèque comme svelte-dnd-action ou Neodrag est plus adaptée.

Le glisser-déposer multi-listes avec l'API native nécessite de suivre manuellement les conteneurs source et cible, ce qui devient rapidement complexe. svelte-dnd-action simplifie cela en vous permettant d'appliquer use:dndzone à chaque conteneur de liste et de partager le même type d'élément entre les zones. Les éléments se déplacent automatiquement entre les listes lorsqu'ils sont glissés d'un conteneur à l'autre.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay