GalerieGratuit

Basic Slider

Carrousel à flèches : la piste glisse d'une image à la suivante au clic, aux touches ← → ou au doigt, et repart de la première après la dernière.

CSSTransformArrows

Mis à jour le

Survolez ou cliquez la scène pour interagir

Cet effet est gratuit — la catégorie Galerie en contient 44 au total, dont 6 gratuits. Effect.Labs regroupe 840 effets vanilla. Découvrir la catégorie →

Exemples d'usage

2 personnes · 24 m² · vue sur le lac

148 € / nuit

① Les chambres d'un hôtel au bord d'un lac — bandeau photo de la page Séjour

QuandLe visiteur arrive sur la page Séjour et clique sur › pour passer de la chambre Rive à la chambre Ponton ; sous le bandeau, la ligne de réservation affiche la capacité, la surface et le prix de la chambre visible.
PourquoiUne chambre à la fois, en grand et sans rien autour, c'est ce qui vend une nuit d'hôtel. Le glissement latéral garde le sens de la visite (on avance dans les chambres) et les flèches restent posées sur la photo, là où l'œil se trouve déjà.
RéglagesBandeau pleine largeur : --bsld-width:100%, --bsld-height:100%, --bsld-radius:0, cadre transparent sans marge (--bsld-stage-bg:transparent, --bsld-stage-padding:0), flèches foncées --bsld-arrow-bg:rgba(36,50,58,.42). Photos en <img>, légende déplacée en bas à gauche par le CSS de la page. Le prix suit la diapositive grâce à l'attribut inert que l'effet pose sur les autres.
Trajolle
1 / 3

② Trois écrans de bienvenue — premier lancement d'une appli de covoiturage de quartier

QuandAu premier lancement, une fenêtre présente l'appli en trois étapes ; chaque clic sur › fait glisser l'étape suivante, le compteur passe de 1 / 3 à 3 / 3 et le bouton « C'est parti » s'allume à la dernière.
PourquoiL'utilisateur avance à son rythme et peut revenir en arrière avec ‹ : rien ne défile sans lui, ce qui compte pour un texte à lire. Le même composant que le bandeau photo sert ici de pas à pas, avec un fond blanc et une illustration au lieu d'une photo plein cadre.
RéglagesDiapositives blanches en colonne (image, titre, texte), flèches vertes : --bsld-arrow-bg:#e3f2ec et trait des icônes en #1f7a5c dans le CSS de la scène. Hauteur prise sur la fenêtre (--bsld-height:100%). Le compteur et les barres de progression lisent la diapositive active, l'effet n'a pas été modifié.
Mottebrune Le blog des mots et des livres

CARNET DE LECTURE

Pourquoi les vieux romans nous semblent si lents

Les longues descriptions étaient le cinéma de leur époque : le lecteur n'avait jamais vu la mer, la ville ou la montagne, alors l'auteur lui montrait tout, ligne après ligne.

Aujourd'hui l'image arrive avant le texte, qui doit la rattraper.

« Décrire, c'était voyager à la place du lecteur. »

8 min de lecture · 3 commentaires

③ Le mot oublié du jour — encadré de la colonne d'un blog de lecture

QuandEn marge d'un article, une petite carte montre un mot rare et sa définition ; le lecteur met le focus sur une flèche et feuillette les jours précédents avec ← et →.
PourquoiÀ cette taille, le carrousel est un détail de mise en page qui ne vole pas la vedette à l'article. Le clavier suffit à le parcourir, et le retour à la première carte après la dernière évite un bouton grisé en bout de liste.
RéglagesCarte de 132 px de haut : --bsld-height:132px, --bsld-ratio:auto, --bsld-radius:12px, fond clair et flèches de 28 px redessinées dans le CSS de la scène. Les diapositives ne contiennent que du texte (mot et définition dans .bsld-caption).

Comment ça marche

Les diapositives .bsld-slide sont alignées côte à côte dans .bsld-track, chacune large de 100 % du cadre .bsld-carousel. Changer de diapositive, c'est poser translateX(-100 %), -200 %… sur la piste ; la transition CSS de 0,5 s en ease-out fait le glissement. Après la cinquième, le bouton suivant ramène à la première : la piste revient en arrière en un seul mouvement, elle ne tourne pas en boucle infinie.

Trois façons de naviguer : les boutons ‹ et › (.bsld-prev, .bsld-next), les touches ← et → quand le focus est dans le carrousel (sur l'une des flèches, par exemple), et un glisser horizontal de plus de 50 px, au doigt comme à la souris. Le glisser passe par les Pointer Events ; un mouvement surtout vertical est laissé à la page, qui défile normalement sur mobile. Rien ne bouge tout seul.

Le cadre suit la largeur de son conteneur jusqu'à 640 px et garde un rapport 16/10 (aspect-ratio). Pour vos photos, placez une balise <img> dans la diapositive : elle est recadrée en object-fit: cover et la légende .bsld-caption passe par-dessus. Les dégradés violets ne servent qu'à la démonstration.

Chaque .bsld-carousel est initialisé à part : deux carrousels sur la même page ne se pilotent pas entre eux, aucune variable n'est posée sur window, et un script collé deux fois ne branche rien en double (marque data-bsld-ready).

Accessibilité

  • Rôles du carrousel : le cadre est un <div role="region"> nommé (aria-label) avec aria-roledescription="carrousel" ; le script donne à chaque diapositive role="group", aria-roledescription="diapositive" et un nom « 2 sur 5 ».
  • Ce qui est caché l'est vraiment : les diapositives hors du cadre reçoivent inert et aria-hidden ; un lien posé sur une image masquée n'est donc pas atteint au Tab.
  • Annonce du changement : un paragraphe invisible en aria-live="polite" dit « diapositive 3 sur 5 » après chaque clic, touche ou glisser ; rien n'est annoncé au chargement.
  • Flèches nommées : vrais <button type="button"> « Diapositive précédente » et « Diapositive suivante », anneau blanc au focus clavier, icônes SVG cachées des lecteurs d'écran.
  • Mouvement réduit : sous prefers-reduced-motion: reduce la piste change de place sans glisser ; les flèches, le clavier et le doigt fonctionnent toujours.

Compatibilité navigateur

Environ 3,5 Ko de JavaScript sans dépendance. Mesuré le 08/11/2026 dans Chromium, Firefox et WebKit (Playwright) : deux copies indépendantes, script collé deux fois, Tab puis Entrée, touches ← →, glisser au doigt à 390 px (Chromium) et à la souris (Firefox, WebKit), mouvement réduit, aucune erreur. Versions minimales tirées de @mdn/browser-compat-data 8.1.8 : inert fixe le plancher (Chrome 102, Firefox 112, Safari 15.5).

Chrome 102+✓ Complet (mesuré)
Firefox 112+✓ Complet (mesuré)
Safari 15.5+✓ Complet (mesuré dans WebKit)
Edge 102+✓ Complet (moteur Chromium)
iOS Safari 15.5+✓ Non vérifié sur appareil réel
Android Chrome 102+✓ Complet (moteur Chromium)

Avant inert (Chrome 88-101, Firefox 89-111, Safari 15-15.4) tout fonctionne, mais un lien placé dans une diapositive masquée reste atteignable au Tab. Avant Safari 15 (et avant Chrome 88, Firefox 89), aspect-ratio manque : donnez une hauteur avec --bsld-height. Sans JavaScript, la première diapositive reste affichée et les flèches ne font rien.

Le code

Copiez les trois blocs dans votre page. Aucune dépendance.

HTML
<div class="fx-0161-root">
  <div class="bsld-carousel" role="region" aria-roledescription="carrousel" aria-label="Diaporama" data-slide="diapositive" data-of="sur">
    <div class="bsld-track">
      <div class="bsld-slide"><span class="bsld-caption">Slide 1</span></div>
      <div class="bsld-slide"><span class="bsld-caption">Slide 2</span></div>
      <div class="bsld-slide"><span class="bsld-caption">Slide 3</span></div>
      <div class="bsld-slide"><span class="bsld-caption">Slide 4</span></div>
      <div class="bsld-slide"><span class="bsld-caption">Slide 5</span></div>
    </div>
    <button type="button" class="bsld-arrow bsld-prev" aria-label="Diapositive précédente">
      <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M15 18l-6-6 6-6"/></svg>
    </button>
    <button type="button" class="bsld-arrow bsld-next" aria-label="Diapositive suivante">
      <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 18l6-6-6-6"/></svg>
    </button>
  </div>
</div>
CSS
.fx-0161-root,
.fx-0161-root *,
.fx-0161-root *::before,
.fx-0161-root *::after {
  box-sizing: border-box;
}

/* Cadre de démonstration : fond, marge intérieure et hauteur minimale réglables */
.fx-0161-root {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--bsld-stage-min-height, 250px);
  padding: var(--bsld-stage-padding, 25px 16px);
  background: var(--bsld-stage-bg, #1a1a24);
  color: #fff;
  font-family: sans-serif;
}

/* Le carrousel prend la largeur de son conteneur, jusqu'à --bsld-width ; hauteur = largeur × ratio */
.bsld-carousel {
  position: relative;
  width: 100%;
  max-width: var(--bsld-width, 640px);
  height: var(--bsld-height, auto);
  aspect-ratio: var(--bsld-ratio, 16 / 10);
  overflow: hidden;
  overflow: clip; /* le cadre ne peut pas défiler tout seul (focus, scrollIntoView) */
  border-radius: var(--bsld-radius, 1rem);
  background: #12121a;
}

.bsld-track {
  display: flex;
  height: 100%;
  transition: transform var(--bsld-duration, 0.5s) ease-out;
  touch-action: pan-y; /* le doigt fait défiler la page à la verticale, le carrousel à l'horizontale */
  user-select: none;
  -webkit-user-select: none;
}

.bsld-slide {
  position: relative;
  flex: 0 0 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Vos photos : <img> dans la diapositive, recadrée pour la remplir */
.bsld-slide > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
}

.bsld-caption {
  position: relative;
  font-weight: 600;
  font-size: 1.2rem;
  color: #fff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.35);
}

/* Fonds de démonstration (remplacés par vos images) */
.bsld-slide:nth-child(1) { background: linear-gradient(135deg, #6366f1, #8b5cf6); }
.bsld-slide:nth-child(2) { background: linear-gradient(135deg, #8b5cf6, #d946ef); }
.bsld-slide:nth-child(3) { background: linear-gradient(135deg, #d946ef, #f43f5e); }
.bsld-slide:nth-child(4) { background: linear-gradient(135deg, #f43f5e, #f97316); }
.bsld-slide:nth-child(5) { background: linear-gradient(135deg, #f97316, #eab308); }

.bsld-arrow {
  position: absolute;
  top: 50%;
  z-index: 10;
  width: 36px;
  height: 36px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateY(-50%);
  background: var(--bsld-arrow-bg, rgba(255, 255, 255, 0.2));
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.3s ease, transform 0.3s ease;
}

.bsld-arrow:hover {
  background: rgba(255, 255, 255, 0.4);
  transform: translateY(-50%) scale(1.1);
}

.bsld-arrow:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.bsld-arrow svg {
  width: 18px;
  height: 18px;
  stroke: #fff;
  stroke-width: 2;
  fill: none;
}

.bsld-prev { left: 10px; }
.bsld-next { right: 10px; }

/* Texte lu par les lecteurs d'écran seulement */
.bsld-status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Mouvement réduit : le changement de diapositive reste, mais sans glissement */
@media (prefers-reduced-motion: reduce) {
  .bsld-track,
  .bsld-arrow {
    transition: none;
  }
}
JavaScript (fx-0161)
(function () {
  // Basic Slider : la piste glisse d'une diapositive à l'autre (flèches, touches ← →, glisser au doigt ou à la souris).
  // Chaque .bsld-carousel de la page a sa propre instance ; rien n'est déclaré sur window.
  function init(car) {
    if (car.hasAttribute('data-bsld-ready')) return; // script collé deux fois : rien n'est branché deux fois
    var track = car.querySelector('.bsld-track');
    var slides = track ? track.querySelectorAll('.bsld-slide') : [];
    if (!slides.length) return;
    car.setAttribute('data-bsld-ready', '');
    var prev = car.querySelector('.bsld-prev');
    var next = car.querySelector('.bsld-next');
    var word = car.getAttribute('data-slide') || 'slide';
    var of = car.getAttribute('data-of') || 'of';
    var n = slides.length;
    var index = 0;

    // annonce « diapositive 2 sur 5 » aux lecteurs d'écran après chaque changement
    var status = document.createElement('p');
    status.className = 'bsld-status';
    status.setAttribute('aria-live', 'polite');
    car.appendChild(status);

    for (var i = 0; i < n; i++) {
      slides[i].setAttribute('role', 'group');
      slides[i].setAttribute('aria-roledescription', word);
      slides[i].setAttribute('aria-label', (i + 1) + ' ' + of + ' ' + n);
    }

    function go(k, announce) {
      index = ((k % n) + n) % n; // en boucle : après la dernière, la première
      track.style.transform = 'translateX(' + (-100 * index) + '%)';
      for (var i = 0; i < n; i++) {
        // diapositives cachées : hors du Tab et des lecteurs d'écran
        if (i === index) {
          slides[i].removeAttribute('inert');
          slides[i].removeAttribute('aria-hidden');
        } else {
          slides[i].setAttribute('inert', '');
          slides[i].setAttribute('aria-hidden', 'true');
        }
      }
      if (announce) status.textContent = (car.getAttribute('data-slide') || word) + ' ' + (index + 1) + ' ' + (car.getAttribute('data-of') || of) + ' ' + n;
    }

    if (prev) prev.addEventListener('click', function () { go(index - 1, true); });
    if (next) next.addEventListener('click', function () { go(index + 1, true); });

    car.addEventListener('keydown', function (e) {
      if (/^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName) || e.target.isContentEditable) return;
      if (e.key === 'ArrowLeft') { e.preventDefault(); go(index - 1, true); }
      if (e.key === 'ArrowRight') { e.preventDefault(); go(index + 1, true); }
    });

    // Glisser (Pointer Events : doigt, souris, stylet) : plus de 50 px à l'horizontale change de diapositive
    var x0 = null, y0 = 0, dragged = false;
    track.addEventListener('pointerdown', function (e) {
      if (e.pointerType === 'mouse' && e.button !== 0) return;
      x0 = e.clientX; y0 = e.clientY; dragged = false;
    });
    track.addEventListener('pointerup', function (e) {
      if (x0 === null) return;
      var dx = e.clientX - x0, dy = e.clientY - y0;
      x0 = null;
      if (Math.abs(dx) > 50 && Math.abs(dx) > Math.abs(dy)) {
        dragged = true;
        go(index + (dx < 0 ? 1 : -1), true);
      }
    });
    track.addEventListener('pointercancel', function () { x0 = null; });
    // un glisser à la souris ne doit pas ouvrir le lien posé sur la diapositive
    track.addEventListener('click', function (e) {
      if (dragged) { e.preventDefault(); e.stopPropagation(); dragged = false; }
    }, true);
    track.addEventListener('dragstart', function (e) { e.preventDefault(); });

    go(0, false);
  }
  Array.prototype.forEach.call(document.querySelectorAll('.bsld-carousel'), init);
})();

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Largeur maximale (CSS — --bsld-width sur .fx-0161-root) 640px Le carrousel prend toute la largeur disponible jusqu'à cette valeur. 100% pour un bandeau sans limite.
Proportions (CSS — --bsld-ratio) 16 / 10 Hauteur calculée depuis la largeur. 4 / 3 pour des photos de produit, 21 / 9 pour un bandeau.
Hauteur fixe (CSS — --bsld-height) auto Une valeur (320px, 100%) remplace le calcul par les proportions ; utile dans un bloc à hauteur imposée.
Durée du glissement (CSS — --bsld-duration) 0.5s Temps de la transition de la piste, en ease-out. Sans effet sous mouvement réduit.
Arrondi et fond des flèches (CSS — --bsld-radius, --bsld-arrow-bg) 1rem · blanc à 20 % Sur des photos claires, foncez les flèches : --bsld-arrow-bg: rgba(0,0,0,.45).
Cadre de démonstration (CSS — --bsld-stage-bg, --bsld-stage-padding, --bsld-stage-min-height) #1a1a24 · 25px 16px · 250px Le fond et la marge autour du carrousel. Dans votre page : transparent, 0 et 0.
Textes lus à voix haute (HTML — aria-label, data-slide, data-of sur .bsld-carousel) Diaporama · diapositive · sur Nom du carrousel et mots de l'annonce « diapositive 2 sur 5 ». Les libellés des flèches se changent sur les boutons.
Vos images (HTML — <img> dans .bsld-slide) dégradés de démonstration L'image couvre la diapositive ; gardez un alt qui décrit la photo. Autant de diapositives que vous voulez : le script les compte.

FAQ

Peut-on faire défiler le carrousel automatiquement ?

Pas dans ce code : il ne bouge que sur une action de la personne. Si vous ajoutez un minuteur qui clique sur .bsld-next, prévoyez un bouton pause, l'arrêt au survol et au focus, et rien sous prefers-reduced-motion : un défilement de plus de cinq secondes sans pause n'est pas accessible.

Pourquoi le retour de la dernière à la première diapositive traverse-t-il toutes les autres ?

La piste revient simplement à translateX(0) : le glissement repasse donc devant les diapositives intermédiaires. Pour enchaîner sans ce retour en arrière, il faut des copies aux deux bouts de la piste, ce que fait l'effet Infinite Loop de la même catégorie.

La diapositive reste-t-elle bien cadrée quand la fenêtre change de taille ?

Oui. La position est donnée en pourcentage de la largeur de la piste (translateX(-200%) pour la troisième), pas en pixels : quand la fenêtre ou la colonne change de largeur, la diapositive affichée reste en place sans aucun recalcul, et sans ResizeObserver.