← Back to gallery
CSS

Film Overlay Compositing

Cinematic film-grain overlay that composites tint + grain + vignette over a base photo via mix-blend-mode + filter chains. Three film stocks: warm Kodachrome, cool tungsten balance, and a high-contrast B&W silver-halide stock.

film-overlaymix-blend-modegrainvignettecolor-tintcompositingprefers-reduced-motion

Mix-blend overlay · texture composited into the wrapper

Film Overlay Compositing

Three production-realistic ways to composite a procedural texture over a scene without contaminating the foreground UI — Soft Grain Drift (steps-based grain shift), Vignette Breathe (radial vignette pulses), and Mood Cycle (slow hue-rotate). Each layer is scoped to the background wrapper so chips and copy keep their contrast.

Fractal noise · authentic film grain

Soft Grain Drift

A procedural fractal-noise grain layer rides on top of a warm cinematic scene with mix-blend-mode: overlay. The grain layer translates in tiny steps (every 0.45s) so the texture reads like authentic film grain instead of a smooth slide. The scene, vignette and REC chip beneath stay pin-sharp.

  • fractal noise
  • mix-blend-mode
  • overlay

Radial vignette · soft pulse

Vignette Breathe

The corner vignette breathes — its dark edge gently pulses between two strengths on a slow ease-in-out cycle, suggesting a single bulb dimming and brightening. The grain stays static; only the vignette layer animates.

  • radial-gradient
  • opacity pulse
  • cinematic

Hue rotate · warm ↔ cool drift

Mood Cycle

The whole scene is wrapped in a slow filter: hue-rotate cycle so the colour temperature drifts warm → cool → warm. A subtle constant grain stays on top to hold the cinematic texture while the underlying mood shifts every cycle. Foreground chips are scoped outside the filter so their colour stays correct.

  • filter: hue-rotate
  • mood
  • temperature

Film overlay inspector

Soft Grain Drift

  • fractal noise
  • mix-blend-mode
  • overlay

A procedural fractal-noise grain layer rides on top of a warm cinematic scene with mix-blend-mode: overlay. The grain layer translates in tiny steps (every 0.45s) so the texture reads like authentic film grain instead of a smooth slide. The scene, vignette and REC chip beneath stay pin-sharp.

Helped you ship something? 🐟 Send my cat a churu

/* A fractal-noise grain layer translates in tiny discrete steps so the texture reads as authentic film grain on top of a static scene. */
.film-grain {
  position: absolute;
  inset: -4%;
  width: 108%;
  height: 108%;
  mix-blend-mode: overlay;
  opacity: 0.85;
  animation: filmGrainShift 0.45s steps(4, end) infinite;
  pointer-events: none;
}

@keyframes filmGrainShift {
  0%, 100% { transform: translate(0, 0); }
  25%      { transform: translate(-2%, 1%); }
  50%      { transform: translate(1%, -2%); }
  75%      { transform: translate(2%, 1%); }
}

@media (prefers-reduced-motion: reduce) {
  .film-grain { animation: none; }
}

How to make this

A film overlay composite scopes grain, vignette, and blend modes to the background wrapper so foreground text keeps stable contrast.

html
1<figure class="film-overlay-card">  <div class="film-overlay-card__scene" aria-hidden="true"></div>  <figcaption>REC 04</figcaption></figure> <style>.film-overlay-card {8  position: relative;  isolation: isolate;  overflow: hidden;  display: grid;  place-items: end start;  width: min(100%, 28rem);  aspect-ratio: 16 / 9;  margin: 0;  border-radius: 18px;  background: #0a0418;}19.film-overlay-card__scene {  position: absolute;  inset: 0;  z-index: -1;  background:    radial-gradient(ellipse at 22% 30%, rgba(244,114,182,.55), transparent 55%),    radial-gradient(ellipse at 78% 70%, rgba(251,191,36,.45), transparent 58%),    linear-gradient(135deg, #1a0820, #0a0418 60%, #1a1206);}.film-overlay-card__scene::before {  content: "";  position: absolute;  inset: -4%;  opacity: .42;33  mix-blend-mode: overlay;34  pointer-events: none;  background-image:    radial-gradient(circle, rgba(255,255,255,.5) 0 1px, transparent 1px);  background-size: 5px 5px;38  animation: film-overlay-recipe-grain .45s steps(4, end) infinite;}.film-overlay-card::after {  content: "";  position: absolute;  inset: 0;  pointer-events: none;  background: radial-gradient(ellipse at center, transparent 48%, rgba(0,0,0,.62));}.film-overlay-card figcaption {  position: relative;  z-index: 1;  margin: 1rem;  padding: .45rem .7rem;  border-radius: 999px;  color: #fef9c3;  background: rgba(15, 23, 42, .82);  font: 800 .78rem/1 ui-sans-serif, system-ui;  letter-spacing: .14em;}@keyframes film-overlay-recipe-grain {  0%, 100% { transform: translate(0, 0); }  25% { transform: translate(-2%, 1%); }  50% { transform: translate(1%, -2%); }  75% { transform: translate(2%, 1%); }}@media (prefers-reduced-motion: reduce) {65  .film-overlay-card__scene::before { animation: none; }}</style>

Annotated snippet

  1. Line 1The figure owns both the decorative scene and the real caption. Any meaning should remain in text, not only in the texture or color grade.
  2. Line 8isolation: isolate creates a local compositing context. That keeps blend modes from leaking into neighboring page backgrounds.
    PitfallIs mix-blend-mode safe for production overlays?

    Modern browsers support it, but results depend on stacking contexts and background colors. Use isolation: isolate and provide a readable base scene if blend mode is unavailable.

  3. Line 19The scene layer is separate from the caption. This lets the overlay affect only the background image while foreground UI remains crisp.

    Both cards run the same hue-rotate animation. On the before card the filter is on the whole wrapper, so the REC chip swims through the colour cycle along with the scene. On the after card the filter is on a scoped background layer only — the chip text stays a stable cream colour.

    PitfallWhy does my film overlay tint the UI text?

    The blend mode or filter is probably applied to the same wrapper as the foreground content. Put the scene and texture in a scoped background layer, then render labels and controls above it.

  4. Line 34The grain sits on a pseudo-element with pointer-events disabled. It should never block hover, focus, or clicks on foreground controls.
    PitfallCan film overlays hurt performance?

    Yes. Large blended textures, filters, and animated background layers can add paint cost. Keep overlays small, avoid full-page animated grain, and pause decorative motion offscreen.

  5. Line 33mix-blend-mode: overlay composites the dots into the scene luminance. Keep it on decorative layers; blending text makes contrast unpredictable.
    PitfallIs mix-blend-mode safe for production overlays?

    Modern browsers support it, but results depend on stacking contexts and background colors. Use isolation: isolate and provide a readable base scene if blend mode is unavailable.

  6. Line 38steps() creates discrete grain jumps. Smoothly translating grain reads like a sliding texture, not film noise.

    Same translate keyframe on the dot texture. With ease-in-out timing the pattern smoothly pans across the card and reads as sliding wallpaper. steps(4, end) snaps the texture between four discrete positions per cycle — that frame-to-frame discontinuity is what makes the eye accept it as film grain.

    PitfallHow do I make film grain feel less like a sliding pattern?

    Move the texture in tiny jumps with steps() rather than a smooth timing function. Real grain changes frame to frame; a smooth pan looks like wallpaper drifting across the card.

  7. Line 65Reduced motion freezes the grain but leaves the static texture and vignette. The cinematic surface remains without constant flicker.
    PitfallWhat should reduced motion do for film grain?

    Stop flicker, hue cycling, or vignette pulsing while preserving a representative static texture. Reduced motion should remove movement, not strip the whole visual treatment.

Notes

Overview

Cinematic film overlays composite tint, grain, and vignette layers over a base photo via mix-blend-mode + filter chains. Three film stocks ship: warm Kodachrome, cool tungsten balance, high-contrast B&W silver-halide.

When to use it

Reach for film overlays on photography portfolios, editorial hero images, and product surfaces where a curated look elevates the brand. Skip overlays on content where color fidelity matters (e-commerce product photos, medical imagery, color-critical previews). Keep grain texture small (32px tile) to avoid moiré on Retina displays.

How it works

The base photo sits at the bottom of the stack. Above it: a tint layer (solid color with reduced opacity) with mix-blend-mode: multiply or soft-light shifts the overall color temperature. A grain layer (small repeating noise PNG) sits above with mix-blend-mode: overlay + opacity: 0.15. A vignette layer uses a radial gradient from transparent center to opaque edges with mix-blend-mode: multiply. Animate the tint opacity or the grain layer’s background-position for slow film texture drift; static stacks work fine without animation.

Production gotchas

mix-blend-mode requires an isolation context — without an opaque ancestor with isolation: isolate, blends can leak through to elements behind the stack. The grain layer must repeat cleanly; if the noise tile has visible seam boundaries the overlay reads as wallpaper, not film grain. Color-management edge cases: Safari iOS clamps wide-gamut blends differently than Chromium, so the same film stock looks slightly different across browsers. Test on actual devices, not just emulators.

Accessibility

Film tints can drop overlaid text contrast unexpectedly — if any text sits on top of the composited photo, verify contrast in the worst-case film stock and not just the unfiltered base. Under prefers-reduced-motion: reduce drop any grain-drift animation and pin the layers static. Decorative photos should carry an empty alt="" or be marked role="presentation".

References

Implementation depth

Film overlays are a blend stack: base image, tint, grain, and vignette each own one visual job. mix-blend-mode can create the look, but isolation keeps the blend from leaking into the rest of the page.

Do not use this where color fidelity is part of the task. Product photos, charts, and status colors should not sit under film tint. If grain moves, reduced motion should pin it to a static texture.