Build a spotlight effect in Webflow that follows the cursor across a hero image — a soft cone of light that reveals the photo where you point and lets everything else dissolve into darkness. It looks like something you’d need WebGL or a heavy plugin for, but it’s really just a radial gradient and one of Webflow’s oldest interactions, dressed up with a little math.
Then we push further. On top of the spotlight we layer a GSAP-powered hover animation that gently scales and rotates the image, and for the grand finale a custom SVG prism filter that splits the image into its red, green, and blue channels and shifts them apart for a premium color-shift glow. Three techniques, stacked, that add up to a hero section that feels genuinely alive.
The nicest part is how approachable each piece is on its own. The spotlight and the hover are pure Webflow — no code at all. The prism is the only part that needs a snippet, and it’s already written for you in the cloneable. Take it one layer at a time and you’ll walk away with a handful of tricks you can reuse everywhere.
How it works
The spotlight isn’t light at all — it’s darkness with a hole in it. You put a full-bleed div (the overlay) over the image and give it a radial gradient that’s transparent in the middle and black at the edges. The trick is tightening the color stops: a lazy fade looks like fog, so pulling the black in close (with a couple of semi-transparent stops around it) gives you a crisp circle of visibility that reads as a real spotlight. Crucially, the overlay lives between the image and the content in the navigator, so it darkens the photo but leaves your heading and text untouched on top.
To make it follow the cursor, you use the classic “mouse move over element” interaction on the section, moving the overlay from -50vw to 50vw across the X axis and -50vh to 50vh across the Y axis. Those are the exact distances from the center of the viewport to each edge, so the center of the spotlight lands precisely under the pointer. Bump the smoothing up around 95% and the motion turns silky. The catch: an absolutely positioned overlay only covers its parent, so the instant it moves it exposes an edge. The fix is to oversize it — scale width and height to 200%, then offset it -50% on top and left to recenter — so it always blankets the viewport no matter where the cursor pushes it. Setting the section’s overflow to hidden hides anything that spills past the edges.
There’s a stacking-context lesson baked in here too. The absolutely positioned image naturally sits above a static container, so simply reordering things in the navigator won’t put your content on top. Give the main container position: relative and both elements share the default z-index: auto — at which point DOM order wins, and the element that comes later renders on top. It’s a small setting with an outsized payoff, and worth internalizing because it bites people constantly.
The hover animation shows off the new GSAP-powered interactions. Instead of building separate “hover in” and “hover out” animations like the old system forced you to, you build one timeline (scale the image to 1.1, rotate it 3°) and set two triggers: mouse enter set to play and mouse leave set to reverse. Because it plays from its current position rather than restarting, flicking the cursor in and out feels continuous instead of jumpy. The prism is the finale: an SVG filter (its ID is prism-basic) splits the image into RGB channels via feColorMatrix, offsets each with feOffset, and recombines them with feBlend. Applied to the image with filter: url(#prism-basic), it does nothing at rest because the offsets are zero — the channels recombine perfectly. A small GSAP script grabs those feOffset nodes and animates their dx/dy values on hover (and on focus, for keyboard users), pulling the colors apart into that chromatic glow. Two gotchas: the filter embed must sit before the section in the DOM so it’s defined before it’s referenced, and the script goes at the end of the page so everything exists when it runs.
How to use it
-
Clone the project. Grab the Webflow cloneable — it ships with the full hero structure, the tuned radial gradient, the interactions, and the SVG filter plus the GSAP script already written.
-
Pick a high-contrast image. The effect lives or dies on the photo. Choose one with bold light-and-dark areas, strong gradients, and striking highlights — flat images look dull under the spotlight. Paweł Czerwiński’s Unsplash profile is a goldmine for exactly this style. Set the image to
width: 100%,height: 100%,object-fit: cover,position: absolute(full), and give its parent containerposition: relativeso your content stays on top. -
Build the spotlight overlay. Add a div between the image and the content, position it absolute (full), and give it a radial gradient that goes from transparent in the center to black at the edges. Tighten the stops until the circle of light feels crisp rather than foggy, then scale the overlay to
200%width and height and offset it-50%on top and left. Set the section toheight: 100vh,overflow: hidden,position: relative. -
Make it follow the cursor. On the section, add a classic “mouse move over element” interaction. Animate the overlay’s move transform:
-50vw/50vwon X,-50vh/50vhon Y. Turn smoothing up to about 95% and preview — the spotlight should glide under your pointer. -
Add the hover animation. Switch to GSAP-powered interactions on the button. Build one custom animation targeting the image class (scale
1.1, rotate3°, duration1.5s, easingpower1.inOut), then add two triggers: mouse enter → play, mouse leave → reverse. -
Drop in the prism filter. Add an Embed element, paste the SVG filter from the cloneable, and place it before the section in the navigator. Apply it to the image via a custom property
filter: url(#prism-basic). Then add a second Embed with the GSAP script and place it at the end of the page. The script targets the button through a custom attribute (not a class) so your naming stays flexible — mark the button in its element settings exactly as the cloneable’s script expects, then play with thedx/dyconstants at the top of the script to dial the color shift in.