Curseurs✨ Premium

Cursor Spotlight

Un voile à 97 % d'opacité couvre toute la zone ; à chaque mousemove, le JS calcule les coordonnées pixel du curseur et les réécrit dans le background de l'overlay — seul un cercle de 90 px reste transparent.

CSSRadial GradientCustom Properties

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

Section de révélation produit — landing page — Cursor Spotlight exemple 1

① Section de révélation produit — landing page

QuandUne landing page veut garder des chiffres clés ou un visuel fort cachés jusqu'à ce que le visiteur les explore activement.
PourquoiLe visiteur est acteur, pas spectateur : la métaphore de la lampe-torche crée une micro-narration — mécanisme de curiosité éprouvé. L'effet est nul sur mobile — ne cache jamais d'informations critiques pour la conversion.
RéglagesRayon JS monté à 120 px pour des passages rapides ; opacité abaissée à 0.85 si tu veux que le contenu reste vaguement devinable en périphérie.
Chasse aux indices — jeu ou onboarding interactif — Cursor Spotlight exemple 2

② Chasse aux indices — jeu ou onboarding interactif

QuandUn parcours d'onboarding ou un jeu veut rendre des instructions découvrables par exploration physique, pas par un clic sur « Voir la réponse ».
PourquoiLe contenu est dans le DOM — lisible par les moteurs de recherche — mais invisible sans interaction active. L'attribut <code>data-spotlight</code> permet plusieurs zones de jeu indépendantes sur la même page sans modifier le JavaScript.
RéglagesRayon réduit à 50–60 px pour rendre la découverte exigeante ; couleur de l'overlay à changer dans les trois occurrences (CSS initial + deux template literals JS) pour éviter un flash de couleur incohérent au mouseleave.
Galerie avec légendes cachées — site d'artiste ou de photographe — Cursor Spotlight exemple 3

③ Galerie avec légendes cachées — site d'artiste ou de photographe

QuandUne galerie plein-écran superpose titre et description à chaque œuvre sans vouloir les afficher en permanence sur l'image.
PourquoiL'overlay masque la légende par défaut et la révèle au passage du curseur — sans fondu ni glissement. Chaque zone portant <code>data-spotlight</code> est équipée automatiquement : ajouter une image à la galerie ne touche pas au JavaScript.
RéglagesContenu de .spotlight-hidden-content remplacé par la légende ; teste rgba(255,255,255,0.92) sur fond clair ; retire cursor: none si tu veux conserver le curseur natif sur les images cliquables.

Comment ça marche

L'effet repose sur un élément .spotlight-overlay positionné en inset: 0 au-dessus du contenu. En CSS, cet overlay démarre avec background: radial-gradient(circle 80px at var(--mouse-x, 50%) var(--mouse-y, 50%), transparent 0%, rgba(10,10,26,0.97) 100%). Le chiffre 0.97 est la clé : à 97 % d'opacité, le fond est presque noir et seul le centre du dégradé laisse passer la lumière. Au repos, ce trou est centré à 50% 50% — une petite fenêtre reste ouverte sans interaction, mais tout le reste du contenu est masqué.

L'écouteur mousemove est posé sur .alchemy-spotlight-zone, le conteneur qui porte le contenu caché et l'overlay. À chaque événement, getBoundingClientRect() lit la position du conteneur ; le script soustrait l'origine pour obtenir des coordonnées en pixels absolus : r = a.clientX - n.left et l = a.clientY - n.top. Ces valeurs sont injectées dans t.style.background : radial-gradient(circle 90px at ${r}px ${l}px, transparent 0%, rgba(10,10,26,0.97) 100%). Le cercle passe à 90 px pendant le mouvement — légèrement plus large qu'au repos — et le JS réécrit l'intégralité du background inline à chaque événement, sans variable CSS intermédiaire.

Un second écouteur mouseleave remet le style.background à radial-gradient(circle 80px at 50% 50%, transparent 0%, rgba(10,10,26,0.97) 100%) : l'ouverture revient brusquement au centre, sans transition. Ce retour sec accentue le sentiment de rideau tiré — c'est un choix délibéré. L'activation passe par querySelectorAll('[data-spotlight]') : toutes les zones portant cet attribut sont équipées en une seule boucle, chaque overlay réagissant exclusivement aux événements de sa propre zone.

Accessibilité

  • prefers-reduced-motion : absent du code. Le dégradé est réécrit à chaque mousemove sans égard pour la préférence système. Conditionne l'enregistrement des écouteurs à window.matchMedia('(prefers-reduced-motion: reduce)'), mais laisse alors une ouverture fixe visible — sinon le contenu caché devient inaccessible en mode mouvement réduit.
  • L'overlay est à pointer-events: none : les liens et boutons de .spotlight-hidden-content restent cliquables et atteignables au Tab. Le curseur est masqué via cursor: none sur la zone — le Tab passe sans problème, mais sans indicateur de focus visible. Définis un état :focus-visible explicite sur chaque élément interactif caché.
  • En dehors du cercle de 90 px, la couche à 97 % d'opacité ramène le contraste à presque zéro — intentionnellement. Si le contenu n'est pas purement décoratif, prévois un bouton « Révéler » ou une version visible par défaut activée uniquement quand JavaScript et un pointeur fin sont disponibles.
  • Sur mobile et tablette, aucun mousemove ne circule : l'overlay reste figé et le trou de 80 px est centré. Tout le contenu hors de ce cercle est invisible et inaccessible au toucher. Réserve cet effet à du contenu décoratif, ou expose le contenu par défaut et conditionne l'overlay à (hover: hover) and (pointer: fine).

Compatibilité navigateur

Le code utilise querySelectorAll, des fonctions fléchées et des template literals — ES2015. IE 11 lève une erreur de syntaxe avant la première exécution. Côté CSS, radial-gradient(circle Xpx at Ypx Zpx, …) est pris en charge sans préfixe dans tous les navigateurs actuels.

Chrome 88+✓ Complet
Firefox 87+✓ Complet
Safari 14+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Overlay figé (pas de curseur)
Android Chrome✓ Overlay figé (pas de curseur)

Sans JavaScript, l'overlay conserve son <code>background</code> CSS initial : un cercle de 80 px centré à <code>50% 50%</code>. Le contenu hors de ce cercle reste masqué — pas un écran noir, mais non découvrable. Pour un repli propre, scope l'overlay à une classe <code>js-ready</code> ajoutée au chargement : sans JS, pas d'overlay.

Le code

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

index.html — structure
🔒 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 cercle pendant le mouvement (90 dans le JS) 90 px La valeur 90px est dans le template literal du mousemove. Augmente pour un faisceau large, réduis pour une torche étroite. Ne confonds pas avec les 80 px du CSS — pendant le mouvement, c'est 90 qui s'applique.
Rayon du cercle au repos (80 dans le CSS et dans mouseleave) 80 px Ce chiffre apparaît dans le background CSS initial et dans le handler mouseleave. Modifie-les ensemble : en les changeant séparément, le cercle saute d'une taille à l'autre au retour du curseur — un à-coup visible.
Opacité de l'overlay (0.97 dans rgba) 0.97 À 0.97, le fond est presque noir. Descends à 0.80 pour un brouillard léger ; monte à 1.0 pour un masque totalement opaque. Mets à jour les trois occurrences — CSS initial, mousemove et mouseleave.
Couleur de l'overlay (10, 10, 26 dans rgba) rgba(10, 10, 26, …) Le triplet 10, 10, 26 produit un bleu-nuit presque noir. Pour un fond blanc, passe à rgba(255,255,255,…). Change les trois occurrences (CSS + deux endroits dans le JS) pour éviter un raccord visible entre le rideau et la page.
Attribut de déclenchement (data-spotlight) [data-spotlight] querySelectorAll('[data-spotlight]') équipe toutes les zones portant l'attribut, sans limite. Pour des paramètres différents par zone, lis el.dataset.spotlightRadius dans la boucle et utilise la valeur dans le template literal — la configuration se fait côté HTML.
Curseur masqué (cursor: none sur .alchemy-spotlight-zone) curseur natif masqué Masquer le curseur renforce l'illusion que le faisceau est le pointeur. Retire cursor: none si tu veux conserver le curseur natif — l'effet fonctionne, mais on voit alors deux cercles se déplacer ensemble (le pointeur + le halo), ce qui réduit l'immersion.

FAQ

Les deux portent un nom proche mais ont des mécaniques opposées. Spotlight Reveal applique un masque CSS (mask: radial-gradient) — le contenu n'est visible que là où le masque est opaque — et le JS écrit les coordonnées en variables CSS pourcentage (--x: 45%). Cursor Spotlight fait l'inverse : un overlay opaque recouvre tout et le JS perce un trou en réécrivant le background en pixels absolus (circle 90px at 312px 87px) à chaque mousemove, sans variable intermédiaire. En pratique, Spotlight Reveal révèle du texte coloré ; Cursor Spotlight masque n'importe quel contenu derrière un vrai rideau et s'active sur autant de zones que nécessaire via data-spotlight.
Le rayon est codé en dur dans le JS (90 px au mouvement). Pour le rendre configurable par zone, stocke-le dans l'attribut HTML : data-spotlight-radius="120", puis lis parseInt(el.dataset.spotlightRadius, 10) || 90 dans la boucle querySelectorAll et utilise cette variable dans le template literal du mousemove. La boucle existante reste intacte.
L'overlay obscurcit sans supprimer : .spotlight-hidden-content reste dans le flux normal, lisible par les moteurs de recherche, et cliquable si pointer-events: none est bien posé sur l'overlay. Ce n'est pas une technique de dissimulation SEO — les robots voient le texte. Si tu veux vraiment masquer du contenu aux moteurs, charge-le via JavaScript après une action explicite de l'utilisateur.