Split Compare
Le même composant dans ses deux thèmes, l'un sur l'autre, et un séparateur « VS » qu'on fait glisser pour découvrir l'un ou l'autre : à la souris, au doigt ou aux flèches du clavier, grâce à un curseur natif invisible posé sur toute la scène. 0,45 Ko de JavaScript ; sans script, la comparaison reste fixe à 50 %.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Transitions comprend 52 effets, dont 9 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La scène .th-split-scene (300 × 220 px, coins de 16 px) superpose deux calques de sa taille exacte, en position: absolute; inset: 0 : .th-split-dark (fond #0f172a) dessous et .th-split-light (fond #f8fafc) dessus. Chacun contient le même composant au même endroit — ici une carte de 180 px avec titre et barre de progression, posée dans le bas — et son étiquette, « Sombre » en haut à gauche, « Clair » en haut à droite. Le calque clair est rogné à gauche jusqu'au séparateur : clip-path: inset(0 0 0 var(--th-split-pos)), avec --th-split-pos: 50% par défaut. À 50 %, la carte apparaît coupée en deux, moitié sombre, moitié claire : c'est la comparaison sur un seul objet.
Le geste passe par un vrai <input type="range"> de 0 à 100, étiré sur toute la scène (inset: 0, z-index 3), rendu invisible (opacity: 0, appearance: none, poignée native de 2 px) mais toujours actif, avec un curseur de souris ew-resize. Le navigateur fournit tout le reste : appui n'importe où pour sauter à cet endroit, glissé, toucher, clavier. À chaque évènement input, le script écrit la valeur dans --th-split-pos. Le séparateur visible est un calque de la largeur de la scène, insensible au pointeur, décalé de translateX(var(--th-split-pos)) : son ::before trace le trait dégradé violet-rose de 2 px sur son bord gauche, et la pastille « VS » est centrée sur ce bord, flanquée de deux petites flèches qui disent qu'elle se déplace. Aucune transition : le séparateur suit le geste sans retard.
Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : glissé de 50 à 20 puis 85 %, valeurs exactes et centre de la pastille à 60 puis 255 px ; un simple clic à 30 % y saute ; flèche droite +1, Page précédente +10, Origine 0, Fin 100 ; dans Chromium et Firefox, la touche Tab atteint le curseur et le contour blanc s'affiche autour de la pastille. Au doigt, dans Chromium en émulation mobile : toucher à 25 % donne 25, glisser de 25 à 75 % donne 75. Le script (0,45 Ko) parcourt chaque .th-split-scene de la page : plusieurs comparateurs cohabitent. Sans JavaScript, la scène garde sa coupe fixe à 50 %. L'effet compare deux thèmes, il n'en applique aucun : il ne lit pas prefers-color-scheme et ne mémorise rien.
Accessibilité
- Curseur natif : un
input type="range"annoncé comme curseur (rôleslider) avec sa valeur de 0 à 100 et un nom qui dit ce qui est où : « Séparateur : à gauche le thème sombre, à droite le thème clair ». Clavier mesuré dans les trois moteurs : flèches (1 %), Page précédente / suivante (10 %), Origine et Fin. Le focus clavier dessine un contour blanc de 2 px autour de la pastille, puisque le curseur lui-même est invisible. - Contenu en double : les deux calques portent le même texte ; le calque clair est
aria-hidden, un lecteur d'écran ne lit donc qu'une version. Si la comparaison porte une information (un logo illisible en sombre, par exemple), dites-la aussi en texte à côté. - Mouvement : rien ne bouge tout seul ; le séparateur ne se déplace que sous le doigt, la souris ou le clavier, sans animation. Aucune règle de mouvement réduit n'est donc nécessaire.
- Contraste et toucher : étiquette « Sombre » à 6,1:1, « Clair » à 4,6:1 ; la pastille « VS » est décorative. Le curseur couvre tout le comparateur : sur téléphone, un glissement vertical commencé dessus peut être capté par le curseur au lieu de faire défiler la page (non mesuré sur appareil réel) ; laissez de la marge autour pour défiler.
Compatibilité navigateur
CSS (clip-path: inset() avec une variable, transform, pseudo-éléments, style des curseurs ::-webkit-slider-thumb et ::-moz-range-thumb, :focus-visible) + 0,45 Ko de JavaScript, aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : mêmes valeurs à la souris et au clavier, même position de la pastille au pixel ; toucher mesuré dans Chromium en émulation mobile. clip-path: inset() existe sans préfixe depuis Chrome 55, Firefox 54 et Safari 9.1 ; les propriétés personnalisées depuis Chrome 49, Firefox 31 et Safari 9.1. Le plancher vient de inset: 0, qui superpose les calques : Chrome et Edge 87, Firefox 66, Safari 14.1 (iOS 14.5).
Sans JavaScript, la scène reste coupée à 50 % : les deux thèmes côte à côte, le curseur bouge mais le séparateur ne suit pas. Sans clip-path, le calque clair couvre toute la scène.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="th-split-root">
<div class="th-split-scene">
<div class="th-split-half th-split-dark">
<span class="th-split-label">…</span>
<div class="th-split-mini-card">…</div>
</div>
<div class="th-split-half th-split-light" aria-hidden="true">
<span class="th-split-label">…</span>
<div class="th-split-mini-card">…</div>
</div>
<input class="th-split-range" type="range" min="0" max="100" step="1" value="50" aria-label="…">
<div class="th-split-divider" aria-hidden="true"><span class="th-split-knob">VS</span></div>
</div>
</div>
Le code complet HTML + CSS + JS de Split Compare, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Position de départ (HTML — value du curseur, et CSS — --th-split-pos) |
50 | Mettez la même valeur aux deux endroits (value="30" et --th-split-pos: 30%) pour qu'elle tienne aussi sans JavaScript. |
Pas du clavier (HTML — step) |
1 (1 % par flèche, 10 % par page) | step="5" rend le clavier plus rapide mais fait avancer le glissé par crans de 5 %. Gardez 1 pour un glissé fluide. |
Contenu des calques (HTML — .th-split-dark et .th-split-light) |
une carte de 180 px posée dans le bas | Les deux calques doivent montrer le même contenu au même endroit, sinon la coupe ne compare rien. Deux images de même taille (object-fit: cover) donnent un avant / après photo. |
Trait et pastille (CSS — .th-split-divider::before, .th-split-knob) |
trait de 2 px dégradé #8b5cf6 → #ec4899, pastille « VS » |
Remplacez « VS » par deux chevrons ou une icône ; gardez la pastille au milieu de la hauteur, là où le pouce la cherche. |
Couleurs et étiquettes (CSS — fonds des deux calques, .th-split-label) |
#0f172a / #f8fafc, « Sombre » / « Clair » |
Changez aussi le nom du curseur (aria-label) si les deux côtés ne sont plus des thèmes. |
FAQ
--th-split-pos, en 0,45 Ko. Le curseur est rendu invisible mais garde son focus : c'est la pastille qui affiche le contour.prefers-color-scheme. La position est dans range.value à tout moment, mais une position n'est pas un choix : ajoutez deux boutons (« Garder le sombre », « Garder le clair ») comme dans le premier exemple, et appliquez puis mémorisez le thème retenu avec votre propre code (une classe sur <html>, localStorage).clip-path: inset() et dessinent un trait sur la frontière. Wipe Transition joue le passage tout seul en 0,6 s, d'un thème à l'autre, et s'arrête sur le nouveau. Split Compare ne joue rien : c'est l'utilisateur qui tient la frontière et la laisse où il veut, le temps de comparer. Choisissez Wipe Transition pour basculer, Split Compare pour décider.