Carrousel JavaScript : le défilement infini sans retour arrière

Carrousel JavaScript : le défilement infini sans retour arrière

Un carrousel JavaScript n’a pas besoin d’une bibliothèque lourde pour être fluide, responsive et utilisable au clavier. La solution la plus robuste consiste à laisser le navigateur gérer le défilement horizontal, puis à ajouter JavaScript pour les boutons, l’état actif, la pagination et les comportements avancés. Le point délicat n’est pas de faire bouger les slides, mais de préserver une navigation cohérente sur mobile, au redimensionnement et avec les technologies d’assistance.

Partir d’une structure simple et sémantique

Un carrousel repose sur trois éléments : un conteneur global, une zone de défilement qui contient les slides, puis des contrôles. Cette séparation évite de mélanger la présentation, le comportement et l’interface de navigation. Chaque slide peut contenir une image, une carte produit, un témoignage ou une actualité, mais doit rester compréhensible même si JavaScript ne se charge pas.

Le conteneur de défilement

La zone qui défile reçoit les propriétés CSS essentielles : display: flex, overflow-x: auto et une largeur adaptée à son parent. Les slides restent sur une seule ligne et obtiennent une largeur ou une min-width cohérente. Pour une galerie de cartes, une largeur minimale de 250 px peut être un bon point de départ. Sur écran large, il est possible d’afficher quatre éléments à la fois. Sur mobile, une carte large ou une carte accompagnée d’un aperçu de la suivante rend le geste de swipe plus évident.

Des contrôles qui décrivent réellement leur action

Les boutons précédent et suivant doivent être de vrais boutons, avec un nom accessible explicite, par exemple « Voir les éléments précédents » et « Voir les éléments suivants ». Une pagination sous forme de boutons apporte un repère supplémentaire : elle permet de rejoindre une position sans multiplier les clics. Si un compteur est affiché, une formulation comme « 1/4 » doit être complétée par un libellé compréhensible pour un lecteur d’écran.

Un bon carrousel ne cache pas son fonctionnement derrière un effet visuel. Les flèches doivent rester atteignables, la zone défilable doit être identifiable et les cartes doivent conserver une hiérarchie de titres logique. Si le contenu est trop important pour être résumé dans une slide, le carrousel n’est probablement pas le bon format. Une liste ou une grille sera plus claire.

Choisir entre scroll-snap et pilotage JavaScript

Le choix technique dépend du niveau de contrôle attendu. Pour une galerie tactile, CSS scroll-snap offre une base légère et naturelle. Pour une interface avec pagination calculée, état actif précis ou défilement par groupe de cartes, JavaScript complète efficacement ce comportement natif. Cette combinaison réduit la quantité de code tout en conservant une navigation précise.

Carrousel JavaScript : comparaison entre scroll-snap, navigation par boutons et boucle infinie
Carrousel JavaScript : comparaison entre scroll-snap, navigation par boutons et boucle infinie
Approche Atout principal À prévoir
Scroll-snap CSS Swipe naturel et peu de JavaScript Contrôles et état actif à synchroniser
JavaScript avec scrollTo Navigation précise par page ou par slide Calcul des positions et des limites
Carrousel infini avec clones Impression de boucle continue Repositionnement invisible et accessibilité

Le défilement horizontal « aimanté »

Avec scroll-snap-type: x proximity sur le conteneur et scroll-snap-align: start sur les slides, le défilement se stabilise naturellement sur une carte. Cet effet d’aimant limite les positions intermédiaires où une carte est coupée de manière ambiguë. Ajoutez un scroll-padding-inline lorsque le premier ou le dernier élément doit conserver une marge visuelle, notamment si les boutons se superposent légèrement à la zone de défilement.

Le scroll-snap reste préférable à une translation forcée pour un composant consulté au doigt. Le navigateur conserve son inertie, l’utilisateur peut interrompre le mouvement à tout moment et le défilement horizontal fonctionne sans logique complexe. JavaScript peut ensuite appeler scrollTo avec un comportement fluide lorsque l’utilisateur clique sur une flèche. Le scroll natif reste ainsi responsable du geste tactile, tandis que le script gère les commandes complémentaires.

Programmer les boutons, les limites et le responsive

La navigation JavaScript doit se baser sur la largeur réellement visible du conteneur, et non sur une valeur figée. Au clic sur « suivant », le script déplace la zone d’une page visible ; au clic sur « précédent », il revient d’une page. La position actuelle est disponible avec scrollLeft, tandis que la largeur de consultation provient de offsetWidth ou de la largeur du conteneur.

Calculer les pages plutôt que compter naïvement les slides

Lorsqu’il y a plusieurs éléments visibles, une slide ne correspond pas forcément à une page. Un carrousel affichant quatre cartes sur grand écran, puis une seule sur mobile, doit recalculer son nombre de pages après chaque redimensionnement. La dernière page peut être incomplète. Le bouton suivant doit alors mener au dernier défilement utile, sans créer un espace vide excessif.

À chaque changement de position, mettez à jour les contrôles. Au début, le bouton précédent peut être désactivé ; à la fin, c’est le bouton suivant. Masquer les boutons est acceptable si l’espace est limité, mais un bouton désactivé explique mieux que l’utilisateur est arrivé à une limite. Avec une seule slide, cachez ou désactivez l’ensemble des contrôles : un carrousel qui ne défile pas ne doit pas simuler une interaction.

Réagir au redimensionnement sans casser l’interface

Le responsive ne se limite pas à modifier la largeur des cartes en CSS. Après un changement de fenêtre ou d’orientation, recalculez la position active et replacez le carrousel sur une position valide. Vérifiez aussi les images : des dimensions réservées avant leur chargement évitent que les slides changent de hauteur pendant la navigation. Le chargement différé est utile pour les visuels éloignés, à condition de ne pas retarder l’image immédiatement visible.

Cette vérification concerne aussi les carrousels affichés plusieurs fois sur une même page. Chaque composant doit conserver ses propres boutons, son index actif et sa zone de défilement. Des attributs data-* peuvent aider à relier les contrôles au bon slider sans dépendre d’une structure globale fragile. Le calcul des limites doit toujours s’effectuer pour le conteneur concerné.

Créer une boucle infinie sans saut visible

Un carrousel infini n’est pas une simple remise à zéro de scrollLeft. Si le défilement revient brutalement à la première slide après la dernière, l’utilisateur perçoit un retour arrière. La technique classique consiste à cloner les premières slides à la fin et les dernières au début. Le carrousel commence sur les véritables éléments, passe visuellement par un clone, puis se repositionne instantanément sur l’original équivalent.

Le repositionnement doit être invisible

Lorsque l’utilisateur atteint un clone final, attendez la fin effective du défilement ou détectez une position stable, puis désactivez temporairement l’animation de repositionnement. Déplacez la zone vers la slide originale correspondante et réactivez ensuite le comportement fluide. Ce repositionnement invisible ne doit ni modifier l’index présenté dans la pagination ni provoquer de clignotement.

La même logique s’applique au passage des clones placés avant les véritables slides. Le script doit identifier la position équivalente, corriger le défilement et conserver l’état affiché. Il faut aussi éviter de repositionner le carrousel pendant un mouvement encore actif, car l’utilisateur pourrait percevoir une accélération ou une direction inattendue.

Les clones ne doivent pas créer de doublons pour les lecteurs d’écran. Ils doivent être exclus de la navigation et masqués avec aria-hidden. Les liens ou boutons qu’ils contiennent ne doivent pas rester accessibles au focus. Sans cette précaution, un utilisateur au clavier peut parcourir deux fois le même contenu et perdre le fil de la navigation.

Rendre le carrousel utile à tous les utilisateurs

Un composant accessible donne le contrôle du mouvement à l’utilisateur. Les flèches gauche et droite peuvent faire avancer ou reculer le carrousel lorsque le focus est dans la zone concernée, sans intercepter inutilement les touches ailleurs dans la page. La slide ou la page active peut être indiquée avec aria-current sur le bouton de pagination correspondant. Le focus visible doit rester identifiable à chaque étape.

  • Prévoir un focus visible sur les boutons, les liens et la pagination.
  • Éviter de placer au focus des contenus entièrement hors écran.
  • Mettre à jour l’état actif après un swipe comme après un clic.
  • Respecter prefers-reduced-motion en supprimant ou en réduisant le défilement animé.
  • Si un autoplay existe, fournir un bouton pause et arrêter le mouvement lors d’une interaction utilisateur.

L’autoplay doit rester exceptionnel. Un carrousel qui avance seul empêche souvent la lecture, perturbe la navigation clavier et rend les cartes difficiles à comparer. Si vous l’utilisez pour un contenu secondaire, prévoyez une pause immédiate au survol, au focus et lors de toute interaction tactile. Le bouton pause doit être accessible et son état doit rester compréhensible.

Testez enfin le composant avec zéro slide, une seule slide, des images de tailles variées, une dernière page incomplète et plusieurs carrousels sur la même page. Vérifiez aussi le clavier, le swipe, le focus et la réduction des animations. Ce sont ces cas limites qui transforment une démonstration en composant réutilisable et maintenable.

À lire aussi