Curseurs✨ Premium

Spotlight Reveal

Un contenu caché dans une zone sombre, révélé sous le curseur par un mask CSS radial : deux variables en pourcentage pilotent simultanément la fenêtre de visibilité et le halo coloré qui éclaire ce qu'elle laisse voir.

JSReveal

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

Zone de teaser avant lancement — page coming soon — Spotlight Reveal exemple 1

① Zone de teaser avant lancement — page coming soon

QuandUne page de pré-lancement affiche un fond sombre et une phrase énigmatique. Le visiteur est invité à explorer avec sa souris pour découvrir ce qui se cache.
PourquoiLe mask révèle progressivement la promesse au fil de l'exploration. L'absence de <code>mouseleave</code> joue en ta faveur : les fragments découverts restent lisibles, les révélations s'accumulent. La tension narrative se construit sans JavaScript dédié.
RéglagesFenêtre du mask à 150 px pour un texte long ; halo réduit à 40 px, opacité à 0.12 pour ne pas écraser le texte.
Code promo ou bonus caché — section tarifs ou fidélité — Spotlight Reveal exemple 2

② Code promo ou bonus caché — section tarifs ou fidélité

QuandUn bloc « Avantage secret » invite l'abonné à passer la souris pour découvrir un code de réduction. Le contenu est dans le DOM mais invisible tant que le curseur ne passe pas dessus.
PourquoiLa révélation est instantanée, sans popup. Comme le texte est dans le DOM, le visiteur peut le sélectionner et le copier une fois visible — sans clic supplémentaire. La curiosité est activée sans JavaScript complexe.
RéglagesRayon du mask à 120 px pour tout révéler d'un coup ; couleur de halo sur la marque ; ajoute un état :focus-visible sur la zone pour les utilisateurs clavier.
Titres cachés sur une grille de vignettes — portfolio ou catalogue — Spotlight Reveal exemple 3

③ Titres cachés sur une grille de vignettes — portfolio ou catalogue

QuandUne grille d'images sans légende : chaque vignette porte un titre en surimpression que le visiteur découvre en passant sa souris dessus.
PourquoiAppliqué à chaque cellule via la variante multi-instances décrite en FAQ, l'effet transforme la grille en exploration. Les coordonnées en pourcentage s'adaptent automatiquement à toute taille de cellule — un seul paramétrage.
RéglagesRayon du mask à 80–90 px sur des vignettes de 200–250 px ; texte en gras et contraste élevé pour rester lisible à travers le glow.

Comment ça marche

L'effet repose sur deux couches dans la zone .spotlight-zone. En dessous, le pseudo-élément ::before affiche un texte fantôme à 10 % d'opacité. Au-dessus, le div .spotlight-reveal couvre toute la zone via inset: 0 : il ne cache pas le contenu, il est le contenu — le texte révélé y vit directement. Ce div reçoit simultanément deux radial-gradient pilotés par les mêmes variables --x et --y : un background qui projette un halo indigo (rgba(99, 102, 241, .3), rayon 80 px) et un mask qui découpe une fenêtre circulaire de 100 px. C'est le mask qui fait tout : là où il est noir, l'élément est visible ; là où il est transparent, il disparaît.

L'écouteur mousemove est posé sur #zone-spotlight, pas sur .spotlight-reveal. À chaque mouvement, getBoundingClientRect() relève la géométrie de la zone, et le script calcule les coordonnées en pourcentage : x = ((e.clientX − rect.left) / rect.width) * 100, idem en Y. Ces valeurs sont écrites dans --x et --y via style.setProperty(). Le navigateur recalcule les deux dégradés instantanément — fenêtre et halo bougent ensemble, d'un seul appel. Aucun mouseleave n'est déclaré : quand le curseur quitte la zone, les variables restent figées.

Le choix du mask CSS — plutôt qu'un overlay opaque par-dessus — change la lecture : c'est la couche de contenu qui s'ouvre, pas un couvercle qui se soulève. Ce qui sort du cercle n'est pas rendu, mais reste dans le DOM — le texte caché est accessible aux technologies d'assistance. Les deux rayons — 80 px pour le halo, 100 px pour la fenêtre — sont indépendants. Leur écart de 20 px crée une frange où le mask s'estompe avant que la couleur ne soit nulle : l'illumination paraît fondue, pas coupée net.

Accessibilité

  • prefers-reduced-motion : absent du code. Conditionne l'enregistrement de l'écouteur à window.matchMedia('(prefers-reduced-motion: reduce)') avant tout déploiement — en mode réduit, laisse les variables au repli 50% 50% pour un mask centré et statique.
  • Sur écran tactile, aucun mousemove ne circule : les variables restent aux valeurs par défaut, la fenêtre reste centrée et le contenu y est visible statiquement — repli sain, mais non interactif. Ne fais jamais dépendre une action critique du survol si une partie de ton audience n'a pas de souris.
  • Sans mouseleave, le spotlight reste figé à la dernière position quand le curseur sort. Si le contenu masqué est fonctionnel, ajoute un écouteur mouseleave qui remet --x et --y à 50%.
  • Le contenu de .spotlight-reveal est dans le DOM — le mask ne touche pas à l'arbre d'accessibilité. Mais le texte fantôme du ::before et le texte révélé coexistent pour les technologies d'assistance : si le ::before porte une instruction, déclare-le aria-hidden="true".

Compatibilité navigateur

La propriété mask non préfixée est acquise dans Chrome 120+, Firefox 53+ et Edge 79+. Pour Safari, -webkit-mask est requis jusqu'à 15.3 ; depuis 15.4, l'alias non préfixé fonctionne. Le reste — variables CSS, radial-gradient, inset: 0 — est sans problème. Le JavaScript utilise des fonctions fléchées (ES2015) : IE 11 s'arrête avant le premier événement.

Chrome 120+✓ Complet
Firefox 53+✓ Complet
Safari 15.4+✓ Complet (ajouter -webkit-mask pour 9.1–15.3)
Edge 79+✓ Complet
Mobile iOS✓ Mask statique centré (pas de curseur)
Android Chrome✓ Mask statique centré (pas de curseur)

Sans JavaScript, les variables restent au repli <code>50% 50%</code> : la fenêtre reste centrée et statique, le contenu y est visible — un repli sain, pas un écran vide. Pour couvrir Safari avant 15.4, duplique les deux propriétés avec le préfixe <code>-webkit-mask</code> avant <code>mask</code>. Aucune autre dépendance.

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 mask (100px dans le CSS) 100 px La propriété mask: radial-gradient(circle 100px at …) contrôle la taille de la fenêtre. Augmente cette valeur pour révéler plus d'un coup ; réduis-la pour une fenêtre étroite. Ce rayon est indépendant du halo — garde-les distincts pour conserver la frange de fondu.
Rayon du halo coloré (80px dans le background) 80 px Pilote uniquement la tache lumineuse. Plus petit que le rayon du mask, il crée une zone éclairée qui s'estompe avant le bord de la fenêtre — l'effet lampe torche. Égalise les deux rayons pour un bord net et coloré.
Couleur et opacité du halo (rgba(99, 102, 241, .3)) indigo à 30 % Change les 4 valeurs RGBA pour adapter teinte et intensité. 0.1 = lueur quasi invisible ; 0.7 = halo dominant qui colore le contenu. Sur fond clair, un halo sombre donne un effet de lentille inversée.
Contenu révélé (nœud texte dans .spotlight-reveal) texte simple Remplace le nœud texte par n'importe quel HTML : image, SVG, badge, lien. Le mask s'applique à tout ce qui reste dans .spotlight-reveal. Évite les champs de formulaire — leur zone de clic suit le bord visible du mask, ce qui peut surprendre.
Texte fantôme (::before sur .spotlight-zone) "Déplacez la souris ici" à 10 % d'opacité Change le content pour une autre instruction, baisse l'opacité à 0.05, ou supprime-le si la zone est auto-explicite. Ce pseudo-élément est distinct de .spotlight-reveal et non affecté par le mask.
Comportement au départ du curseur (pas de mouseleave) figé à la dernière position Sans mouseleave, le spotlight reste là où le curseur s'est arrêté. Ajoute un écouteur qui remet --x et --y à 50% pour recentrer au départ. Ou passe à -200% pour sortir le mask de la zone et cacher tout le contenu.

FAQ

La différence est architecturale. Ici, la couche de contenu porte le mask CSS : la fenêtre s'ouvre dans l'élément qui contient le texte, ce qui sort du cercle disparaît. Dans « Cursor Spotlight » (fx-0214), un overlay opaque recouvre le fond, avec un trou transparent au curseur — le contenu est en dessous et le couvercle se soulève. Trois différences de code en plus : fx-0201 calcule en pourcentages, fx-0214 en pixels absolus ; fx-0201 n'a pas de mouseleave, fx-0214 recentre au départ ; fx-0214 cache le curseur système (cursor: none), fx-0201 le laisse visible.
Le code cible deux id via getElementById — une seule paire. Pour plusieurs instances, passe sur querySelectorAll('.spotlight-zone') et boucle en récupérant le .spotlight-reveal enfant et en attachant l'écouteur avec les références locales dans la fermeture. Les variables étant écrites sur le style inline de chaque .spotlight-reveal, les instances sont indépendantes.
Les pourcentages se branchent directement dans radial-gradient(), qui les interprète comme un ratio de la dimension de l'élément. Si la zone est redimensionnée, le prochain mousemove relit getBoundingClientRect() et corrige le positionnement — pas besoin de ResizeObserver, contrairement à une approche en pixels.