Neu Slider
De vrais curseurs input type=range habillés en neumorphisme : piste creusée de 10 px, remplissage en dégradé violet qui s'arrête pile sous la poignée, poignée de 24 px en relief, valeur affichée au-dessus. Souris, doigt et clavier, 13 lignes de JavaScript.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Glassmorphism comprend 47 effets, dont 6 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
Chaque curseur est un <input type="range" class="neu-slider"> dans un <label class="neu-slider-group"> qui porte le titre et la valeur. L'apparence native est retirée (appearance: none) et redessinée sur les pseudo-éléments de chaque moteur : la piste (::-webkit-slider-runnable-track, ::-moz-range-track) fait 10 px de haut, border-radius: 5px, creusée par #b8bec7 2px 2px 4px inset et #fff -2px -2px 4px inset ; la poignée (::-webkit-slider-thumb, ::-moz-range-thumb) est un disque de 24 px en relief (ombres 4 px / 8 px, 6 px / 12 px au survol), curseur de souris grab puis grabbing. L'input lui-même fait 24 px de haut, fond transparent : toute la hauteur de la poignée est une zone de prise.
Le remplissage est un second fond de la piste : linear-gradient(135deg, #8b5cf6, #a78bfa) de largeur calc(12px + (100% - 24px) * var(--neu-p)). Le centre de la poignée parcourt la piste de 12 px à la largeur moins 12 px ; avec ce calcul, le dégradé s'arrête exactement sous ce centre, à 0 % comme à 100 %. Le JavaScript tient en 13 lignes : à chaque événement input, il écrit la proportion dans --neu-p et la valeur dans .neu-slider-value (« 75% »). Il s'applique à tous les .neu-slider de la page, sans identifiant.
Pourquoi de vrais <input type="range"> plutôt que des <div> dessinés : un curseur fait de blocs posés à 75 % et 40 % par un style en ligne promet une prise (cursor: grab) mais ne bouge pas — glisser sa poignée de 120 px laisse « 75% », et Tab ne trouve rien à atteindre. L'input natif apporte gratuitement le glisser, le toucher, le clavier et l'annonce aux lecteurs d'écran ; le CSS ne fait que l'habiller. Mesuré dans Chromium, Firefox et WebKit : glisser de 75 % vers la gauche donne 28 %, un toucher sur la piste à 20 % donne 20 %, les flèches avancent d'un point, Fin et Début vont à 100 % et 0 %. Comme toute la famille, .neu-slider-scene porte sa surface (#e0e5ec, padding: 28px, border-radius: 24px).
Accessibilité
- Clavier et lecteurs d'écran : ce sont des
input type="range"natifs. Tab les atteint, les flèches changent la valeur d'un point, Page précédente/suivante de dix, Début et Fin vont aux bornes. Le nom accessible vient du libellé englobant (« Volume », « Luminosité ») ; la valeur affichée portearia-hidden="true"pour ne pas être lue deux fois, puisque le curseur annonce déjà sa valeur. Pour une unité parlée (« 75 pour cent »), ajoutezaria-valuetextdans la fonctionupdate. - Focus : au clavier, la poignée reçoit un anneau plein
#8b5cf6 0 0 0 3px(3,3:1 sur la matière, au-dessus des 3:1 demandés). Le contour du navigateur est retiré (outline: 0), mais seulement parce que cet anneau le remplace. - Contraste : les titres
#6b7280sur#e0e5ecmesurent 3,8:1 et la valeur violette#8b5cf63,3:1, pour 12,5 px : sous le seuil de 4,5:1. Passez-les en#374151(8,1:1) et#6d28d9(5,6:1), comme dans les scènes. Le remplissage violet tranche à 3,3:1 sur la piste ; la poignée, elle, n'existe que par ses ombres (1,5:1). - Tactile : la zone de prise fait 24 px de haut sur toute la largeur (WCAG 2.5.8 demande 24 × 24 px au minimum). Sur un écran pris en main, 32 à 44 px de haut sont plus confortables : agrandissez l'input et la poignée ensemble (voir Personnaliser).
Compatibilité navigateur
CSS : appearance: none, pseudo-éléments de piste et de poignée propres à chaque moteur (-webkit- pour Chrome, Edge et Safari, -moz- pour Firefox, en règles séparées : un sélecteur inconnu invaliderait toute la règle), calc() avec une variable CSS dans background-size, :focus-visible. JavaScript : écouteur input, style.setProperty. Mesuré dans Chromium, Firefox et WebKit 26 (Playwright) : rendu identique (piste de 10 px, poignée centrée), glisser, toucher et clavier fonctionnels, clic jusqu'à 11 px sous le centre de la piste pris en compte dans les trois.
Sans JavaScript, les curseurs restent utilisables (ce sont des inputs natifs) mais la valeur affichée ne suit plus et le remplissage reste à 50 %, la valeur par défaut de --neu-p. Les versions données sont celles de :focus-visible ; avant, tout fonctionne sauf l'anneau de focus au clavier.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :
<div class="neu-slider-scene">
<label class="neu-slider-group">
<span class="neu-slider-header">
<span class="neu-slider-title">Volume</span>
<span class="neu-slider-value" aria-hidden="true">75%</span>
</span>
<input type="range" class="neu-slider" min="0" max="100" value="75">
</label>
<!-- second curseur : même structure -->
</div>
Le code complet HTML + CSS + JS de Neu Slider, 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 |
|---|---|---|
Bornes et pas (HTML — min, max, step, value) |
0 à 100, pas de 1 | Tout se règle sur l'input : min="1" max="5" step="1" pour cinq vitesses de hotte. Le JavaScript calcule la proportion à partir de min et max, le remplissage suit. |
Valeur affichée (JS — out.textContent = s.value + '%') |
valeur suivie de « % » | Remplacez par votre unité (' dB', ' K') ou par un libellé (['Lente', 'Moyenne', 'Forte'][s.value]). Pensez à s.setAttribute('aria-valuetext', …) avec le même texte. |
Couleur du remplissage (CSS — dégradé dans le background des deux pistes) |
#8b5cf6 → #a78bfa | Changez-le dans ::-webkit-slider-runnable-track ET ::-moz-range-track, en gardant la taille calc(12px + (100% - 24px) * var(--neu-p, .5)). Une classe de modificateur permet une couleur par curseur (comme l'ambre de la scène 3). |
Taille de la prise (CSS — input height: 24px, poignée 24 px, margin-top: -7px) |
24 px de haut | Pour 32 px : input et poignée à 32 px, margin-top: -11px sur la poignée WebKit (moitié de 10 − 32), et remplacez les deux 12px / 24px de la formule du remplissage par 16px / 32px. |
Teinte de la matière (CSS — #e0e5ec, ombres #b8bec7 / #fff) |
gris bleuté clair | Piste, poignée et surface .neu-slider-scene partagent la même teinte : changez-les ensemble. |
FAQ
slider.addEventListener('input', () => maj(slider.value)) pour suivre pendant le glisser, change pour la valeur finale. Dans un formulaire, donnez un name à l'input : la valeur part avec les autres champs.