Guides/ CSS & Images
auto_fix_high

CSS Photo Filters Guide: Instagram-Style Effects with filter()

The CSS filter property applies Photoshop-style effects to images with a single line: grayscale, sepia, blur, contrast, brightness. This guide covers every filter function, Instagram-style preset combinations, and the often-confused difference between filter and backdrop-filter.

April 2026 · 7 min read

Filter Functions Reference

FunctionRangeEffect
brightness()0 to ∞ (1 = original)Darker below 1, brighter above
contrast()0 to ∞ (1 = original)Flatter below 1, punchier above
saturate()0 to ∞ (1 = original)0 = grayscale, 2 = oversaturated
grayscale()0 to 10 = color, 1 = black and white
sepia()0 to 1Warm brown tint, vintage feel
hue-rotate()0deg to 360degShifts color wheel by degree
invert()0 to 1Inverts colors (photo negative)
opacity()0 to 1Transparency (prefer opacity property)
blur()0px to ∞Gaussian blur, affects sharpness
drop-shadow()shadow paramsLike box-shadow but respects image transparency

Combining Filters

Apply multiple filters by space-separating them. Order matters — filters apply left to right:

img {
  filter: contrast(1.1) brightness(1.05) saturate(1.2);
}

/* Order matters: grayscale after hue-rotate vs before */
.a { filter: hue-rotate(90deg) grayscale(1); }  /* gray result */
.b { filter: grayscale(1) hue-rotate(90deg); }  /* still gray */

Instagram-Style Presets

Classic filter recipes you can apply directly:

Clarendon (Cool, Punchy)

.clarendon {
  filter: contrast(1.2) saturate(1.35);
}

Gingham (Soft, Vintage)

.gingham {
  filter: brightness(1.05) hue-rotate(-10deg) sepia(0.04);
}

Moon (Cool Black & White)

.moon {
  filter: grayscale(1) contrast(1.1) brightness(1.1);
}

Lark (Bright, Desaturated Greens)

.lark {
  filter: brightness(1.1) contrast(0.95) saturate(1.15);
}

Reyes (Dusty, Faded)

.reyes {
  filter: sepia(0.22) brightness(1.1) contrast(0.85) saturate(0.75);
}

Juno (Warm, Vivid)

.juno {
  filter: contrast(1.15) saturate(1.4) hue-rotate(-5deg);
}

Hover Effects with filter()

/* Color on hover, grayscale at rest — portfolio classic */
.gallery img {
  filter: grayscale(1);
  transition: filter 0.4s ease;
}
.gallery img:hover {
  filter: grayscale(0);
}

/* Blur on hover for out-of-focus effect */
.blurrable {
  transition: filter 0.3s;
}
.blurrable:hover {
  filter: blur(8px);
}

/* Brightness pulse on card hover */
.card:hover img {
  filter: brightness(1.1) saturate(1.1);
}

filter vs backdrop-filter

Two different properties for two different jobs:

  • filter — applies effects to the element itself. The element and everything inside it gets filtered.
  • backdrop-filter — applies effects to whatever is behind the element, visible through its transparent/semi-transparent background. The element itself is not filtered.
/* Glassmorphism panel — blur what's behind the element */
.glass {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(16px) saturate(1.5);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Darkened image with text overlay readable */
.hero {
  position: relative;
}
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  backdrop-filter: brightness(0.6);
}

backdrop-filter is what powers iOS-style glassmorphism. It needs a transparent or semi-transparent background to show the filtered backdrop through.

Performance Notes

  • Most filters are GPU-accelerated — safe to use on large images and animate smoothly.
  • blur() is expensive at large radii — 20px+ blur on a full-screen element can drop frame rate on mobile.
  • backdrop-filter is heavier than filter — the browser must composite everything behind. Use sparingly on mobile.
  • Combining filter with animations — stick to opacity and transform for transitions if possible; filter animations stress compositing.
  • Add will-change: filter when animating, but remove it after the animation ends (it reserves resources).

Browser Support

  • filter — supported in all browsers since 2015. Safe to use unconditionally.
  • backdrop-filter — Chrome, Edge, Safari fully support. Firefox supports since 2022. Include -webkit-backdrop-filter for older Safari.
  • SVG filters (referenced via filter: url(#id)) — supported everywhere but harder to write. Built-ins cover most use cases.

Frequently Asked Questions

Are CSS filters destructive?
No — they apply at render time. The underlying image is untouched. Remove the filter property and you're back to the original. This is the main advantage over server-side filtering.
Can I save a CSS-filtered image?
Not directly from CSS — the filter is a display layer. To persist the filtered result, render the image to a Canvas with the same filter applied, then export the canvas. Most browser-based filter tools do this behind the scenes.
Why does my backdrop-filter not work?
Three common issues: (1) the element has a fully opaque background (no backdrop visible), (2) you forgot the -webkit-backdrop-filter prefix for Safari, or (3) the parent has overflow: hidden with rounded corners clipping the backdrop area.
Is there a way to get more control than built-in filters?
Yes — use SVG filters via filter: url(#my-filter) referencing an inline <filter> element. You can compose arbitrary matrix operations, displacement maps, and turbulence effects. Complex, but gives you Photoshop-level control.
Can I apply different filters to different parts of an image?
Not with pure filter — it applies to the whole element. You can use clip-path or masks to reveal different filtered layers, or use Canvas/SVG for true per-pixel control.