Avatar Morph
Un avatar rond de 80 px qui s'étire en carte de 220 × 120 px : le cercle devient rectangle arrondi, les initiales glissent à gauche, puis le nom, le rôle et un badge apparaissent avec un quart de seconde de retard. Seul passage du rond à la carte de la catégorie, en CSS pur, sans une ligne de JavaScript ; il s'ouvre au survol, au clavier et au toucher, et change de forme sans s'étirer si l'utilisateur réduit les animations.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Liquid comprend 31 effets, dont 6 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Le bloc .avatar-morph (80 × 80 px) contient un cadre .avatar-morph-inner arrondi à 50 %, la pastille d'initiales .avatar-pic (60 px, dégradé violet-rose) et un bloc .avatar-info transparent : nom, rôle, badge. Au survol, le bloc passe à 220 × 120 px et le cadre à des coins de 16 px, avec transition: .6s cubic-bezier(.68, -.3, .27, 1.2) : un léger recul au départ, un léger dépassement à l'arrivée. La pastille se réduit à 50 px et glisse au bord gauche, centrée en hauteur (top: 50% et translateY(-50%)). Le texte, posé à 80 px du bord, apparaît en 0,4 s après 0,25 s d'attente : il ne se montre que quand la carte a la place de l'afficher.
La pastille part d'une position écrite en pixels (left: 9px; top: 9px, le centre du rond) et non de la position automatique d'un élément centré : une valeur auto ne s'interpole pas, la pastille sauterait d'un coup vers le bas avant de remonter. Mesuré image par image dans Chromium 151, Firefox 153 et WebKit 26 : le haut de la pastille glisse de 10 à 35 px pendant les 0,6 s, une valeur différente à chaque image, sans saut.
Chaque règle :hover est doublée d'une règle :focus-within, et le bloc porte tabindex="0" : la carte s'ouvre aussi quand on l'atteint avec Tab, et au doigt, puisque toucher l'élément lui donne le focus. L'anneau de focus clavier (2 px violet) est posé sur le cadre intérieur, dont il suit l'arrondi. Le texte de la carte est toujours dans la page, seulement transparent : un lecteur d'écran le lit, que la carte soit ouverte ou fermée.
Accessibilité
- Clavier : mesuré dans les trois moteurs, y compris WebKit, Tab atteint l'avatar et la carte s'ouvre ; elle se referme quand le focus part. L'anneau de focus n'apparaît qu'au clavier (
:focus-visible). - Toucher : mesuré en émulation mobile, un toucher ouvre la carte dans Chromium et dans WebKit. Dans Chromium, toucher ailleurs la referme ; dans WebKit, elle reste ouverte jusqu'au toucher d'un autre élément qui prend le focus (lien, bouton, autre avatar). Pour la fermer au toucher de n'importe quelle zone, ajoutez :
document.addEventListener('pointerdown', function (e) { if (!e.target.closest('.avatar-morph')) document.activeElement.blur(); }); - Lecteurs d'écran : la pastille d'initiales est masquée (
aria-hidden) ; le nom, le rôle et le badge sont lus dans l'ordre, ouverts ou non. Si l'avatar mène à un profil, mettez un vrai lien autour du nom. - Mouvement réduit : sous
prefers-reduced-motion: reduce, le rond devient carte d'un coup (mesuré : la forme finale est là dès la première mesure), et seul le texte apparaît en fondu.
Compatibilité navigateur
CSS pur (transitions, :hover, :focus-within), 3,3 Ko, aucun JavaScript. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : même étirement, même glissement des initiales, même ouverture au clavier, même arrêt sous mouvement réduit. :focus-within existe depuis Chrome 60, Firefox 52 et Safari 10.1.
Sans :focus-within, la carte ne s'ouvre plus qu'au survol de la souris ; le texte reste lisible par les lecteurs d'écran. Sans transitions, le rond devient carte d'un coup.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0409-root">
<div class="avatar-morph" tabindex="0">
<div class="avatar-morph-inner">
<div class="avatar-pic" aria-hidden="true">JD</div>
<div class="avatar-info">
<div class="avatar-info-name">…</div>
<div class="avatar-info-role">…</div>
<span class="avatar-info-badge">…</span>
</div>
</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 |
|---|---|---|
Tailles (CSS — width / height de .avatar-morph et de ses règles :hover) |
80 px de diamètre, carte de 220 × 120 px | Le texte commence à 80 px du bord (left de .avatar-info) et ne passe pas à la ligne : pour un rôle plus long, élargissez la carte (260 px) plutôt que de réduire la police. |
Rebond (CSS — transition: .6s cubic-bezier(.68, -.3, .27, 1.2), trois fois) |
0,6 s, léger recul puis léger dépassement | .4s ease-out donne une ouverture plus nette. Gardez la même valeur sur le bloc, le cadre et la pastille pour qu'ils bougent ensemble. |
Retard du texte (CSS — transition-delay: .25s de .avatar-info) |
0,25 s | En dessous de 0,15 s, le texte apparaît pendant que la carte est encore étroite et se fait couper ; au-delà de 0,4 s, la carte paraît vide un instant. |
Couleurs (CSS — .avatar-morph-inner, .avatar-pic, .avatar-info-badge) |
violet #a855f7, rose #ec4899, cyan à 15 % |
Si la carte s'ouvre par-dessus d'autres éléments, ajoutez une couleur pleine sous le dégradé translucide (background: linear-gradient(…), #121f3f) pour que les voisins ne transparaissent pas. |
Badge (HTML — .avatar-info-badge) |
« En ligne » | Un état court et utile : « De permanence », « Sur le terrain », « Absent jusqu'au 12 ». Retirez-le si vous n'en avez pas, la carte reste équilibrée avec deux lignes. |
FAQ
left et top : au survol, elle sauterait d'un coup à top: 50%, tout en bas du rond, puis remonterait avec la translation. Écrire la position du centre en pixels (80 − 2 de bordure − 60, divisé par deux) donne au navigateur un point de départ ; mesuré, la pastille glisse de 10 à 35 px sans à-coup.tabindex="0" rend l'avatar focalisable, et un toucher lui donne le focus, ce qui déclenche les règles :focus-within. Mesuré en émulation mobile dans Chromium et WebKit. La différence est à la fermeture : Chromium referme au toucher ailleurs, WebKit attend que le focus passe à un autre élément interactif ; la ligne de JavaScript de la section accessibilité harmonise les deux.