CSS filters enable powerful visual effects without images. Here's how to use them.
Basic Filters#
1/* Blur */
2.blurred {
3 filter: blur(5px);
4}
5
6/* Brightness (0 = black, 1 = normal, >1 = brighter) */
7.bright {
8 filter: brightness(1.5);
9}
10
11.dark {
12 filter: brightness(0.5);
13}
14
15/* Contrast (0 = gray, 1 = normal, >1 = more contrast) */
16.high-contrast {
17 filter: contrast(1.5);
18}
19
20.low-contrast {
21 filter: contrast(0.5);
22}
23
24/* Grayscale (0 = normal, 1 = fully grayscale) */
25.grayscale {
26 filter: grayscale(1);
27}
28
29.partial-grayscale {
30 filter: grayscale(0.5);
31}
32
33/* Sepia (0 = normal, 1 = fully sepia) */
34.sepia {
35 filter: sepia(1);
36}
37
38/* Invert colors */
39.inverted {
40 filter: invert(1);
41}
42
43/* Saturate (0 = grayscale, 1 = normal, >1 = oversaturated) */
44.saturated {
45 filter: saturate(2);
46}
47
48.desaturated {
49 filter: saturate(0.5);
50}Hue Rotation#
1/* Rotate hue (0-360deg) */
2.hue-shift {
3 filter: hue-rotate(90deg);
4}
5
6/* Animated hue rotation */
7.rainbow {
8 animation: hue-cycle 5s linear infinite;
9}
10
11@keyframes hue-cycle {
12 from {
13 filter: hue-rotate(0deg);
14 }
15 to {
16 filter: hue-rotate(360deg);
17 }
18}
19
20/* Color themes with hue-rotate */
21.theme-warm {
22 filter: hue-rotate(-15deg) saturate(1.1);
23}
24
25.theme-cool {
26 filter: hue-rotate(15deg) saturate(0.9);
27}Drop Shadow#
1/* Basic drop shadow */
2.shadow {
3 filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.3));
4}
5
6/* Multiple shadows */
7.multi-shadow {
8 filter:
9 drop-shadow(2px 2px 0 red)
10 drop-shadow(-2px -2px 0 blue);
11}
12
13/* Glowing effect */
14.glow {
15 filter: drop-shadow(0 0 10px rgba(255, 255, 0, 0.8));
16}
17
18/* Drop shadow follows shape (unlike box-shadow) */
19.png-image {
20 /* Shadows the actual PNG shape, not the bounding box */
21 filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.5));
22}
23
24/* Text with glow */
25.glowing-text {
26 filter: drop-shadow(0 0 5px currentColor);
27}Combining Filters#
1/* Multiple filters */
2.vintage {
3 filter: sepia(0.5) contrast(1.1) brightness(0.9);
4}
5
6.dramatic {
7 filter: contrast(1.3) saturate(1.2) brightness(1.1);
8}
9
10.faded {
11 filter: grayscale(0.3) brightness(1.1) contrast(0.9);
12}
13
14/* Instagram-style filters */
15.clarendon {
16 filter: contrast(1.2) saturate(1.35);
17}
18
19.gingham {
20 filter: brightness(1.05) hue-rotate(-10deg);
21}
22
23.moon {
24 filter: grayscale(1) contrast(1.1) brightness(1.1);
25}
26
27.lark {
28 filter: contrast(0.9) saturate(1.2) brightness(1.1);
29}Backdrop Filter#
1/* Frosted glass effect */
2.glass {
3 background: rgba(255, 255, 255, 0.2);
4 backdrop-filter: blur(10px);
5}
6
7/* Dark glass */
8.dark-glass {
9 background: rgba(0, 0, 0, 0.3);
10 backdrop-filter: blur(10px) saturate(180%);
11}
12
13/* Modal overlay */
14.modal-backdrop {
15 position: fixed;
16 inset: 0;
17 background: rgba(0, 0, 0, 0.5);
18 backdrop-filter: blur(5px);
19}
20
21/* Header blur on scroll */
22.header {
23 position: sticky;
24 top: 0;
25 background: rgba(255, 255, 255, 0.8);
26 backdrop-filter: blur(10px) saturate(180%);
27}
28
29/* Card with backdrop blur */
30.card {
31 background: rgba(255, 255, 255, 0.1);
32 backdrop-filter: blur(20px);
33 border: 1px solid rgba(255, 255, 255, 0.2);
34 border-radius: 16px;
35}Interactive Filters#
1/* Hover effects */
2.image-card {
3 filter: grayscale(1);
4 transition: filter 0.3s ease;
5}
6
7.image-card:hover {
8 filter: grayscale(0);
9}
10
11/* Focus brightness */
12.button {
13 filter: brightness(1);
14 transition: filter 0.2s;
15}
16
17.button:hover {
18 filter: brightness(1.1);
19}
20
21.button:active {
22 filter: brightness(0.9);
23}
24
25/* Disabled state */
26.disabled {
27 filter: grayscale(1) opacity(0.6);
28 pointer-events: none;
29}
30
31/* Loading state */
32.loading {
33 filter: blur(2px) grayscale(0.5);
34}Image Effects#
1/* Duotone effect */
2.duotone {
3 filter: grayscale(1) contrast(1);
4 position: relative;
5}
6
7.duotone::after {
8 content: '';
9 position: absolute;
10 inset: 0;
11 background: linear-gradient(to right, #ff6b6b, #4ecdc4);
12 mix-blend-mode: color;
13}
14
15/* Night vision */
16.night-vision {
17 filter: brightness(1.5) contrast(1.5) saturate(0) sepia(1)
18 hue-rotate(80deg);
19}
20
21/* X-ray effect */
22.xray {
23 filter: invert(1) grayscale(1) contrast(1.2);
24}
25
26/* Emboss-like effect */
27.emboss {
28 filter: contrast(1.5) brightness(0.9);
29 mix-blend-mode: hard-light;
30}
31
32/* Vignette with radial gradient */
33.vignette {
34 position: relative;
35}
36
37.vignette::after {
38 content: '';
39 position: absolute;
40 inset: 0;
41 background: radial-gradient(
42 circle,
43 transparent 50%,
44 rgba(0, 0, 0, 0.5) 100%
45 );
46 pointer-events: none;
47}SVG Filters#
1/* Reference SVG filter */
2.custom-filter {
3 filter: url(#custom-svg-filter);
4}
5
6/* Inline SVG filter definition */
7/*
8<svg>
9 <defs>
10 <filter id="custom-svg-filter">
11 <feGaussianBlur stdDeviation="2" />
12 <feColorMatrix type="saturate" values="2" />
13 </filter>
14 </defs>
15</svg>
16*/
17
18/* Noise texture */
19/*
20<filter id="noise">
21 <feTurbulence type="fractalNoise" baseFrequency="0.7" numOctaves="3" />
22 <feBlend mode="overlay" in="SourceGraphic" />
23</filter>
24*/
25
26.noisy {
27 filter: url(#noise);
28}
29
30/* Gooey effect */
31/*
32<filter id="gooey">
33 <feGaussianBlur in="SourceGraphic" stdDeviation="10" />
34 <feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" />
35</filter>
36*/
37
38.gooey {
39 filter: url(#gooey);
40}Performance Optimization#
1/* Hardware acceleration */
2.accelerated {
3 filter: blur(5px);
4 will-change: filter;
5 transform: translateZ(0);
6}
7
8/* Reduce complexity on scroll */
9.scrolling .blur-element {
10 filter: none; /* Disable during scroll */
11}
12
13/* Simplified filter for animations */
14@media (prefers-reduced-motion: reduce) {
15 .animated-filter {
16 filter: none;
17 transition: none;
18 }
19}
20
21/* Use smaller blur values when possible */
22.subtle-blur {
23 filter: blur(2px); /* Cheaper than blur(10px) */
24}Accessibility Considerations#
1/* Respect user preferences */
2@media (prefers-contrast: more) {
3 .filtered {
4 filter: contrast(1.3);
5 }
6}
7
8@media (prefers-reduced-motion: reduce) {
9 .animated-filter {
10 animation: none;
11 }
12}
13
14/* Ensure text remains readable */
15.text-over-blur {
16 position: relative;
17 z-index: 1;
18 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
19}
20
21/* Provide fallback for backdrop-filter */
22@supports not (backdrop-filter: blur(10px)) {
23 .glass {
24 background: rgba(255, 255, 255, 0.9);
25 }
26}Filter Utilities#
1/* Utility classes */
2.blur-sm { filter: blur(4px); }
3.blur-md { filter: blur(8px); }
4.blur-lg { filter: blur(16px); }
5
6.brightness-50 { filter: brightness(0.5); }
7.brightness-75 { filter: brightness(0.75); }
8.brightness-125 { filter: brightness(1.25); }
9
10.grayscale { filter: grayscale(1); }
11.grayscale-50 { filter: grayscale(0.5); }
12
13.saturate-50 { filter: saturate(0.5); }
14.saturate-150 { filter: saturate(1.5); }
15.saturate-200 { filter: saturate(2); }
16
17/* Backdrop utilities */
18.backdrop-blur-sm { backdrop-filter: blur(4px); }
19.backdrop-blur-md { backdrop-filter: blur(8px); }
20.backdrop-blur-lg { backdrop-filter: blur(16px); }Best Practices#
Performance:
✓ Use will-change sparingly
✓ Prefer simpler filters
✓ Disable filters during animations
✓ Test on lower-end devices
Accessibility:
✓ Maintain color contrast
✓ Respect motion preferences
✓ Provide fallbacks
✓ Don't rely solely on color
Browser Support:
✓ Check backdrop-filter support
✓ Use @supports for fallbacks
✓ Test across browsers
✓ Consider SVG filters for complex effects
Design:
✓ Use filters subtly
✓ Ensure readability
✓ Combine purposefully
✓ Match brand aesthetics
Conclusion#
CSS filters enable powerful visual effects with simple declarations. Use them for hover states, image effects, and glassmorphism. Combine filters for unique looks, consider performance implications, and always provide fallbacks for accessibility and browser support.