CSS Filters - Visual Effects for Images & Elements

What You'll Learn

  • Apply blur, brightness, and contrast filters to elements
  • Transform colors with grayscale, sepia, hue-rotate, and saturate
  • Use invert and opacity filters for creative effects
  • Create shape-aware shadows with drop-shadow()
  • Combine multiple filters for complex visual effects
  • Build interactive hover effects with smooth filter transitions
  • Understand the difference between drop-shadow() and box-shadow

Introduction to CSS Filters

CSS filters apply graphical effects like blur, color manipulation, and shadows to any element. Originally designed for image processing, filters work on all HTML elements including text, backgrounds, and SVG. Filters are GPU-accelerated for smooth performance and can be combined for sophisticated visual effects.

The filter property accepts one or more filter functions, each modifying the element's appearance in a specific way. Filters process in order, allowing layered effects.

blur() - Gaussian Blur Effect

The blur() filter applies Gaussian blur with a specified radius. Larger values create stronger blur. Accepts length values (px, rem, em) but not percentages.

/* Basic blur */ filter: blur(5px); /* Creates 5-pixel radius Gaussian blur */ /* Slight blur for depth */ filter: blur(2px); /* Strong blur for backgrounds */ filter: blur(10px); /* Practical examples */ /* Backdrop effect (before backdrop-filter was available) */ .modal-background { filter: blur(8px); } /* Focus effect */ .unfocused { filter: blur(3px); transition: filter 0.3s; } .unfocused:focus { filter: blur(0); } /* Loading state */ .loading { filter: blur(5px); pointer-events: none; }

brightness() - Lightness Control

The brightness() filter adjusts lightness from complete black (0) through normal (1) to infinitely bright. Values less than 1 darken; values greater than 1 lighten.

/* Darken element */ filter: brightness(0.5); /* 50% brightness, noticeably darker */ /* Normal (default) */ filter: brightness(1); /* Lighten element */ filter: brightness(1.5); /* 150% brightness, noticeably lighter */ /* Very bright */ filter: brightness(2); /* Double brightness */ /* Practical examples */ /* Dimmed inactive state */ .inactive { filter: brightness(0.6); } /* Highlight on hover */ .card:hover { filter: brightness(1.2); } /* Disabled appearance */ button:disabled { filter: brightness(0.8); cursor: not-allowed; } /* Loading shimmer (with animation) */ @keyframes shimmer { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.3); } } .shimmer { animation: shimmer 2s infinite; }

contrast() - Contrast Adjustment

The contrast() filter adjusts the difference between light and dark areas. Values less than 1 reduce contrast (approaching gray); values greater than 1 increase contrast.

/* Low contrast (washed out) */ filter: contrast(0.5); /* Reduces contrast by 50% */ /* Normal (default) */ filter: contrast(1); /* High contrast */ filter: contrast(1.5); /* Increases contrast by 50% */ /* Very high contrast */ filter: contrast(2.5); /* Dramatic, punchy appearance */ /* Practical examples */ /* Enhance photos */ .photo { filter: contrast(1.2); } /* Dramatic hover effect */ .image:hover { filter: contrast(1.5) brightness(1.1); } /* Accessibility: high contrast mode */ @media (prefers-contrast: high) { .content { filter: contrast(1.3); } } /* Disabled look */ .disabled { filter: contrast(0.5) brightness(0.9); }

Color Manipulation - grayscale, sepia, saturate

Three filters control color saturation and tone: grayscale() removes color, sepia() adds vintage brown tone, and saturate() adjusts color intensity.

/* grayscale() - Remove color (0% to 100%) */ filter: grayscale(50%); /* 50% desaturated */ filter: grayscale(100%); /* Fully black and white */ /* sepia() - Vintage brown tone (0% to 100%) */ filter: sepia(100%); /* Old photograph effect */ filter: sepia(50%); /* Subtle vintage tone */ /* saturate() - Color intensity (0 to infinity) */ filter: saturate(0.3); /* Desaturated, muted colors */ filter: saturate(2); /* Vibrant, vivid colors */ filter: saturate(4); /* Extremely vibrant */ /* Practical examples */ /* Inactive image */ .thumbnail { filter: grayscale(100%); transition: filter 0.3s; } .thumbnail:hover { filter: grayscale(0%); } /* Vintage photo effect */ .vintage-photo { filter: sepia(80%) contrast(1.2) brightness(0.9); } /* Enhance product images */ .product-image { filter: saturate(1.3) brightness(1.05); } /* Muted background */ .background-image { filter: saturate(0.5) brightness(0.8); }

hue-rotate() - Color Wheel Rotation

The hue-rotate() filter rotates colors around the color wheel. Accepts degree values from 0deg to 360deg, where 0deg/360deg returns to the original color.

/* No rotation (original color) */ filter: hue-rotate(0deg); /* 90-degree rotation */ filter: hue-rotate(90deg); /* Red → Yellow, Blue → Green, etc. */ /* 180-degree rotation (opposite colors) */ filter: hue-rotate(180deg); /* Red → Cyan, Blue → Yellow, etc. */ /* 270-degree rotation */ filter: hue-rotate(270deg); /* Practical examples */ /* Theme variations from single image */ .theme-green { filter: hue-rotate(90deg); } .theme-purple { filter: hue-rotate(270deg); } /* Color animation */ @keyframes rainbow { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } } .rainbow { animation: rainbow 5s linear infinite; } /* Duotone effect */ .duotone { filter: grayscale(100%) sepia(100%) hue-rotate(180deg) saturate(4); } /* Dynamic theming */ .element { filter: hue-rotate(var(--theme-hue, 0deg)); }

invert() & opacity() - Advanced Effects

The invert() filter creates negative images by reversing colors. The opacity() filter adjusts transparency, similar to the opacity property but processed as a filter.

/* invert() - Color inversion (0% to 100%) */ filter: invert(100%); /* Full color inversion: black→white, red→cyan, etc. */ filter: invert(50%); /* Partial inversion, creates gray midtone */ /* opacity() - Transparency (0% to 100%) */ filter: opacity(50%); /* 50% transparent */ filter: opacity(30%); /* 30% visible, 70% transparent */ /* Practical examples */ /* Dark mode image adjustment */ @media (prefers-color-scheme: dark) { .logo { filter: invert(100%); } } /* Disabled state */ .disabled { filter: opacity(40%) grayscale(100%); } /* Ghost/fade effect */ .ghost { filter: opacity(60%) blur(1px); } /* High contrast icons */ .icon-dark-bg { filter: invert(100%) brightness(2); } /* Combining invert with hue-rotate */ .creative-effect { filter: invert(100%) hue-rotate(180deg); }

drop-shadow() - Shape-Aware Shadows

Unlike box-shadow, the drop-shadow() filter creates shadows that follow the actual shape of elements, including transparency. Perfect for icons, SVG, and irregular shapes.

/* drop-shadow syntax */ filter: drop-shadow(offset-x offset-y blur-radius color); /* Basic drop shadow */ filter: drop-shadow(4px 4px 6px rgba(0, 0, 0, 0.3)); /* Shadow 4px right, 4px down, 6px blur */ /* Soft large shadow */ filter: drop-shadow(10px 10px 20px rgba(0, 0, 0, 0.5)); /* Glow effect (zero offset) */ filter: drop-shadow(0 0 15px rgba(255, 255, 0, 0.8)); /* Multiple drop shadows NOT supported - use multiple elements or combine with box-shadow */ /* Practical examples */ /* Icon shadow */ .icon { filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.3)); } /* SVG shadow (follows shape) */ .svg-graphic { filter: drop-shadow(5px 5px 10px rgba(0, 0, 0, 0.4)); } /* Text cutout effect */ .text-cutout { color: transparent; filter: drop-shadow(2px 2px 0 #333); } /* Neon glow */ .neon { filter: drop-shadow(0 0 10px #f0f) drop-shadow(0 0 20px #f0f) drop-shadow(0 0 30px #f0f); } /* Combining with other filters */ .enhanced-icon { filter: brightness(1.2) drop-shadow(3px 3px 6px rgba(0, 0, 0, 0.4)); }

Combining Multiple Filters

Multiple filter functions can be applied by listing them space-separated. Filters process from left to right, allowing complex layered effects.

/* Enhanced vibrant effect */ filter: brightness(1.2) contrast(1.3) saturate(1.5); /* First brighten, then increase contrast, then boost saturation */ /* Vintage photograph */ filter: sepia(80%) contrast(1.2) brightness(0.9); /* Sepia tone with enhanced contrast and slight darkening */ /* Dramatic black and white */ filter: grayscale(100%) contrast(1.8) brightness(1.1); /* Convert to B&W with high contrast and slight brightening */ /* Glowing effect */ filter: brightness(1.2) saturate(1.3) drop-shadow(0 0 20px rgba(102, 126, 234, 0.6)); /* Brighten, saturate, then add glow */ /* Duotone effect */ filter: grayscale(100%) sepia(100%) hue-rotate(180deg) saturate(4); /* Remove color, add sepia, shift hue, boost saturation */ /* Soft focus with enhancement */ filter: blur(1px) brightness(1.1) contrast(1.2) saturate(1.3); /* Dark mode image adjustment */ filter: invert(100%) hue-rotate(180deg); /* Frosted glass effect */ filter: blur(10px) brightness(1.2) saturate(1.5); /* Order matters! */ filter: grayscale(100%) hue-rotate(90deg); /* No visible effect - can't rotate hue of grayscale */ filter: hue-rotate(90deg) grayscale(100%); /* Rotates hue THEN converts to grayscale - still appears gray */

Interactive Filter Effects

Combine filters with CSS transitions and hover states for smooth, engaging interactions. Filters transition smoothly, making them perfect for hover effects.

/* Hover brighten effect */ .card { transition: filter 0.3s ease; } .card:hover { filter: brightness(1.2) saturate(1.2); } /* Grayscale to color on hover */ .image { filter: grayscale(100%); transition: filter 0.4s ease; } .image:hover { filter: grayscale(0%); } /* Glow on hover */ .button { transition: filter 0.3s ease; } .button:hover { filter: brightness(1.2) drop-shadow(0 0 20px rgba(102, 126, 234, 0.8)); } /* Focus state with multiple filters */ .input { filter: brightness(1) saturate(1); transition: filter 0.2s ease; } .input:focus { filter: brightness(1.1) saturate(1.3) drop-shadow(0 0 8px rgba(59, 130, 246, 0.5)); } /* Animated rainbow effect */ @keyframes rainbow { 0%, 100% { filter: hue-rotate(0deg); } 50% { filter: hue-rotate(180deg); } } .rainbow { animation: rainbow 4s ease-in-out infinite; } /* Performance optimization for animated filters */ .animated-element { will-change: filter; filter: brightness(1); }

Key Takeaways

  • 10 Filter Functions: blur, brightness, contrast, drop-shadow, grayscale, hue-rotate, invert, opacity, saturate, sepia
  • Multiple filters: Space-separated, process left to right
  • blur(): Accepts px/rem/em, no percentages; larger values = stronger blur
  • brightness(): 0 = black, 1 = normal, >1 = lighter; great for hover effects (1.1-1.3)
  • contrast(): 0 = gray, 1 = normal, >1 = increased difference between light/dark
  • grayscale/sepia: 0% to 100%; grayscale removes color, sepia adds vintage tone
  • saturate(): 0 = grayscale, 1 = normal, >1 = vivid; subtle boosts (1.2-1.4) enhance photos
  • hue-rotate(): 0deg to 360deg rotates color wheel; black/white/gray unchanged
  • drop-shadow(): Follows element shape including transparency, unlike box-shadow's rectangle
  • Filter order matters: Apply color transforms before desaturation
  • Smooth transitions: Use transition: filter 0.3s for interactive effects
  • GPU-accelerated: Filters perform well; use will-change: filter for animations
  • Combine filters for sophisticated effects: vintage photos, duotone, glow, dramatic B&W