SCRIPTWEBFLOWJAVASCRIPT

Slider avant / après

Deux images superposées, une poignée qui glisse, et le visiteur compare lui-même. Tu poses le script, tu construis trois éléments, c'est en ligne.

/ ÉTAPE 01

Copie-colle ce script dans le <body> de ton site Webflow

Ajoute ce script sur ton site Webflow pour rendre fonctionnel ton slider avant/après.

slider-avant-apres.html
<script>
document.addEventListener('DOMContentLoaded', function() {
  document.querySelectorAll('.before-after').forEach(container => {
    const beforeImg = container.querySelector('.before');
    const afterImg = container.querySelector('.after');
    
    if (!beforeImg || !afterImg) return;
    
    // S'assurer que le conteneur a la bonne position
    if (getComputedStyle(container).position === 'static') {
      container.style.position = 'relative';
    }
    
    // Créer le divider
    const divider = document.createElement('div');
    divider.className = 'slider-divider';
    divider.innerHTML = `
      <div class="slider-line" style="
        position: absolute;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 2px;
        height: 100%;
        background: white;
        z-index: 10;
        box-shadow: 0 0 10px rgba(0,0,0,0.3);
        pointer-events: none;
      "></div>
      <div class="slider-handle" style="
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 40px;
        height: 40px;
        background: white;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        z-index: 11;
        cursor: grab;
        transition: transform 0.2s ease;
        pointer-events: all;
      ">
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
          <path d="m9 7-5 5 5 5"/>
          <path d="m15 7 5 5-5 5"/>
        </svg>
      </div>
    `;
    
    divider.style.cssText = `
      position: absolute;
      top: 0;
      left: 50%;
      transform: translateX(-50%);
      height: 100%;
      z-index: 10;
      pointer-events: none;
    `;
    
    container.appendChild(divider);
    
    const sliderHandle = divider.querySelector('.slider-handle');
    
    // Variables
    let isDragging = false;
    
    // Fonction de mise à jour
    function updateSlider(percentage) {
      const clampedPercentage = Math.max(0, Math.min(100, percentage));
      const rightClip = 100 - clampedPercentage;
      
      beforeImg.style.clipPath = `inset(0 ${rightClip}% 0 0)`;
      divider.style.left = clampedPercentage + '%';
    }
    
    // Fonction pour obtenir la position X
    function getPositionX(e) {
      return e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
    }
    
    // Fonction pour calculer le pourcentage
    function calculatePercentage(clientX) {
      const rect = container.getBoundingClientRect();
      const x = clientX - rect.left;
      return (x / rect.width) * 100;
    }
    
    // Events pour le drag
    function handleStart(e) {
      if (!sliderHandle.contains(e.target)) return;
      
      e.preventDefault();
      isDragging = true;
      
      sliderHandle.style.cursor = 'grabbing';
      document.body.style.userSelect = 'none';
      
      beforeImg.style.transition = 'none';
      divider.style.transition = 'none';
    }
    
    function handleMove(e) {
      if (!isDragging) return;
      
      e.preventDefault();
      const clientX = getPositionX(e);
      const percentage = calculatePercentage(clientX);
      updateSlider(percentage);
    }
    
    function handleEnd(e) {
      if (!isDragging) return;
      
      isDragging = false;
      sliderHandle.style.cursor = 'grab';
      document.body.style.userSelect = '';
    }
    
    // Event listeners
    sliderHandle.addEventListener('mousedown', handleStart);
    document.addEventListener('mousemove', handleMove);
    document.addEventListener('mouseup', handleEnd);
    
    // Touch events
    sliderHandle.addEventListener('touchstart', handleStart);
    document.addEventListener('touchmove', handleMove, { passive: false });
    document.addEventListener('touchend', handleEnd);
    
    // Clic sur le conteneur pour positionner
    container.addEventListener('click', (e) => {
      if (isDragging || sliderHandle.contains(e.target)) return;
      
      const percentage = calculatePercentage(e.clientX);
      beforeImg.style.transition = 'clip-path 0.3s ease';
      divider.style.transition = 'left 0.3s ease';
      updateSlider(percentage);
      
      setTimeout(() => {
        beforeImg.style.transition = 'none';
        divider.style.transition = 'none';
      }, 300);
    });
    
    // Hover sur la poignée
    sliderHandle.addEventListener('mouseenter', () => {
      if (!isDragging) {
        sliderHandle.style.transform = 'translate(-50%, -50%) scale(1.1)';
      }
    });
    
    sliderHandle.addEventListener('mouseleave', () => {
      if (!isDragging) {
        sliderHandle.style.transform = 'translate(-50%, -50%) scale(1)';
      }
    });
    
    // Initialiser la position
    updateSlider(50);
  });
});
</script>

/ ÉTAPE 02

Construis ton slider avant/après

Ajoute une "div" avec la classe "before-after", puis à l'intérieur places-y 2 éléments "image" avec les classes "after" et "before" et ajoute les images de ton choix.

  1. 01Pour le style, réfère-toi à l'exemple de démonstration ou applique les propriétés ci-dessous.
Les propriétés CSS à appliquer aux classes before-after, before et after

/ OÙ LE COLLER

DansWebflow, Paramètres › Custom code

CUSTOM CODE

PARAMÈTRES DU PROJET

Head code

<!-- vide -->

Footer code

<script> … </script>

Les codes personnalisés ne s'appliquent qu'après publication.

Footer code, jamais Head

Le script doit s'exécuter après le contenu de la page. Dans le Head, il ne trouverait rien à animer.

Une seule fois pour tout le site

Il se pose au niveau du projet, pas page par page. Les blocs le trouvent tout seuls.

Publier pour activer

Tant que le site n'est pas publié, le code personnalisé ne tourne pas, même en aperçu.

/ LES OPTIONS

Tout se pilote par classe et par attribut.

.before-after

classe

Le conteneur du slider : le script cherche ses deux images et sa poignée dedans.

.before

classe

L'image de départ, celle que la poignée dévoile.

.after

classe

L'image d'arrivée, posée par-dessus.

.slider-handle

classe

La poignée que le visiteur fait glisser.