Nouveauté CSS en 2026 – un carousel sans JavaScript avec ::scroll-button

Nouveauté CSS en 2026 avec la propriété scroll-button qui permet de créer un carousel fonctionnel sans JavaScript
Web pratique Lecture 4 minutes

Après la personnalisation des <select> et le Masonry sans JavaScript avec grid-lanes, le CSS continue sa conquête du territoire JavaScript avec une nouvelle propriété pseudo-élément : ::scroll-button(). Elle permet de générer nativement des boutons de navigation pour les conteneurs scrollables, sans écrire une seule ligne de JS.

Pourquoi c’est une vraie amélioration ?

Jusqu'ici, créer un carousel avec des boutons "précédent / suivant" imposait systématiquement du JavaScript : écouter les clics, calculer la position de scroll, gérer les états désactivés en bout de liste… Autant de code à maintenir, à tester et à rendre accessible.

Avec ::scroll-button(), le navigateur prend en charge tout ça nativement :

  • Les boutons sont générés automatiquement par le CSS, sans aucun <button> dans le HTML
  • L'état :disabled est appliqué automatiquement quand le scroll atteint ses limites
  • La navigation au clavier et l'accessibilité sont gérées par le navigateur
  • Combiné à scroll-snap-type, le défilement s'effectue snap par snap, de façon précise

Démo de carousel pur CSS avec ::scroll-button

Démo de Carousel élégant réalisé en HTML et CSS sans aucun code JavaScript. Avec la nouvelle propriété CSS scroll-button.

Note : cette fonctionnalité requiert Chrome 135+ ou Edge 135+

See the Pen Carousel en pur CSS avec ::scroll-button by Tibow (@Tibow) on CodePen.

Le résultat est incroyablement fluide et convaincant. Voyons maintenant les compatibilités navigateurs et comment marche cette petite merveille en détails !

Compatibilité avec les navigateurs modernes

::scroll-button() est une propriété très récente et prometteuse pour 2026, et elle est supportée (pour le moment) uniquement par Chrome et Edge 135 +

Bonne pratique : la dégradation est gracieuse. Sur les navigateurs non compatibles, le conteneur reste scrollable (touch, trackpad, barre de défilement) — les boutons disparaissent simplement. Pas d'erreur, pas de JavaScript à prévoir.

Comment ça fonctionne : sémantique et balisage

Le HTML : minimaliste

Aucun bouton à ajouter dans le markup. Le conteneur scroll suffit :

<div class="carousel">
  <article class="card"><!-- contenu --></article>
  <article class="card"><!-- contenu --></article>
  <article class="card"><!-- contenu --></article>
</div>

Le CSS : tout se passe ici

.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}

/* Bouton "précédent" */
.carousel::scroll-button(inline-start) {
  content: "←";           /* OBLIGATOIRE pour afficher le bouton */
  display: flex;
  width: 3rem;
  height: 3rem;
  background: #1a1612;
  color: white;
  border-radius: 50%;
  cursor: pointer;
}

/* Bouton "suivant" */
.carousel::scroll-button(inline-end) {
  content: "→";
  /* mêmes styles */
}

Les valeurs acceptées par ::scroll-button()

La propriété accepte 4 directions correspondant aux axes logiques CSS :

ValeurDirection
inline-start← (début de ligne, gauche en LTR)
inline-end→ (fin de ligne, droite en LTR)
block-start↑ (début de bloc, haut)
block-end↓ (fin de bloc, bas)

Cela permet de gérer aussi bien les scrolls horizontaux que verticaux, et les contextes RTL (arabe, hébreu) sans aucune adaptation CSS.

La propriété content est obligatoire

Comme pour ::before et ::after, la propriété content est indispensable pour que le pseudo-élément s'affiche. Sans elle, le bouton n'est pas rendu.

/* ❌ Ne s'affiche pas */
.carousel::scroll-button(inline-end) {
  background: black;
}

/* ✅ S'affiche */
.carousel::scroll-button(inline-end) {
  content: "→";
  background: black;
}

Gérer les états :disabled et :hover

Le navigateur applique automatiquement :disabled quand le scroll ne peut plus aller dans une direction. On peut cibler cet état directement :

.carousel::scroll-button(inline-start):disabled,
.carousel::scroll-button(inline-end):disabled {
  opacity: 0.2;
  pointer-events: none;
}

.carousel::scroll-button(inline-end):hover {
  background: #c8502a;
}

Bonus : les points de pagination avec ::scroll-marker

Dans la même spec, ::scroll-marker permet de générer des indicateurs de position (les fameux "dots") eux aussi sans JavaScript :

/* Groupe de dots généré automatiquement */
.carousel::scroll-marker-group {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
}

/* Un dot par élément */
.card::scroll-marker {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: #ccc;
}

/* Dot actif */
.card::scroll-marker:target-current {
  background: #c8502a;
  width: 1.5rem;
  border-radius: 0.25rem;
}

Conclusion

::scroll-button() s'inscrit dans une tendance de fond : le CSS reprend progressivement des interactions que seul JavaScript pouvait gérer jusqu'ici. Après les animations complexes, les transitions de vue avec @view-transition, ou encore la personnalisation des éléments de formulaire, c'est maintenant la navigation des conteneurs scrollables qui bascule côté CSS natif.

Le résultat : un HTML plus sémantique, moins de JavaScript à maintenir, de meilleures performances et une accessibilité gérée nativement par le navigateur.

C'est aujourd'hui limité à Chrome 135+, mais la spec est en bonne voie et Firefox a déjà annoncé son implémentation. À surveiller de près, et à tester dès maintenant sur vos projets CodePen !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *