Curseurs✨ Premium

Cursor Spotlight

Un voile noir à 95 % percé d'un trou de 120 px qui suit le pointeur, posé sur un contenu gardé à 15 % d'opacité au repos et remonté à 100 % au survol : le texte n'est lisible que sous le projecteur. Le curseur natif reste visible — c'est un éclairage, pas un curseur de remplacement.

JSSpotlight

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

Fiche « bientôt disponible » — caractéristiques dans l'ombre — Cursor Spotlight exemple 1

① Fiche « bientôt disponible » — caractéristiques dans l'ombre

QuandSection de pré-lancement d'un produit : nom, date, trois caractéristiques que l'on découvre en balayant.
PourquoiLe voile matérialise le secret sans le rendre frustrant : tout est là, il suffit de passer la souris. Le fondu de 120 px donne un rendu de lampe torche cohérent avec un objet dévoilé.
RéglagesRayon 160 px pour éclairer une ligne entière de spécifications, voile rgba(0,0,0,.92), opacité de repos .15 conservée.
Visite nocturne — citation d'un artiste sur fond noir — Cursor Spotlight exemple 2

② Visite nocturne — citation d'un artiste sur fond noir

QuandPage d'exposition ou de musée : une citation, son auteur, la date. Rien d'autre à lire.
PourquoiLe projecteur est ici littéral : on éclaire une œuvre dans une salle sombre. Le contenu est court, tenu dans le cercle, et sa lecture n'est pas indispensable à la navigation.
RéglagesRayon 120 px (défaut), opacité de repos abaissée à .1 pour un noir plus profond, transition .5s pour un allumage lent.
Section « sous le capot » — arguments de confidentialité — Cursor Spotlight exemple 3

③ Section « sous le capot » — arguments de confidentialité

QuandLanding d'une application de messagerie ou de stockage : trois garanties techniques présentées comme un coffre.
PourquoiLa métaphore de la lumière sur ce qui est caché sert le message ; l'opacité de repos remontée garde les titres lisibles sans survol, pour que l'argumentaire reste accessible.
RéglagesOpacité de repos .3, rayon 140 px, voile .9, @media (hover: none) qui retire l'overlay sur mobile.

Comment ça marche

Trois couches dans la zone #zone-spotlight-cursor (.spotlight-cursor-zone, 300 px de haut, fond #0f0f1a, overflow: hidden). En dessous, .spotlight-content : position: absolute; inset: 0, colonne flex centrée, opacity: .15 et transition: opacity .3s. Au-dessus, #spotlightOverlay (.spotlight-cursor-overlay) : inset: 0, pointer-events: none et un radial-gradient(circle 120px at var(--spot-x, 50%) var(--spot-y, 50%), transparent 0%, rgba(0,0,0,.95) 100%). Le .info-text, déclaré après l'overlay dans le DOM, reste au-dessus du voile.

Le JS tient en un écouteur mousemove sur la zone : x = (clientX − rect.left) / rect.width × 100, idem pour y, puis spotlightOverlay.style.setProperty('--spot-x', x + '%'). Les coordonnées sont des pourcentages de la zone, donc le centre du dégradé suit le pointeur quelle que soit la taille du conteneur (mesuré : --spot-x: 25%, --spot-y: 50% pour un pointeur au quart de la largeur). Pas de requestAnimationFrame, pas de lissage : le trou est collé au pointeur, et rien ne tourne hors survol (0 appel rAF/s mesuré).

Le dégradé va de transparent au centre à rgba(0,0,0,.95) à 120 px : ce n'est pas un disque net mais un fondu sur 120 px de rayon, après quoi le voile est uniforme à 95 %. Le contenu n'est donc éclairé que dans un cercle d'environ 240 px de diamètre, et c'est le CSS seul qui le rend lisible : .spotlight-cursor-zone:hover .spotlight-content { opacity: 1 }, avec la transition de 300 ms. En sortant, :hover tombe et le contenu redescend à 15 %.

Aucun écouteur mouseleave : les variables --spot-x/--spot-y gardent leur dernière valeur (mesuré : toujours 25 %/50 % après la sortie), si bien qu'à la prochaine entrée le trou est là où on l'avait laissé jusqu'au premier mousemove. Pas de cursor: none : la flèche système reste. Deux détails dans le HTML livré : le h3 porte un style="font-family: Inter, …" en ligne (repli système si Inter n'est pas chargée) et garde ses marges navigateur (20 px mesurés, non remises à zéro).

Accessibilité

  • Contraste au repos volontairement nul : le titre blanc à 15 % d'opacité sur #0f0f1a donne 1,5:1, le paragraphe (rgba(255,255,255,.7)) 1,3:1, et sous le voile hors du cercle 1,07:1. Au survol, sous le projecteur : 19:1 et 9,5:1. Le contenu ne doit donc rien porter d'indispensable, ou être répété ailleurs ; sinon montez l'opacité de repos à .5 (5,3:1 pour le blanc).
  • Sans survol, pas de lecture : au clavier et au tactile, :hover ne s'installe pas de façon fiable et le contenu reste à 15 %. Ajoutez @media (hover: none) { .spotlight-content { opacity: 1 } .spotlight-cursor-overlay { display: none } } et, si la zone contient un élément focusable, .spotlight-cursor-zone:focus-within .spotlight-content { opacity: 1 }.
  • prefers-reduced-motion : le seul mouvement autonome est la transition d'opacité de 300 ms ; le trou suit la main, il n'est pas animé. Rien d'obligatoire, mais @media (prefers-reduced-motion: reduce) { .spotlight-content { transition: none } } évite le fondu pour qui l'a demandé.
  • Lecteurs d'écran : l'overlay est un div vide, le contenu est du DOM ordinaire annoncé normalement quelle que soit sa visibilité — c'est la bonne situation. Le .info-text (« Effet projecteur ») est lu lui aussi : retirez-le ou passez-le en aria-hidden hors démo.
  • Le contenu est en position: absolute; inset: 0 dans une zone à hauteur fixe (300 px) avec overflow: hidden : un texte plus long que la zone est coupé sans défilement. Prévoyez une hauteur en min-height ou un contenu court ; à 200 % de zoom, vérifiez que rien ne disparaît.

Compatibilité navigateur

Requiert les propriétés personnalisées CSS avec setProperty, la propriété raccourcie inset et radial-gradient() avec taille et position explicites. JS ES2015 (fonctions fléchées, const). Zéro dépendance.

Chrome 87+✓ Complet
Firefox 66+✓ Complet
Safari 14.1+✓ Complet
Edge 87+✓ Complet
Mobile iOS✓ Contenu figé à 15 % (pas de survol)
Android Chrome✓ Contenu figé à 15 % (pas de survol)

Sans JavaScript, le trou reste au centre (valeurs de repli 50 %/50 %) et le survol éclaire toujours le contenu : une vignette statique, utilisable. Sans inset (Safari avant 14.1, Firefox avant 66), contenu et overlay perdent leur taille : plus de voile, le contenu s'affiche à 15 % puis 100 % au survol.

Le code

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

index.html — structure
<div class="cursor-zone spotlight-cursor-zone" id="zone-spotlight-cursor">
  <div class="spotlight-content">
    <h3 style="font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;">Contenu Illuminé</h3>
    <p>Le curseur éclaire le contenu</p>
  </div>
  <div class="spotlight-cursor-overlay" id="spotlightOverlay"></div>
  <span class="info-text" style="color: rgba(255,255,255,0.5);">Effet projecteur</span>
</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
Rayon du trou (CSS — circle 120px) 120 px Distance sur laquelle le voile passe de transparent à 95 %. 80 px = lampe de poche étroite ; 200 px = halo large qui dévoile un bloc entier.
Densité du voile (CSS — rgba(0,0,0,.95)) .95 Opacité du noir hors du cercle. .8 laisse deviner le contenu ; 1 le cache totalement (le pointeur est alors la seule fenêtre).
Opacité de repos (CSS — .spotlight-content opacity) .15 Visibilité du contenu sans survol. C'est le réglage d'accessibilité : .5 donne 5,3:1 sur le blanc, 1 laisse tout lisible et ne garde que le voile.
Transition (CSS — .spotlight-content) opacity .3s Durée de l'allumage et de l'extinction du contenu au survol. Le trou, lui, n'est jamais animé (variables non interpolées).
Profil du dégradé (CSS — arrêts 0% / 100%) transparent 0% → noir 100% transparent 45%, rgba(0,0,0,.95) 100% crée un disque clair franc avec un bord fondu court ; deux arrêts identiques donnent un bord net.
Fond de la zone (CSS — .spotlight-cursor-zone background) #0f0f1a Couleur vue à travers le voile et sous le trou. Un fond clair casse l'effet : gardez une teinte sombre, ou montez le voile à 1.
Remise à zéro en sortie (JS — écouteur mouseleave à ajouter) absente setProperty('--spot-x', '50%') et '--spot-y', '50%' dans un mouseleave recentrent le trou, au lieu de le laisser au dernier point survolé.

FAQ

Oui, c'est le comportement livré et il cumule deux choses : le contenu à opacity: .15 et le voile à 95 % par-dessus. Mesuré : 1,5:1 pour le titre au repos, 1,07:1 sous le voile. Si vous voulez un contenu lisible avec un simple effet de lampe au survol, montez l'opacité de repos à 1 et gardez l'overlay : le projecteur devient un éclairage d'ambiance et le texte reste conforme.
Pas avec une transition classique : --spot-x est une variable non typée, le navigateur ne sait pas interpoler entre deux pourcentages et saute d'une valeur à l'autre. Deux voies : enregistrer la variable avec @property --spot-x { syntax: '<percentage>'; inherits: false; initial-value: 50% } puis transition: --spot-x .15s, --spot-y .15s sur l'overlay (Chrome 85+, Safari 16.4+, Firefox 128+) ; ou lisser en JS avec une boucle requestAnimationFrame et un facteur, comme Dot Follower.
Le code n'a pas d'écouteur mouseleave : les variables gardent leur dernière valeur (mesuré 25 %/50 % après la sortie) et le prochain survol les réutilise jusqu'au premier mouvement. Ajoutez zone.addEventListener('mouseleave', () => { overlay.style.setProperty('--spot-x', '50%'); overlay.style.setProperty('--spot-y', '50%'); }). Le contenu, lui, redescend bien à 15 % puisque :hover est géré par le CSS.