Building a CSS Lens Flare From Scratch
Anamorphic lens flares are a signature cinematic flourish, often associated with directors like J.J. Abrams. The effect—where light scatters and reflects inside a camera lens—adds an instant film-like quality to otherwise ordinary stills. While you can easily paste a flare image onto a photo in Photoshop, it's also possible to recreate the effect purely with CSS gradients and background layering. That keeps it lightweight, responsive, and fully editable without a raster image editor.
There are several types of lens artifacts in photography. The one we're simulating here is the aperture-shaped blotch you get when light enters the lens and bounces off its internal optics. If you look at a movie still with a visible flare, you'll usually spot three distinct visual components:
- A bright central glowing ball of light.
- Several horizontal, elongated elliptical streaks—these are your classic distorted and blurred rays.
- Sharp, conical rays that shoot outward from the center at odd angles.
Designing the Core Light Source
The foundation of any lens flare is the bright center. The trick is using a radial gradient with multiple alpha-channel stops to create a layered, diffuse glow rather than a flat circle. A filter with a CSS blur helps sell the effect further, making the light look as if it's scattering through atmosphere and optics.
background: radial-gradient(
closest-side circle at center,
hsl(4 5% 100% / 100%) 0%,
hsl(4 5% 100% / 100%) 15%,
hsl(4 10% 70% / 70%) 30%,
hsl(4 0% 50% / 30%) 55%,
hsl(4 0% 10% / 5%) 75%,
transparent 99
);
filter: blur(4px);
Note the use of new-style alpha syntax (hsl with a fourth channel) rather than calling a separate opacity function—this is the direction CSS color functions are heading. Alongside the main source, you'll want a larger, softer light halo sitting behind the core to give the glow depth.
To push realism further, add a few smaller off-diagonal circular flares at fixed angles from the center. In the reference effect, those are positioned around the main light at 45deg intervals, giving the appearance of light bouncing between adjacent lens elements.
Creating Asymmetrical Horizontal Streaks
background: radial-gradient(
closest-side circle at center,
transparent 50%,
hsl(4 10% 70% / 40%) 90%,
transparent 100%
);
filter: blur(5px);
Horizontal lens streaks are not perfectly symmetrical in practice. A stretched ellipse gradient would give you a fine two-lobed burst, but to mimic real photographic artifacts it helps to construct each side with distinct dimensions and colors. You can fake this by plotting smaller individual gradients to the left and right of the center with slightly different size and color stops. Applying an opacity filter where the streaks meet the center keeps that joint from looking like a cardboard cutout.
You'll also want a single full-length elliptical flare sitting near the bottom of the viewport—this creates the sense of a slight tilt in your lens assembly and adds that handmade bokeh quality to the photo treatment.
Using Conical Gradients for Light Rays
background: conic-gradient(
from 5deg at 0% 100%,
transparent 0deg,
hsl(4 10% 70% / 30%) 7deg,
transparent 15deg
);
transform-origin: bottom left;
transform: rotate(-45deg);
Some modern lenses are prone to specular light rays along a particular axis. In CSS, this texture is easy to obtain using the conic-gradient() function. For the flare, use several conic gradients pinned to the same center point, each stroking a slightly different width and color. Since gradients fill the entire element by default, you need to rotate the flare container around that shared origin to keep the effect tidy and—crucially—to keep other parts of the flare from being colored by accident.
You can skew and translate elliptical shapes to approximate those rays, but the conic option is cleaner and arguably more portable.
Controlling It All with Custom Properties
Hardcoding the flare position makes for brittle CSS. If you need to move the flare to follow the main source of light in a photo—say on a subject's nose or a background lamp—you also need to reposition every horizontal streak or conic ray with its own set of magic numbers. Instead, define the flare's center, size, and hue as CSS custom properties, then let every dependent gradient resolve its value from there.
:root {
--hue: 4;
--lens-center-size: 40%;
--lens-spread-size: 80%;
--lens-left: 55%;
--lens-top: 15%;
}
Custom properties also let you treat distinct flare elements as reusable hooks. For instance, a horizontal flare's width can fall back to the global center coordinate or to the image width—so long as you inherit it properly. This "variable overloading" keeps your CSS readable while retaining flexibility when you author a flare for a particular image.
.left-flare {
width: var(--left-flare-width, var(--lens-left, 50%));
}
The resulting component is a backdrop-agnostic overlay. Placing it in a photo whose main illumination sits top-left of frame suddenly becomes a matter of shifting two custom properties rather than hunting for a suitable PNG asset.
How CSS Flare Components Fit in the Larger Ecosystem
A pure CSS implementation isn't the only route. There are plenty of innovative online demos that use SVG gradients, Canvas, or JavaScript libraries to achieve similar effects. Some coders randomize the balance of red, green, and blue stops for every page reload; others gently track pointer hover so the flare follows your cursor across a gallery view, selling the physicality of a moving light source.
That's the fun of the medium—your flare can be as subtle or as dramatic as the image in front of it demands. What techniques have you used to simulate optical effects in your own projects?



