Les exports HTML statiques des équipes marketing continuent d’empiler accordéons, tiroirs de filtres et panneaux d’aide qui doivent glisser entre un état replié et une hauteur naturelle dictée par le contenu. Pendant longtemps, CSS a échoué parce que height: auto n’offrait pas d’extrémité numérique stable pour les transitions et que les moteurs sautaient brutalement à la fin. En 2026, le duo interpolate-size: allow-keywords et calc-size() réintroduit les mots-clés intrinsèques dans la chaîne d’interpolation sans retomber sur d’énormes heuristiques max-height ni sur des scripts scrollHeight fragiles. Ce guide couvre la douleur initiale, les primitives, le renforcement progressif via @supports, les interactions flex/grid, les particularités Safari/WebKit, les pièges de performance, l’accessibilité, une matrice et une checklist de release. Pour comparer avec des transitions cross-documents, lisez le guide View Transitions pour MPA statiques ; si vos disclosures mélangent champs auto-agrandissants, croisez avec field-sizing sur HTML statique et formulaires.
Le comportement Safari se valide le mieux sur du matériel Apple réel. MacHTML propose des Mac mini cloud autour de 16,9 USD par jour, un ordre de grandeur réaliste pour des salles de répétition courtes mais dédiées.
Pourquoi animer height:auto faisait mal
Une transition exige deux valeurs utilisées comparables. auto est spécial : il n’existe qu’après mesure de layout et, dans la plupart des moteurs, n’est pas interpolable. Les équipes simulaient l’effet avec des plafonds max-height artificiels, découplant la durée de la longueur réelle du texte. Les traductions françaises ou allemandes rallongent les chaînes, rendant l’easing soudainement mou. Les scripts qui mesurent le DOM recollent le fil principal, heurtent les CSP et clignotent quand les webfonts arrivent tard. La nouvelle pile garde mesure et interpolation dans la couche style, réduit le JavaScript sur les bundles statiques et évite les doubles passes tant qu’on n’anime pas des tailles contradictoires sur la même boîte.
overflow: hidden complique les cartes arrondies : si max-height et border-radius ne sont pas synchronisés, des artefacts de bord apparaissent sur écran Retina. L’interpolation intrinsèque rapproche la hauteur mesurée du contenu réel.
Les landings SEO utilisent souvent des accordéons juridiques : un saccadement est confondu avec une régression Core Web Vitals alors que seule la couche motion bouge. Séparez clairement métriques business et métriques motion.
interpolate-size: allow-keywords en pratique
interpolate-size: allow-keywords déclare un sous-arbre où le moteur peut traduire des mots-clés intrinsèques en échantillons numériques. Limitez la déclaration au conteneur de disclosure, pas au body entier, pour ne pas payer d’interpolation ailleurs. Ajoutez overflow: clip si les masques arrondis doivent rester nets et fixez explicitement les états height ouverts/fermés.
.disclosure {
interpolate-size: allow-keywords;
overflow: clip;
transition: height 260ms cubic-bezier(.2,.8,.2,1);
}
Attention au collapse de marges : un panneau à height: 0 peut laisser un vide si les marges adjacentes fusionnent ; préférez du padding sur un wrapper interne. La propriété hérite : les accordéons imbriqués en profitent, mais des flex profonds animant aussi flex-basis peuvent provoquer des passes supplémentaires.
Documentez dans le design system quels modules ont le droit d’interpoler et versionnez le CSS séparément des exports CMS pour que le support relie captures d’écran et révisions.
calc-size(fit-content) comme pont de mesure
calc-size() encapsule un mot-clé intrinsèque dans un calcul traité comme une longueur. Un accordéon typique passe de height: 0 à height: calc-size(fit-content, size) pour mesurer le contenu tout en conservant une courbe interpolable. Contrairement aux max-height géantes, la durée perçue suit la profondeur réelle du texte.
.panel[data-open="true"] .panel-body {
height: calc-size(fit-content, size);
}
.panel[data-open="false"] .panel-body {
height: 0;
}
Si une live region injecte du texte pendant la transition, la cible bouge—comportement correct mais déroutant. Sur HTML statique, figez les mutations DOM jusqu’à transitionend. Avec box-sizing: border-box, vérifiez que le padding est inclus dans la mesure attendue.
Testez l’impression : certains moteurs PDF ignorent des fonctionnalités récentes ; le contenu doit rester lisible sans motion.
Renforcement progressif avec @supports
Toutes les installations ne suivent pas Safari au même rythme. Offrez un basculement instantané ou une animation max-height de secours si calc-size() est absent. Testez la règle @supports sur la déclaration exacte, pas sur un feature string vague.
@supports (height: calc-size(fit-content, size)) {
.panel-body { transition: height 240ms ease; }
}
@supports not (height: calc-size(fit-content, size)) {
.panel-body { transition: max-height 320ms ease; max-height: 0; }
.panel[data-open="true"] .panel-body { max-height: 80vh; }
}
Gardez la structure sémantique indépendante de la couche motion : details/summary ou boutons avec aria-expanded restent la source de vérité.
Grille, flex et min-height:auto
Les items flex ont min-height: auto par défaut et ne rétrécissent pas sous leur minimum intrinsèque. Les panneaux repliés exigent souvent min-height: 0 pour que height: 0 soit honnête. En grille, min-size:auto et l’étirement des pistes peuvent empêcher l’animation si les tailles de ligne sont trop rigides.
Avec contain: layout, vérifiez les anneaux de focus : un containment trop agressif les clippe. Évitez d’animer marge et hauteur en parallèle sur des frères pour limiter les doubles layouts.
Les langues longues (allemand, français juridique) changent les césures et donc les mesures intrinsèques : retestez après traduction.
Notes Safari et WebKit
WebKit fusionne les mises à jour de style quand le fil principal est saturé par des scripts tiers. Même une page statique peut micro-saccader à cause d’analytics. Profilez avec la timeline Web Inspector et comparez Safari stable à Safari Technology Preview si votre release chevauche une mise à jour macOS.
Les animations de hauteur déclenchent du layout : elles ne sont pas « gratuites » sur le compositeur. Évitez de combiner transform et height sur la même boîte sans mesure. Harmonisez le lissage de police pour éviter le scintillement du texte entre états.
Sur ProMotion, la cadence varie : testez 60 Hz et 120 Hz lorsque le matériel cible le permet.
Performance et thrash de layout
Chaque échantillon de hauteur impose un recalcul. Cinq panneaux ouverts ensemble multiplient le coût. Limitez la concurrence, décalez légèrement les ouvertures ou utilisez content-visibility: auto hors écran après avoir vérifié l’accessibilité. Les callbacks ResizeObserver ne doivent pas écrire dans le layout de façon synchrone pendant une transition.
La limitation CPU sur batterie étire les courbes : évitez des durées excessives qui donnent l’impression d’attendre.
Accessibilité et prefers-reduced-motion
Les personnes sensibles au vestibulaire souhaitent moins de mouvement. Sous prefers-reduced-motion: reduce, réduisez les durées quasi à zéro ou passez à une simple variation d’opacité sans cacher le contenu.
@media (prefers-reduced-motion: reduce) {
.panel-body { transition: none !important; }
}
Mettez à jour aria-expanded en même temps que l’état, pas seulement après la fin de la transition, sauf recherche UX contraire—cas rare.
Motifs pour accordéons HTML statiques
Stockez l’état dans des attributs data-* ou des details natifs. Évitez les doubles règles de hauteur entre framework et overrides marketing. Isolez la motion dans un fichier versionné par query string pour purger CDN proprement.
Dans les pipelines CMS headless, supprimez les espaces insécables parasites qui faussent la mesure intrinsèque.
Matrice : quand interpoler la hauteur intrinsèque
| Scénario | Interpoler ? | Note |
|---|---|---|
| Textes juridiques en accordéon | Oui | calc-size suit la profondeur réelle. |
| Cartes de flux infini | Non | Virtualisez pour éviter le thrash de scroll. |
| Modales | Parfois | Préférez transform pour le cadre, hauteur pour le contenu. |
| Navigation sticky | Prudence | Sticky et hauteur partagent des décisions compositeur. |
Checklist QA numérotée
- Tester 320, 390 et 834 px avec les traductions les plus longues.
- Activer prefers-reduced-motion et vérifier la lisibilité.
- Ouvrir cinq panneaux d’affilée et mesurer le CPU sur une base M2.
- Profiler avec les scripts tiers activés comme en production.
- Valider l’ordre de focus à mi-transition.
- Comparer Safari stable et STP si une mise à jour macOS est proche.
- Retester après changement de preload de webfonts.
- Capturer captures en mode sombre et contraste élevé.
FAQ
max-height reste-t-il acceptable ?
Oui en repli, mais calc-size donne des courbes plus honnêtes sur les longs textes.
Remplace-t-on les animations liées au scroll ?
Non, mécanismes différents—combinez seulement avec profilage.
Et width:auto ?
Idées proches, mais l’axe horizontal provoque plus de reflow typographique.
La motion fiable sur HTML statique exige du matériel Safari réel avec polices et échelle proches de la prod. Un Mac mini MacHTML à environ 16,9 USD par jour permet des répétitions dédiées, captures SSH et revues VNC sans acheter du neuf.
Répéter les animations de hauteur sur Mac mini cloud
Chargez votre bundle statique dans Safari Apple Silicon, profilez les tempêtes de layout et signez avant merge.