Snippets / Layout /

Filter chain effect

Stack multiple CSS filter values to create complex visual transformations — blur, brightness, hue-rotate, and more in a single declaration.

Chained
Vivid
Mono

Filter Chain

Multiple filters stack left-to-right. Each filter processes the output of the previous one.

Widely supported
colorno-js

Quick implementation

.filtered-element {
  /* Stack multiple filters — order matters! */
  filter: blur(4px) brightness(1.2) hue-rotate(30deg);
}

/* Vivid color enhancement */
.vivid-enhancement {
  filter: saturate(2) contrast(1.3) sepia(0.3);
}

/* Grayscale with shadow */
.grayscale-shadow {
  filter: grayscale(1) blur(2px) drop-shadow(0 4px 8px oklch(0 0 0 / 0.4));
}

/* Remove filter on reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
  .filtered-element {
    filter: none;
  }
}

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer specializing in modern CSS.

Goal: Create a visual effect by chaining multiple CSS filters together (blur, brightness, hue-rotate, saturate, etc.).

Technical constraints:
- Use the filter property with multiple functions chained in a single declaration.
- Filters are applied left-to-right; each filter processes the output of the previous one.
- Use oklch() for any drop-shadow or color values — no hex or rgba().
- Include a @media (prefers-reduced-motion: reduce) rule that removes filters for users who prefer less motion.
- Consider performance: multiple filters trigger GPU compositing.

Framework variant (pick one):
A) Vanilla HTML/CSS only — return a class with the filter chain applied.
B) React component — accept `children`, `className`, and `filterVariant` props ('blur', 'vivid', 'mono', etc.).

Edge cases to handle:
- What happens when filter is not supported? Provide a fallback using @supports (filter: blur(1px)).
- Performance impact: multiple filters may slow down animation on low-end devices.
- Accessibility: ensure filtered images still convey meaning (don't over-blur important details).

Return the HTML structure and CSS, clearly separated.

Why this matters in 2026

Filter chains let you create complex visual effects with a single CSS declaration. Instead of stacking multiple pseudo-elements or relying on SVG filters, you can chain blur(), brightness(), hue-rotate(), saturate(), and more. This reduces markup, improves maintainability, and keeps visual logic in CSS where designers expect it. In 2026, filter is GPU-accelerated across all major browsers, making filter chains performant even for interactive elements.

The logic

The filter property accepts multiple functions in a single declaration. They are applied left-to-right, with each function processing the output of the previous one. For example, filter: blur(4px) brightness(1.2) first blurs the element, then brightens the blurred result. This order matters: filter: brightness(1.2) blur(4px) would brighten first, then blur — producing a subtly different visual outcome.

Common filter functions include blur(), brightness(), contrast(), grayscale(), sepia(), saturate(), hue-rotate(), invert(), opacity(), drop-shadow(), and url() (for SVG filters). Combine them to create custom visual treatments like duotone effects, vintage filters, or atmospheric overlays.

Accessibility & performance

Filters are GPU-accelerated in modern browsers, making them efficient for static and animated use. However, multiple chained filters can still impact performance on low-end devices, especially on large elements. Test your filter chains on mobile before deploying at scale.

For accessibility, avoid over-using filters on content that conveys meaning. A heavily blurred image may lose its communicative value. Always provide an alt attribute for filtered images. Respect @media (prefers-reduced-motion: reduce) by removing or simplifying filters for users who prefer less visual activity.

Browser support note: filter is widely supported in all modern browsers. However, older mobile browsers (iOS Safari < 9, Android Chrome < 34) lack support. Use @supports (filter: blur(1px)) to provide fallbacks for critical content.