Curseurs✨ Premium

Cursor Color Sampler

Un anneau blanc de 28 px suit le pointeur sans délai ; à chaque mousemove, elementFromPoint identifie la case survolée et copie son background inline dans --sampler-color : le disque central et le halo (20 et 40 px) prennent la couleur, le halo en 150 ms. La grille masque le pointeur natif (cursor: none).

JSCSS VariablesColor

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Curseurs comprend 26 effets, dont 1 gratuits. Découvrir la catégorie →

3 exemples d'usage

Palette d'un éditeur de thème — 18 nuances à survoler — Cursor Color Sampler exemple 1

① Palette d'un éditeur de thème — 18 nuances à survoler

QuandPanneau latéral d'un outil de design : la palette du thème en grille, un en-tête et la valeur courante.
PourquoiL'anneau qui prend la couleur qu'il survole est une pipette sans clic : l'utilisateur voit la teinte isolée du reste de la palette, avec son halo, avant de choisir. Le suivi immédiat (pas de transition sur la position) convient à un outil de précision.
RéglagesGrille repeat(6, 1fr) × repeat(3, 1fr), anneau réduit à 22 px, halo 0 0 14px / 0 0 28px, valeur hexadécimale de la case affichée dans l'en-tête à partir de --sampler-color.
Nuancier de peinture — choisir un coloris — Cursor Color Sampler exemple 2

② Nuancier de peinture — choisir un coloris

QuandFiche produit d'une peinture murale : grille de coloris mats, nom de la gamme, prix du testeur.
PourquoiSur des teintes claires et terreuses, le halo coloré autour de l'anneau donne un aperçu « pot ouvert » de la couleur ; c'est l'argument de vente d'un nuancier. Les cases claires imposent ici la bordure sombre recommandée en accessibilité.
RéglagesBordure de l'anneau #1c1917 (≥ 4,4:1 sur toutes les cases), halo élargi 0 0 30px / 0 0 60px pour un rendu « lumière du pot », transition: box-shadow .25s.
Carte de chaleur — lecture case par case — Cursor Color Sampler exemple 3

③ Carte de chaleur — lecture case par case

QuandWidget de tableau de bord : fréquentation par heure sur une grille 8 × 4, du bleu pâle au bleu profond.
PourquoiSur une carte de chaleur, l'anneau isole la case sous le pointeur et son halo en reprend l'intensité — une aide à la lecture des nuances proches, que l'œil distingue mal côte à côte. Le texte de valeur reste indispensable (couleur seule insuffisante).
RéglagesGrille repeat(8, 1fr) × repeat(4, 1fr), anneau 20 px à bordure 2 px, halo 0 0 12px / 0 0 24px ; les cases portent leur valeur dans un data-value affiché dans la légende.

Comment ça marche

La zone .sampler-zone est une grille CSS de 5 colonnes × 3 rangées (repeat(5, 1fr) / repeat(3, 1fr)), 100% × 300px, position: relative, cursor: none. Ses quinze .sampler-cell n'ont ni contenu ni CSS de couleur : chacune porte son fond en ligne, style="background:#6366f1" (indigo, rose, ambre, émeraude, cyan, violet…). Mesuré : des cases de 148,8 × 100 px dans une zone de 744 px. Le premier enfant, .sampler-cursor, est l'anneau : position: absolute, 28 px, border: 3px solid #fff, rond, pointer-events: none, translate(−50%, −50%), z-index: 10.

La couleur voyage par une variable CSS. L'anneau a box-shadow: 0 0 20px var(--sampler-color, rgba(255,255,255,.5)), 0 0 40px var(--sampler-color, rgba(255,255,255,.3)) avec transition: box-shadow .15s, et son ::after (inset: 3px, rond, opacity: .8) a background: var(--sampler-color, white). Tant que la variable n'existe pas, halo blanc et disque blanc. À chaque mousemove, le script positionne l'anneau en left/top (aucune transition sur la position : suivi immédiat), l'affiche, puis appelle document.elementFromPoint(clientX, clientY). Si l'élément trouvé porte la classe sampler-cell, il écrit sur la zone --sampler-color = target.style.background || target.style.backgroundColor — la valeur inline, renvoyée par le navigateur sous la forme rgb(234, 179, 8) (mesuré sur la case jaune). Le disque change à l'instant, le halo en 150 ms.

Deux détails rendent cela possible. L'anneau est en pointer-events: none : sans cela, elementFromPoint le renverrait lui-même et la couleur ne changerait jamais. Et le script lit target.style, c'est-à-dire uniquement l'attribut style : une case colorée par une classe ou une feuille de style renvoie une chaîne vide, la variable n'est pas mise à jour et l'anneau garde la couleur précédente. Le CSS contient aussi .sampler-cell { transition: filter .3s } sans qu'aucune règle ne modifie jamais filter — une transition sans rien à animer, déjà inerte dans la page d'origine.

mouseenter affiche l'anneau, mouseleave le cache (display: none en ligne) — la variable, elle, conserve la dernière couleur. Le CSS livré pose display: none sur .sampler-cursor : avant le premier survol, rien n'est visible — sans cet état initial, l'anneau blanc et son halo blanc apparaissaient dans le coin haut-gauche de la grille, à −6/−6 px (mesuré). Le pointeur natif étant masqué par cursor: none, l'anneau est le seul repère de position dans la grille ; il est blanc à 3 px, ce qui compte pour la lisibilité sur les cases claires (voir Accessibilité).

Accessibilité

  • prefers-reduced-motion : le seul mouvement animé est la transition du halo (150 ms) ; le suivi de l'anneau est instantané. Sous @media (prefers-reduced-motion: reduce), mettez .sampler-cursor { transition: none } — et, si vous préférez désactiver l'effet, retirez aussi cursor: none, sinon la grille n'a plus de pointeur du tout.
  • cursor: none supprime le pointeur natif sur toute la grille : l'anneau le remplace, mais il n'existe que si le script tourne et n'est correctement placé qu'après le premier mousemove. Sans JavaScript, la grille est un trou sans pointeur (l'anneau, en display: none, n'apparaît jamais). Déclarez cursor: none sous une classe posée par le script (.js .sampler-zone).
  • Contraste de l'anneau : blanc sur les quinze cases, il mesure 4,5:1 sur l'indigo #6366f1 mais 1,9:1 sur le jaune #eab308, 2,0:1 sur le vert #84cc16, 1,8:1 sur le cyan #22d3ee — sous le seuil de 3:1 d'un indicateur graphique sur sept cases sur quinze. Passez la bordure en #0a0a0f (≥ 4,4:1 sur les quinze) ou gardez le blanc avec un filet sombre : box-shadow: 0 0 0 1px #0a0a0f, 0 0 20px var(--sampler-color), ….
  • La couleur seule ne suffit pas (WCAG 1.4.1) : la case survolée n'est désignée que par la teinte du halo, et les cases sont des div vides sans nom. Si le nuancier est un vrai sélecteur, donnez à chaque case role="button", tabindex="0" et un aria-label (« Indigo, #6366f1 »), et affichez la valeur échantillonnée en texte (le code hexadécimal) à côté de l'anneau. Au tactile, aucun mousemove ne déplace l'anneau : son display: none initial évite qu'il reste figé dans un coin.
  • Intégration : les fonds des cases doivent être en ligne (style="background:…"), ou remplacez la lecture par getComputedStyle(target).backgroundColor ; l'anneau doit être un enfant de la zone (zone.querySelector('.sampler-cursor')) et rester en pointer-events: none ; la grille fixe 5 × 3 dans le CSS — adaptez grid-template-columns/rows à votre nombre de cases, sinon les surnuméraires créent une rangée implicite. Hauteur explicite obligatoire (les cases n'ont pas de hauteur propre). La remise à zéro à la sortie est faite (display: none).

Compatibilité navigateur

Code ES5 (var, function). Il requiert document.elementFromPoint, les propriétés personnalisées CSS (var(), setProperty) et la grille CSS. Zéro dépendance.

Chrome 57+✓ Complet
Firefox 52+✓ Complet
Safari 10.1+✓ Complet
Edge 16+✓ Complet
Mobile iOS✓ Inerte (pas de pointeur)
Android Chrome✓ Inerte (pas de pointeur)

Sans JavaScript, la grille de couleurs s'affiche mais le pointeur natif est masqué (cursor: none) et l'anneau, en display: none, n'apparaît pas : aucun curseur dans la grille — réservez cursor: none à une classe ajoutée par le script. Sans var() (navigateurs de 2016), les déclarations box-shadow et background du disque sont invalides : anneau blanc sans halo ni disque. Sans grille CSS, les cases, vides et sans hauteur, ne mesurent 0 px : rien n'est visible.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="sampler-zone" data-color-sampler>
  <div class="sampler-cursor"></div>
  <div class="sampler-cell" style="background:#6366f1;"></div>
  <div class="sampler-cell" style="background:#ec4899;"></div>
  <!-- … 15 au total, une par couleur … -->
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

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

Option / propriétéDéfautEffet
Grille (CSS — repeat(5, 1fr) / repeat(3, 1fr)) 5 colonnes × 3 rangées Nombre de cases par ligne et par colonne. Le CSS fixe la grille : avec 18 cases, passez à repeat(6, 1fr), sinon les trois dernières forment une quatrième rangée implicite qui écrase la hauteur.
Couleurs des cases (HTML — style="background:…") 15 teintes vives (#6366f1 … #a855f7) Le script lit l'attribut style : la couleur doit être en ligne. Hexadécimal, rgb() ou hsl() sont acceptés, le navigateur renvoie du rgb(). Un dégradé en ligne fonctionne aussi comme halo (la chaîne complète est copiée), pas comme couleur de disque.
Anneau (CSS — .sampler-cursor 28 px, bordure 3 px #fff) 28 px, blanc, 3 px Diamètre et couleur du seul pointeur de la grille. Blanc, il passe sous 3:1 sur les cases claires ; #0a0a0f tient sur toutes. Le disque intérieur suit via inset: 3px : gardez inset égal à l'épaisseur de bordure.
Halo (CSS — 0 0 20px … , 0 0 40px …, transition: box-shadow .15s) 20 px + 40 px, 150 ms Deux ombres portées dans la couleur échantillonnée. Doublez les rayons pour un rendu « lampe » ; 0 ms rend le changement instantané comme le disque. Les replis rgba(255,255,255,.5) et .3 s'appliquent avant le premier échantillon.
Disque central (CSS — ::after, opacity: .8, inset: 3px) couleur échantillonnée à 80 % Aperçu plein de la couleur. opacity: 1 pour la couleur exacte ; supprimez le pseudo-élément pour un anneau creux qui laisse voir la case.
Source de la couleur (JS — target.style.background) attribut style de la case Remplacez par getComputedStyle(target).backgroundColor pour échantillonner des cases colorées par classe — au prix d'un calcul de style par mouvement, négligeable sur une grille.
cursor: none (CSS — .sampler-zone) pointeur natif masqué Indispensable pour que l'anneau remplace la flèche, dangereux sans JavaScript. Déclarez-le sous une classe posée par le script ; l'état initial de l'anneau est déjà couvert par son display: none.

FAQ

Par le display: none de la règle .sampler-cursor. Positionné en absolu sans left/top, l'anneau se trouve à l'origine de la grille, décalé d'un demi-diamètre par translate(−50%, −50%) (−6/−6 px) — c'est là qu'il apparaissait, avec son halo blanc de repli, tant que cet état initial n'existait pas (mesuré). Le script écrit display: block en ligne au mouseenter et au mousemove, ce qui l'emporte sur la règle, puis display: none au mouseleave. Retirez la déclaration CSS et l'anneau réapparaît dans le coin dès le chargement — y compris au tactile, où aucun mousemove ne viendra le déplacer.
Presque toujours la source de la couleur. Le script lit target.style.background || target.style.backgroundColor, c'est-à-dire l'attribut style de la case, rien d'autre. Si vos cases sont colorées par une classe (.swatch-indigo { background: #6366f1 }), la lecture renvoie une chaîne vide, setProperty écrit une valeur vide et l'anneau garde sa couleur précédente ou son blanc de repli. Deux solutions : mettre la couleur en ligne, ou remplacer la lecture par getComputedStyle(target).backgroundColor. Vérifiez aussi que l'élément sous le pointeur est bien la case : un enfant (texte, icône) placé dans la case fait échouer le test classList.contains('sampler-cell') — utilisez target.closest('.sampler-cell').
La couleur échantillonnée est déjà disponible : zone.style.getPropertyValue('--sampler-color') renvoie rgb(234, 179, 8). Écoutez click sur la zone et copiez cette valeur dans un champ ou un libellé ; convertissez en hexadécimal si besoin. Pour l'accessibilité, chaque case doit devenir un contrôle : role="button", tabindex="0", aria-label avec le nom et le code de la couleur, et un style :focus-visible — l'anneau ne suit pas le clavier. Affichez la valeur courante en texte près de l'anneau : la couleur seule ne peut pas être la seule information.