Bookmark Toggle
Un bouton marque-page dont le ruban tombe en place au clic avec un léger rebond, le fond se remplit et l'icône passe du contour au plein — animation de sauvegarde en CSS pur avec retour haptique visuel.
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
La racine .fx-0362-root (250 px de haut, fond rgb(26, 26, 36)) centre deux boutons marque-page côte à côte dans .mi-bookmark-scene. Chaque bouton .mi-bookmark-btn (40×48 px) contient un SVG de ruban dont les bords sont tracés en stroke et l'intérieur coloré par fill. Un pseudo-élément ::before forme le fond de remplissage, initialement hors du bouton (translateY(-100%)).
Au clic, la classe .saved s'ajoute au bouton. Elle déclenche trois transitions simultanées. Côté fond : le ::before descend de translateY(-100%) à translateY(0) en 0,4 s avec une cubic-bezier(0.34, 1.56, 0.64, 1) qui donne un léger dépassement vers le bas avant de remonter en place. Côté SVG : stroke et fill passent respectivement de couleur de contour à blanc opaque, via une transition de 0,25 s. Côté label : la couleur du texte adjacent passe aussi en couleur active. L'animation de la coche (@keyframes savedCheck) dessine un trait de confirmation visible 0,2 s après le début de la transition de fond, pour que les trois changements ne semblent pas simultanés.
Le script trouve chaque .fx-0362-root, câble les boutons de la racine et met à jour aria-pressed à chaque clic. L'état initial est lu depuis la présence de la classe .saved dans le HTML : un bouton préchargé en état sauvegardé a déjà aria-pressed="true". Les deux boutons de la démo sont indépendants et leurs états ne se propagent pas d'une copie du composant à l'autre.
Accessibilité
- Clavier : chaque bouton marque-page est un vrai
<button>; Tab l'atteint, Espace ou Entrée le bascule. Le contour de focus (:focus-visible) apparaît à la navigation au clavier. - État annoncé :
aria-pressedpasse defalseàtrueau clic. L'aria-label(Sauvegarder / Favoris selon le bouton) décrit l'action ; le lecteur d'écran annonce l'état activé ou non activé. - Mouvement réduit : sous
prefers-reduced-motion: reduce, la transitiontranslateYdu fond est supprimée et l'animation@keyframes savedCheckest désactivée. L'état sauvegardé reste lisible par le changement de couleur du fond et de l'icône. - Toucher : les boutons répondent normalement aux événements tactiles. Leur cible de 40×48 px est dans les minimums recommandés (44×44 px).
Compatibilité navigateur
CSS pur (transitions, pseudo-éléments, cubic-bezier avec dépassement) + 0,4 Ko de JavaScript (classList, aria-pressed), aucune dépendance. Vérifié dans Chromium 151 : animation de chute, remplissage, deux boutons indépendants, deux copies de la racine indépendantes, aria-pressed mis à jour, 0 erreur. Les captures d'aperçu montrent l'animation rejouée en boucle automatique par le code de scène : ce comportement n'est pas inclus dans le code vendu.
Sans JavaScript, le bouton reste fonctionnel en lecture seule (l'état ne bascule plus). Sans CSS transitions, le fond et l'icône changent instantanément de couleur sans animation de chute.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0362-root">
<div class="mi-bookmark-scene">
<button class="mi-bookmark-btn" aria-pressed="false" aria-label="Sauvegarder">
<svg viewBox="0 0 24 24">
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>
</svg>
</button>
<span class="mi-bookmark-text">Sauvegarder</span>
</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 |
|---|---|---|
Couleur de fond actif (CSS — background de .mi-bookmark-btn::before et .mi-bookmark-btn.saved::before) |
Bleu indigo #6366f1 |
Passez à #f59e0b (ambre) ou #10b981 (vert émeraude). La couleur de l'icône SVG en état actif (.mi-bookmark-btn.saved svg) et du label (.mi-bookmark-btn.saved ~ .mi-bookmark-text) doivent être mis à jour en cohérence. |
Rebond de la chute (CSS — cubic-bezier de la transition transform sur ::before) |
cubic-bezier(0.34, 1.56, 0.64, 1) (léger dépassement) |
ease-out donne une chute sans rebond ; augmentez le deuxième paramètre au-delà de 1 (ex. 1,8) pour un rebond plus marqué. |
Taille du bouton (CSS — width / height de .mi-bookmark-btn) |
40×48 px | Réduisez à 32×40 px pour une liste très dense ; agrandissez à 48×56 px pour un usage isolé. Le SVG à l'intérieur suit si sa taille est exprimée en pourcentage. |
Nombre de boutons dans la démo (HTML — nombre de .mi-bookmark-btn dans la scène) |
2 boutons | Ajoutez ou supprimez des boutons dans le .mi-bookmark-scene. Chaque bouton doit avoir son propre aria-label décrivant l'élément à sauvegarder. |
État initial sauvegardé (HTML — classe .saved sur le bouton) |
Aucun bouton sauvegardé au départ | Ajoutez la classe .saved directement dans le HTML pour afficher un bouton déjà enregistré au chargement ; le JS lit cet état et initialise aria-pressed en conséquence. |
FAQ
.saved s'ajoute et l'animation de chute rejoue. Mais le passage inverse (sauvegardé → non sauvegardé) n'a pas d'animation propre : le fond disparaît sans animation de sortie. Pour ajouter une animation de retrait, déclarez @keyframes sur la suppression de la classe ou utilisez une animation animation-direction: reverse..saved directement dans le HTML. Le script lit l'état initial des classes et fixe aria-pressed en conséquence : aria-pressed="true" sur un bouton déjà .saved..saved et son propre aria-pressed. L'un peut être sauvegardé et l'autre non, indépendamment. De même, deux copies du composant sur la même page ont des états totalement séparés.