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.
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



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") sansrole="button"(un bouton impliquerait une action à Entrée/Espace, ce qui ne correspond pas à un élément qu'on glisse). Unaria-labeldé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,touchmoveettouchendsont gérés. L'attribut CSStouch-action: noneempê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.
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) :
<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éfaut | Effet |
|---|---|---|
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
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()).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é.vx += (0 − x) × 0.15 × (dt / 16.67).