CSS Filters & Blend Modes
CSS filters and blend modes bring image-editing capabilities directly to the browser. The filter property applies graphical effects like blur, contrast, and hue rotation to an element. The backdrop-filter applies these effects to the area behind an element. Blend modes (mix-blend-mode and background-blend-mode) control how elements visually blend with what is underneath them.
These properties enable sophisticated visual effects without JavaScript or image assets — terminal scanlines, glitch effects, frosted glass, color adjustments, and more can be achieved purely with CSS.
| 1 | .element { |
| 2 | filter: brightness(1.2) contrast(1.1) saturate(1.3); |
| 3 | /* Multiple filters can be chained — applied right to left */ |
| 4 | } |
CSS provides ten filter functions that can be used individually or chained together. Each function accepts a parameter that controls the intensity of the effect.
| Function | Parameters | Description |
|---|---|---|
| blur() | length (px, rem) | Applies Gaussian blur |
| brightness() | number or % (0-∞) | Linear multiplier (0=black, 1=normal, >1=brighter) |
| contrast() | number or % (0-∞) | Adjusts contrast (0=gray, 1=normal, >1=more contrast) |
| grayscale() | number or % (0-1) | Converts to grayscale (0=color, 1=gray) |
| hue-rotate() | angle (deg, turn) | Rotates the hue (0deg=normal, 360deg=full circle) |
| invert() | number or % (0-1) | Inverts colors (0=normal, 1=inverted) |
| opacity() | number or % (0-1) | Applies transparency (0=transparent, 1=opaque) |
| saturate() | number or % (0-∞) | Adjusts saturation (0=desaturated, 1=normal) |
| sepia() | number or % (0-1) | Applies sepia tone (0=normal, 1=full sepia) |
| drop-shadow() | offset-x offset-y blur-radius color | Creates shadow following element contour |
| 1 | .blur { filter: blur(4px); } |
| 2 | .brightness { filter: brightness(1.5); } |
| 3 | .contrast { filter: contrast(2); } |
| 4 | .grayscale { filter: grayscale(100%); } |
| 5 | .hue-rotate { filter: hue-rotate(180deg); } |
| 6 | .invert { filter: invert(100%); } |
| 7 | .opacity { filter: opacity(0.5); } |
| 8 | .saturate { filter: saturate(3); } |
| 9 | .sepia { filter: sepia(100%); } |
| 10 | .drop-shadow { filter: drop-shadow(2px 4px 8px rgba(0,0,0,0.5)); } |
The backdrop-filter property applies filter effects to the area behind the element, creating effects like frosted glass. The element itself must be at least partially transparent for the effect to be visible.
| 1 | .glass { |
| 2 | background: rgba(13, 13, 13, 0.6); |
| 3 | backdrop-filter: blur(12px); |
| 4 | -webkit-backdrop-filter: blur(12px); /* Safari support */ |
| 5 | border: 1px solid rgba(255, 255, 255, 0.1); |
| 6 | } |
| 7 | |
| 8 | .glass-heavy { |
| 9 | background: rgba(26, 26, 46, 0.4); |
| 10 | backdrop-filter: blur(20px) saturate(1.5); |
| 11 | } |
| 12 | |
| 13 | /* Frosted terminal panel */ |
| 14 | .terminal-glass { |
| 15 | background: rgba(13, 13, 13, 0.7); |
| 16 | backdrop-filter: blur(8px); |
| 17 | border: 1px solid rgba(0, 255, 65, 0.1); |
| 18 | } |
warning
Multiple filter functions can be chained in a single filter declaration, separated by spaces. They are applied in order from right to left. Chaining filters creates compound effects that cannot be achieved with a single function.
| 1 | .compound { |
| 2 | /* Apply brightness first, then grayscale */ |
| 3 | filter: grayscale(100%) brightness(1.2); |
| 4 | } |
| 5 | |
| 6 | .dramatic { |
| 7 | filter: contrast(1.5) saturate(1.3) sepia(0.3); |
| 8 | } |
| 9 | |
| 10 | .terminal-dark { |
| 11 | filter: brightness(0.8) contrast(1.2); |
| 12 | } |
| 13 | |
| 14 | .retro { |
| 15 | filter: sepia(0.6) hue-rotate(-20deg) saturate(1.4); |
| 16 | } |
| 17 | |
| 18 | /* Use variables to compose filters */ |
| 19 | .dim { --dim: brightness(0.7); } |
| 20 | .warm { --warm: sepia(0.3) saturate(1.3); } |
| 21 | .cool { --cool: hue-rotate(30deg) saturate(0.9); } |
| 22 | |
| 23 | .composed { |
| 24 | filter: var(--dim) var(--warm); |
| 25 | } |
CSS supports two blend mode properties: mix-blend-mode blends an element with what is behind it, and background-blend-modeblends an element's background layers (images, gradients, colors) together.
| 1 | .mix-blend { |
| 2 | mix-blend-mode: multiply; /* multiplies colors — always darker */ |
| 3 | mix-blend-mode: screen; /* inverts, multiplies, inverts — always lighter */ |
| 4 | mix-blend-mode: overlay; /* combines multiply and screen */ |
| 5 | mix-blend-mode: difference; /* subtracts darker from lighter */ |
| 6 | mix-blend-mode: exclusion; /* similar to difference but lower contrast */ |
| 7 | } |
| 8 | |
| 9 | .background-blend { |
| 10 | background: |
| 11 | linear-gradient(45deg, #00FF41, #0D0D0D), |
| 12 | url('bg.png'); |
| 13 | background-blend-mode: overlay; |
| 14 | } |
| 15 | |
| 16 | /* Terminal overlay blend */ |
| 17 | .terminal-scanlines { |
| 18 | background: repeating-linear-gradient( |
| 19 | 0deg, |
| 20 | transparent, |
| 21 | transparent 2px, |
| 22 | rgba(0, 255, 65, 0.03) 2px, |
| 23 | rgba(0, 255, 65, 0.03) 4px |
| 24 | ); |
| 25 | mix-blend-mode: overlay; |
| 26 | pointer-events: none; |
| 27 | } |
mix-blend-mode blends an element with its backdrop — the content behind it. It is commonly used for text overlays on images, creative hover effects, and terminal scanline overlays.
| 1 | .text-overlay { |
| 2 | mix-blend-mode: difference; |
| 3 | color: white; |
| 4 | /* Text appears inverted against any background */ |
| 5 | } |
| 6 | |
| 7 | .image-text { |
| 8 | mix-blend-mode: overlay; |
| 9 | color: #0D0D0D; |
| 10 | font-weight: 900; |
| 11 | /* Text blends with background image */ |
| 12 | } |
| 13 | |
| 14 | /* Available mix-blend-mode values */ |
| 15 | /* |
| 16 | normal — no blending |
| 17 | multiply — multiplies pixel values (darker) |
| 18 | screen — inverse multiply (lighter) |
| 19 | overlay — combines multiply and screen |
| 20 | darken — uses darker pixel from each layer |
| 21 | lighten — uses lighter pixel from each layer |
| 22 | color-dodge — brightens backdrop |
| 23 | color-burn — darkens backdrop |
| 24 | hard-light — harsh lighting effect |
| 25 | soft-light — soft lighting effect |
| 26 | difference — subtracts darker from lighter |
| 27 | exclusion — similar to difference, lower contrast |
| 28 | hue — uses hue from element, saturation/luminosity from backdrop |
| 29 | saturation — uses saturation from element, hue/luminosity from backdrop |
| 30 | color — uses hue/saturation from element, luminosity from backdrop |
| 31 | luminosity — uses luminosity from element, hue/saturation from backdrop |
| 32 | */ |
background-blend-modeblends an element's multiple background layers together. It does not affect blending with content outside the element. This is useful for creating textured backgrounds, gradient overlays, and terminal CRT effects.
| 1 | .textured-bg { |
| 2 | background: |
| 3 | linear-gradient(135deg, #1A1A2E, #0D0D0D), |
| 4 | url('noise.png'); |
| 5 | background-blend-mode: overlay; |
| 6 | } |
| 7 | |
| 8 | /* Terminal CRT screen effect */ |
| 9 | .crt-screen { |
| 10 | background: |
| 11 | radial-gradient(ellipse at center, rgba(0, 255, 65, 0.1) 0%, transparent 70%), |
| 12 | #0D0D0D; |
| 13 | background-blend-mode: screen; |
| 14 | } |
| 15 | |
| 16 | /* Gradient on image */ |
| 17 | .image-overlay { |
| 18 | background: |
| 19 | linear-gradient(rgba(0, 255, 65, 0.3), rgba(0, 0, 0, 0.8)), |
| 20 | url('photo.jpg'); |
| 21 | background-blend-mode: multiply; |
| 22 | background-size: cover; |
| 23 | } |
Terminal Scanlines
| 1 | .terminal-scanlines { |
| 2 | position: relative; |
| 3 | } |
| 4 | |
| 5 | .terminal-scanlines::after { |
| 6 | content: ''; |
| 7 | position: absolute; |
| 8 | inset: 0; |
| 9 | background: repeating-linear-gradient( |
| 10 | 0deg, |
| 11 | transparent 0px, |
| 12 | transparent 2px, |
| 13 | rgba(0, 255, 65, 0.03) 2px, |
| 14 | rgba(0, 255, 65, 0.03) 4px |
| 15 | ); |
| 16 | pointer-events: none; |
| 17 | mix-blend-mode: overlay; |
| 18 | } |
Glitch Effect
| 1 | .glitch { |
| 2 | position: relative; |
| 3 | color: #E0E0E0; |
| 4 | } |
| 5 | |
| 6 | .glitch::before, |
| 7 | .glitch::after { |
| 8 | content: attr(data-text); |
| 9 | position: absolute; |
| 10 | inset: 0; |
| 11 | opacity: 0.8; |
| 12 | } |
| 13 | |
| 14 | .glitch::before { |
| 15 | color: #FF0000; |
| 16 | animation: glitch-shift 0.3s infinite linear alternate; |
| 17 | clip-path: inset(20% 0 60% 0); |
| 18 | } |
| 19 | |
| 20 | .glitch::after { |
| 21 | color: #00FFFF; |
| 22 | animation: glitch-shift 0.3s infinite linear alternate-reverse; |
| 23 | clip-path: inset(60% 0 20% 0); |
| 24 | } |
| 25 | |
| 26 | @keyframes glitch-shift { |
| 27 | 0% { transform: translate(0); } |
| 28 | 20% { transform: translate(-2px, 1px); } |
| 29 | 40% { transform: translate(2px, -1px); } |
| 30 | 60% { transform: translate(-1px, 2px); } |
| 31 | 80% { transform: translate(1px, -2px); } |
| 32 | 100% { transform: translate(0); } |
| 33 | } |
Color Adjustments
| 1 | .dark-mode-img { |
| 2 | filter: brightness(0.8) contrast(1.2); |
| 3 | /* Makes images consistent in dark mode */ |
| 4 | } |
| 5 | |
| 6 | .terminal-green { |
| 7 | filter: sepia(1) hue-rotate(70deg) saturate(3); |
| 8 | /* Converts any image to terminal green palette */ |
| 9 | } |
| 10 | |
| 11 | .hover-colorize { |
| 12 | filter: grayscale(100%); |
| 13 | transition: filter 0.3s ease; |
| 14 | } |
| 15 | |
| 16 | .hover-colorize:hover { |
| 17 | filter: grayscale(0%); |
| 18 | /* Desaturated by default, colorizes on hover */ |
| 19 | } |
| 20 | |
| 21 | /* Terminal CRT curvature effect */ |
| 22 | .crt-curvature { |
| 23 | filter: brightness(0.95) contrast(1.1); |
| 24 | background: radial-gradient( |
| 25 | ellipse at center, |
| 26 | transparent 60%, |
| 27 | rgba(0, 0, 0, 0.3) 100% |
| 28 | ); |
| 29 | } |
Community
Get help on Slack, Discord or VIP
Stuck on a guide? Join the community and ask.