Hover✨ Premium

Elastic Drag

Élément draggable à retour élastique : tirez l'objet dans n'importe quelle direction, relâchez, il oscille et revient au centre par ressort JS.

JSDragSpring

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Hover comprend 48 effets, dont 5 gratuits. Découvrir la catégorie →

3 exemples d'usage

Composant de tutoriel drag-and-drop — guide d'apprentissage d'un ERP de gestion d'entrepôt — Elastic Drag exemple 1

① Composant de tutoriel drag-and-drop — guide d'apprentissage d'un ERP de gestion d'entrepôt

QuandLe tutoriel montre comment déplacer un article entre zones ; l'élément de démo revient élastiquement à l'origine si on le lâche hors de la zone cible, illustrant la notion de « zone de dépôt ».
PourquoiUn retour élastique après mauvais placement enseigne visuellement la cible d'un drag-and-drop — l'utilisateur comprend qu'il a lâché au mauvais endroit sans message d'erreur.
RéglagesZone 540×360 px, objet 100×60 px étiqueté « Article → Zone B ». La zone de dépôt cible est mise en évidence (couleur différente) pendant le drag (ajouter une classe via mousemove).
Curseur de tombola en ligne — espace animations d'un comité d'entreprise — Elastic Drag exemple 2

② Curseur de tombola en ligne — espace animations d'un comité d'entreprise

QuandUn cube « Tirez-moi ! » peut être tiré dans n'importe quelle direction puis relâché ; il rebondit et se recentre, créant un moment de tension physique avant le tirage au sort.
PourquoiLe retour élastique après relâchement crée un sentiment de tension et de relâchement qui rend le tirage plus physique et ludique — un micro-moment engageant.
RéglagesObjet carré 120×120 px, design « dé de jeu ». Force du ressort augmentée (0.2) pour des oscillations plus vives. Zone 400×300 px avec fond légèrement texturé.
Teaser d'une date clé — page de lancement d'une agence de communication événementielle — Elastic Drag exemple 3

③ Teaser d'une date clé — page de lancement d'une agence de communication événementielle

QuandUn cube « Découvrez la date » peut être tiré dans tous les sens ; il rebondit en révélant progressivement une partie de la date cachée derrière.
PourquoiLe retour élastique donne au composant de teaser une énergie physique qui entretient la curiosité et l'anticipation — une interaction mémorable pour une annonce événementielle.
RéglagesObjet 200×200 px avec texte partiel de la date visible au dos (rotation CSS au drag). Zone étendue. L'objet peut aussi afficher un compte à rebours sous lui après 3 s d'inactivité.

Comment ça marche

Le cadre .fx-0374-root contient une zone .edg-zone et un objet .edg-box positionné au centre. L'état de déplacement (position courante, vélocité, drapeau dragging) est isolé par instance dans une fermeture JavaScript — deux instances sur la même page ne partagent aucune variable.

Au mousedown (ou touchstart) sur l'objet, le script mémorise le décalage entre la position du pointeur et le centre de l'objet. Les événements mousemove et touchmove sur document mettent à jour la position de l'objet (transform: translate(x, y)) et calculent la vélocité instantanée (vx = x − prevX). touchmove appelle preventDefault() pour bloquer le défilement.

Au mouseup ou touchend, la fonction animateBack() démarre une boucle requestAnimationFrame : à chaque image, la vélocité est amortie (vx *= 0.9) et une force de rappel est ajoutée (vx += (0 − x) × 0.15 — ressort). La boucle s'arrête quand position et vélocité sont suffisamment proches de zéro. Les flèches du clavier déplacent aussi l'objet (10 px par appui), puis déclenchent animateBack(). Sous prefers-reduced-motion: reduce, animateBack() replace l'objet instantanément à (0, 0) sans animation.

Accessibilité

  • Clavier : l'objet est focusable par Tab (tabindex="0") sans role="button" (un bouton impliquerait une action à Entrée/Espace, ce qui ne correspond pas à un élément qu'on glisse). Un aria-label décrit l'objet et ses instructions : « Glissez-moi — touches fléchées pour déplacer ». Les touches fléchées déplacent l'objet de 20 px par appui ; au relâchement, il revient élastiquement au centre.
  • Touch : touchstart, touchmove et touchend sont gérés. L'attribut CSS touch-action: none empêche le navigateur d'interférer avec le défilement pendant le drag.
  • Mouvement réduit : sous prefers-reduced-motion: reduce, le drag fonctionne (c'est un geste volontaire), mais le retour est instantané — l'objet se replace à (0, 0) sans oscillation.
  • Pas d'information encodée dans la position : la position de l'objet est purement décorative ou ludique. Aucune action fonctionnelle ne doit dépendre d'un dépôt précis — ce n'est pas un drag-and-drop fonctionnel (pour ça, utilisez l'API HTML5 Drag and Drop ou une bibliothèque dédiée).

Compatibilité navigateur

DOM + requestAnimationFrame + 2,5 Ko de JavaScript, aucune dépendance. Touch events disponibles sur tous les navigateurs mobiles modernes. L'animation de ressort est calculée en JS pur (pas de Web Animations API). Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : drag, vélocité et retour élastique identiques dans les trois. Sur iOS, touch-action: none est requis pour empêcher le défilement de la page pendant le drag.

Chrome 60+✓ Complet
Firefox 55+✓ Complet
Safari 11+✓ Complet
Edge 79+✓ Complet
Mobile iOS 11+✓ Complet (tactile)
Android Chrome 60+✓ Complet (tactile)

Sans JavaScript, l'objet s'affiche au centre de la zone sans comportement. L'effet nécessite JavaScript pour fonctionner. Sur navigateurs très anciens sans requestAnimationFrame (IE9 et avant), le retour est instantané.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :

index.html — structure
<div class="fx-0374-root">
  <div class="edg-zone">
    <div class="edg-box" tabindex="0" role="button" aria-label="Élément élastique — glissez ou utilisez les touches fléchées">DRAG ME</div>
  </div>
</div>

Paiement unique, sans abonnement — le code est à toi pour toujours

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Raideur du ressort (JS — vx += (0 − x) × 0.15) 0,15 par image 0,05 donne des oscillations longues et souples, 0,3 un retour vif. Des valeurs > 0,5 peuvent rendre l'animation instable (l'objet dépasse et ne revient pas).
Amortissement (JS — vx *= 0.9) 0,9 par image (10 % de perte) 0,8 amortit rapidement (1-2 oscillations), 0,95 laisse osciller longtemps. 1 = oscillation infinie (en théorie).
Pas clavier (JS — 10 px par appui) 10 px Augmentez à 20-30 px pour un mouvement clavier plus visible, diminuez à 5 px pour un déplacement plus fin.
Libellé de l'objet (HTML — contenu de .edg-box) "DRAG ME" Remplacez par « Tirez-moi ! », une icône, un logo ou n'importe quel contenu HTML. L'objet adapte sa taille à son contenu.
Contrainte de déplacement (JS) déplacement libre dans les deux axes Pour contraindre à l'axe horizontal, annulez y (y = 0) dans le mousemove. Pour une contrainte verticale, annulez x.

FAQ

Oui. Ajoutez des contraintes dans le mousemove : x = Math.max(-maxX, Math.min(maxX, x)) où maxX est la moitié de la largeur de la zone moins la moitié de la largeur de l'objet. Calculez maxX et maxY à partir des dimensions de la zone et de l'objet (getBoundingClientRect()).
Oui. Dans le gestionnaire mouseup, lisez la position finale (x, y) avant d'appeler animateBack(). Si la position est dans une zone cible (rectangle défini), déclenchez votre action (changement d'état, navigation, animation de validation). Après l'action, appelez ou non animateBack() selon le comportement souhaité.
Le ressort est calculé par image, pas par temps écoulé : sur un écran 120 Hz, il oscille deux fois plus vite que sur un écran 60 Hz. Pour un timing constant quelle que soit la fréquence, calculez le delta de temps depuis la dernière image et ajustez les coefficients en conséquence : vx += (0 − x) × 0.15 × (dt / 16.67).