Les effets d'entrée et de sortie sont des animations qui se déclenchent lorsqu'un élément entre dans la fenêtre d'affichage ou en sort. Cela peut être utilisé pour créer des expériences utilisateur attrayantes et dynamiques. Par exemple, vous pouvez utiliser un effet d'entrée pour faire apparaître un élément en fondu lorsqu'il défile dans la vue, ou un effet de sortie pour réduire sa taille lorsqu'il défile hors de la vue.
Mise en œuvre
Pour ajouter des effets d'entrée et de sortie à un élément, vous devez combiner plusieurs propriétés CSS. Voici la procédure à suivre, étape par étape :
Créez des
@keyframesdistincts pour les animations d'entrée et de sortie. L'animation d'entrée sera appliquée lorsque l'élément entrera dans la fenêtre d'affichage, et l'animation de sortie sera appliquée lorsqu'il en sortira.@keyframes slide-in { from { transform: translateX(-100%); } } @keyframes slide-out { to { transform: translateX(100%); } }Associez les images clés d'entrée et de sortie à l'élément. Pour ce faire, définissez plusieurs animations dans la propriété
animation.- Attribuez à l'animation d'entrée un
animation-fill-modedebackwardsafin qu'elle applique son état initial avant le début de l'animation. - Attribuez à l'animation de sortie un
animation-fill-modedeforwardsafin qu'elle conserve son état final une fois l'animation terminée.
.animated-element { animation: slide-in 1s linear backwards, slide-out 1s linear forwards; }- Attribuez à l'animation d'entrée un
Créez une timeline d'affichage et associez-la aux animations. Une timeline d'affichage est un type de timeline associé à la visibilité d'un élément dans la fenêtre d'affichage. Vous pouvez en créer une à l'aide de la fonction
view(), puis l'appliquer à vos animations à l'aide de la propriétéanimation-timeline..animated-element { animation-timeline: view(); }Par défaut,
view()suit l'élément sur l'axeblock. Si vous devez le suivre sur l'axeinline, vous pouvez utiliserview(inline).Limitez les animations aux plages
entryetexit. La propriétéanimation-rangevous permet de spécifier la partie de la chronologie sur laquelle une animation doit s'exécuter.- La plage
entrycouvre la période entre l'entrée de l'élément dans la fenêtre d'affichage et sa visibilité complète. - La plage
exitcouvre la période entre le moment où l'élément commence à quitter la fenêtre d'affichage et celui où il est complètement masqué.
.animated-element { animation-range: entry, exit; }- La plage
Exemple de code
Ce code anime les enfants directs du défileur lors du défilement à l'aide d'une view-timeline anonyme :
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: view(inline);
animation-range: entry, exit;
}
}
}
Lorsque les éléments entrent dans la zone de défilement, l'animation grow est lue. Lorsqu'ils quittent la zone de défilement, l'animation shrink est lue.
Le code suivant produit le même résultat visuel, mais anime les enfants directs du défileur lors du défilement à l'aide d'une chronologie de vue nommée :
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
view-timeline: --tl inline;
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: --tl;
animation-range: entry, exit;
}
}
}
Bonnes pratiques
Lorsque vous utilisez des animations basées sur le défilement, il est important de suivre quelques bonnes pratiques pour garantir une expérience fluide et accessible :
- À FAIRE : incluez la détection de fonctionnalités. Tous les navigateurs ne sont pas compatibles avec les animations déclenchées par le défilement. Utilisez
@supports ((animation-timeline: view()) and (animation-range: entry))pour vérifier la compatibilité et fournir une solution de remplacement pour les navigateurs qui ne sont pas compatibles.- La vérification
(animation-range: entry)DOIT être incluse ici pour filtrer les navigateurs qui ne sont que partiellement compatibles. - N'UTILISEZ PAS le package
scroll-timeline-polyfillpour la stratégie de remplacement, car il n'est pas complet et présente de nombreux problèmes connus. - Si l'animation n'est considérée que comme décorative, optez pour l'amélioration progressive et NE FOURNISSEZ PAS de solution de remplacement.
- La vérification
- À FAIRE : Respectez les préférences des utilisateurs. Certains préfèrent avoir moins de mouvements sur le Web. Utilisez la requête média
prefers-reduced-motionpour désactiver ou réduire vos animations pour ces utilisateurs. - À FAIRE : Essayez de n'animer que les propriétés CSS performantes. Pour des animations plus fluides, n'animez que les propriétés pouvant être gérées par le thread du compositeur du navigateur, telles que
transformetopacity. L'animation d'autres propriétés telles quewidthouheightpeut entraîner des problèmes de performances. - À FAIRE : Utilisez l'ordre de déclaration correct. Lorsque vous utilisez la propriété abrégée
animation, déclarezanimation-timelineaprès celle-ci pour éviter que la propriété abrégée ne réinitialise la chronologie.
Lorsque vous utilisez la fonction view() pour créer une animation basée sur le défilement :
- FACULTATIF : indiquez explicitement l'axe à suivre. Lorsque vous ne ciblez pas l'axe
blockpar défaut (par exemple, dans un défilement horizontal), indiquez explicitement l'axe à suivre avecview(block)ouview(inline). - Lorsque l'animation n'est pas appliquée au sujet suivi lui-même, utilisez une chronologie de vue nommée.
Lorsque vous utilisez la propriété view-timeline pour créer une animation basée sur le défilement :
- À FAIRE : utilisez une
<dashed-ident>CSS pour le nom. - FACULTATIF : Soyez explicite sur l'axe à suivre. Lorsque vous ne ciblez pas l'axe
blockpar défaut (par exemple, dans un défilement horizontal), indiquez explicitement l'axe à suivre avecview-timeline-axis. - À FAIRE : Assurez-vous que le champ d'application de la recherche fonctionne. Lorsque l'élément qui déclare
view-timelinen'est pas un ancêtre de l'arborescence plate de l'élément animé, augmentez la visibilité du nom deview-timelineen utilisanttimeline-scopesur un ancêtre partagé.
Privilégiez un view-timeline nommé lorsque plusieurs éléments ou enfants du sujet suivi doivent être animés.
Compatibilité des navigateurs et stratégies de remplacement
Par conséquent, une stratégie de remplacement est généralement requise.
Pour les navigateurs qui ne sont pas compatibles avec les animations déclenchées par le défilement, vous pouvez utiliser une solution de remplacement pour recréer les effets visuels. Les solutions de remplacement sont généralement créées avec un écouteur de défilement (pour les effets ScrollTimeline) ou l'API IntersectionObserver (pour les effets ViewTimeline).
Dans les navigateurs compatibles de manière native avec les animations liées au défilement, utilisez TOUJOURS l'implémentation CSS native, car elle est plus performante.
Notez que tous les effets ne peuvent pas être recréés à l'aide de l'approche de remplacement.
Pour ce cas d'utilisation spécifique, le script suivant applique la solution de remplacement pour les navigateurs qui ne sont pas compatibles avec les animations déclenchées par le défilement. Il utilise un IntersectionObserver pour suivre la visibilité de l'élément .wrapper et met à jour la propriété transform des calques en fonction de la position de défilement.
<script>
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
// This matches the effect as defined in the CSS example above.
// Customize this further if needed.
entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
}
},
{
threshold: Array.from({ length: 101 }, (_, i) => i / 100),
}
);
document.querySelectorAll('.scroller > *').forEach((el) => {
observer.observe(el);
});
}
</script>