CSS blur() Function: Practical Guide for Modern UI

I still remember the first time I shipped a frosted glass header and wondered why it looked sharp on my laptop but muddy on a mid-range phone. That moment pushed me to really understand how blur() behaves, how much it costs in rendering time, and what design choices actually hold up across devices. If you have ever tried to soften a hero image, build a background haze behind a modal, or reduce distraction by de-emphasizing content, you have already reached for the blur() function. The effect feels simple, but the details matter: how the blur radius is interpreted, how it interacts with layout and compositing, and how to keep it performant while still looking intentional.

You are going to get a clear, practical view of blur() as it exists in modern CSS. I will show you how the function works, where it shines, where it bites back, and the implementation patterns I trust in production. We will cover syntax, units, visual results, performance ranges, accessible fallbacks, and the mental model I use to avoid common mistakes. You will also see complete, runnable examples that you can paste into a file and test immediately.

How blur() Works in CSS Filters

The blur() function is part of the CSS filter property. Conceptually, it applies a Gaussian blur to the pixels of an element as it is painted. The key to remember is that this happens during the rendering phase, after layout and paint for the element are already determined. In practice, that means blur() does not change the element’s layout box, but it absolutely changes how much space the visual effect appears to occupy.

The function takes a single length value called the blur radius. The browser uses that radius to determine how much neighboring pixel data to mix into each pixel. A larger radius means more neighboring pixels are sampled, which produces a softer, more out-of-focus look. A blur radius is not a percentage of the element size; it is a physical length based on CSS units like px, rem, or %. For most UI work, px and rem are the safest choices because their results are more predictable across screen densities and font scaling.

One detail I rely on: the visual spread of a blurred element extends beyond its original boundary. This is why you often see blur clipped at container edges if overflow is hidden. If you blur an image inside a card with overflow: hidden, the blur will be visibly cut off at the edges. Sometimes that is desirable, but often it is a surprise. If you need the blur to glow outward, you either provide extra padding or blur a larger layer behind the visible container.

Another nuance that bites people: the blur is applied after the element is rendered, which means effects like box-shadow, borders, and text are blurred too if they are part of the element. If you want only the background to blur while keeping text sharp, you must separate layers (for example, with a pseudo-element) and apply filter to the background layer only.

Syntax and Practical Parameter Choices

The syntax is simple:

filter: blur(12px);

That simplicity hides a few choices you should make deliberately:

  • Unit selection: I use px for precise visual tuning and rem when the blur should scale with the user’s font size. rem helps maintain a consistent softness relative to the rest of the UI.
  • Zero is valid: blur(0) is useful for toggling the effect without changing code paths. It allows you to keep a single class and update a custom property or state.
  • Large values: Anything above about 20px on normal-sized UI elements quickly becomes heavy and can create muddy edges. For large backgrounds or hero images, 20–40px can be acceptable, but I usually blur a downscaled layer instead of the full-size asset.

A subtle point: blur() requires a length, not a percentage of the element size. A percentage may be accepted in some browsers but it is not as reliable. Stick with px or rem for consistent output.

Visual Intent: When Blur Helps and When It Hurts

Blur is great for guiding attention. You can blur non-primary elements while keeping the focus on a foreground component. I often use it for:

  • Background images behind a text block to increase contrast without changing the image content
  • Softening repeated textures so they do not compete with foreground typography
  • De-emphasizing inactive cards or sections during a progressive reveal
  • Creating a depth cue in data dashboards, so the currently active panel stands out

Where blur hurts:

  • Small text or thin line art: even a 2px blur can make text illegible.
  • High-density iconography: icons with fine details lose their crispness quickly.
  • Performance-sensitive animations: animating blur radius at 60fps is expensive on many devices.

If you are blurring content that the user must read, stop and reconsider. Blur is a visual cue, not a substitute for state change. If the content is still important, reduce opacity or shift contrast instead.

Complete Example: Single Image Blur

This example blurs a logo while keeping the headline sharp. It also shows a mild shadow so the blurred image does not look cut off.






CSS blur() Example

:root {

--brand-green: #1b7f3b;

}

body {

margin: 0;

min-height: 100vh;

display: grid;

place-items: center;

font-family: ‘Georgia‘, serif;

background: #f5f7f3;

color: #1f2a1f;

}

.card {

background: #fff;

padding: 40px 48px;

border-radius: 18px;

box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12);

text-align: center;

width: min(540px, 90vw);

}

h1 {

margin: 0 0 16px;

color: var(--brand-green);

font-size: 2.4rem;

letter-spacing: 0.5px;

}

.blurred {

filter: blur(5px);

margin-top: 8px;

box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);

}

img {

width: 200px;

height: auto;

display: inline-block;

}

Brand Focus

Sharp heading, softened graphic.

Brand logo

Notes from my own usage:

  • I add a shadow when the blur is moderate because the edge of the blur can feel too soft. The shadow gives the eye a boundary.
  • I keep blur between 3–8px for small graphics. If I want a stronger effect, I reduce opacity instead of cranking up blur.

Example: Comparing Multiple Blur Values

When you want to teach your team how blur scales, it helps to show multiple values side by side. Here is a complete example using Flexbox. The key detail is that all images are the same size; only the blur radius changes.






Blur Comparison

body {

margin: 0;

padding: 32px;

font-family: ‘Source Serif 4‘, serif;

background: #f1efe9;

color: #243028;

}

h1 {

margin-bottom: 20px;

font-size: 2rem;

}

.row {

display: flex;

gap: 16px;

align-items: center;

flex-wrap: wrap;

}

.tile {

background: #fff;

padding: 12px;

border-radius: 12px;

box-shadow: 0 10px 20px rgba(0, 0, 0, 0.08);

text-align: center;

width: 140px;

}

img {

width: 80px;

height: 80px;

display: block;

margin: 0 auto 8px;

}

.blur-none { filter: blur(0); }

.blur-med { filter: blur(3px); }

.blur-large { filter: blur(1.5rem); }

Blur Radius Comparison

No blur
blur(0)
3px blur
blur(3px)
1.5rem blur
blur(1.5rem)

I often replace logo.png with any neutral icon or pattern so the blur effect reads clearly. If you use a high-contrast photo, the strongest blur can look like a low-quality image rather than an intentional effect.

Performance and Rendering Costs

Blur is not a free effect. It typically triggers the browser to render the element into an offscreen buffer and then apply a pixel-based filter. On modern desktops, small blur values on small elements might cost around 1–4ms per frame. On mid-range phones, that can climb to 8–15ms per frame, which already eats most of your 16ms budget for 60fps.

Here is how I keep it under control:

  • Avoid animating blur radius: toggling the blur class on and off is cheaper than smooth animation. If you must animate, do it once and then settle on a static value.
  • Blur smaller layers: blur a downscaled image and then scale it up, or blur a pseudo-element with a smaller background image.
  • Avoid blurring large videos: a blurred video frame is expensive; if you need a blurred background, consider a static poster or use a pre-blurred fallback image.
  • Contain complexity: filter interacts with stacking contexts and compositing. Keep the blurred element isolated so the browser can optimize it without re-rendering the whole page.

I also test blur performance using browser devtools’ rendering metrics. In 2026, most devtools offer a rendering cost or frames view. I target a blur cost low enough that my interaction animations stay smooth.

Common Mistakes I See in Code Reviews

I review a lot of CSS, and blur mistakes show up constantly. Here are the top ones and how I fix them:

  • Clipping blur at container edges: If the container has overflow: hidden, the blur is cut off. Fix by adding padding, or apply the blur to a pseudo-element that is larger than the visible area.
  • Blurring readable text: If the user needs to read it, don’t blur it. Use opacity or reduce contrast instead.
  • Animating blur on scroll: This causes frame drops in many browsers. If you want a dynamic blur, use a small range (0–4px) and throttle updates.
  • Using very large blur values: Large values create a foggy look that often feels accidental. If you need big softness, reduce image resolution first and then apply a smaller blur.
  • Forgetting fallbacks: Not all environments render filters smoothly. Always provide a reasonable fallback color or background layer.

If you remember only one rule: blur should be the first thing you remove when you are debugging a performance issue.

Practical Patterns I Trust

Here are a few patterns that I use regularly because they are predictable and safe.

Pattern 1: Frosted Header with Backdrop Layer

This uses backdrop-filter, which blurs what is behind the element, not the element itself. It is not the same as filter: blur() but often the visual goal is identical. When backdrop-filter is unavailable, I fall back to a translucent background.

<div class='headercontent‘>Dashboard
.header {

position: sticky;

top: 0;

backdrop-filter: blur(12px);

background: rgba(255, 255, 255, 0.7);

border-bottom: 1px solid rgba(0, 0, 0, 0.08);

}

I often combine this with a gradient background so the blur feels intentional, not just like a broken image.

Pattern 2: De-emphasize Inactive Cards

A small blur paired with opacity signals not active without hiding the content.

.card {

transition: opacity 200ms ease;

}

.card.is-inactive {

filter: blur(2px);

opacity: 0.6;

}

I keep the blur under 3px. At 4px and above, the text gets hard to read.

When to Use vs When Not to Use

This is where I give direct guidance. If you are unsure, lean toward clarity.

Use blur when:

  • You need to keep the content visible but clearly de-emphasized.
  • You are creating a background layer that supports readable foreground text.
  • You want a depth cue in a UI with stacked layers.

Do not use blur when:

  • The element contains text the user must read quickly.
  • The blur will animate frequently or in response to pointer movement.
  • The element is very large and already expensive to render (full-screen video).
  • The device range includes low-end phones or embedded browsers with limited GPU acceleration.

If you need a strong visual separation, I usually recommend a combination of contrast, spacing, and opacity before blur.

Traditional vs Modern Approach Table

This table shows how my own approach has shifted over the last few years. The modern method is not flashy; it is just more reliable.

Goal

Traditional Approach

Modern Approach —

— Soft background

Apply filter: blur(20px) to a full-size image

Use a downscaled background image + blur(8px) Focused content

Blur active area and leave others sharp

Keep active area sharp, blur only inactive cards Smooth transition

Animate blur from 0 to 12px

Cross-fade between sharp and blurred layers Compatibility

Assume filters are fine everywhere

Provide visual fallback for filter off

If you are designing for a wide device range, the modern approach is the safer default.

Browser Support and Compatibility Notes

The blur() function is part of the standard filter property and is widely supported in modern browsers. You should assume it works in current Chrome, Firefox, Safari, and Edge. If you still support older browsers, you will need a fallback, because some older engines ignore filter entirely or render it poorly.

My fallback approach is straightforward:

  • Use a solid or semi-transparent background color behind text.
  • For images, pre-blur a version of the asset and swap it with a class or media query.
  • Keep the layout stable so the effect is purely visual; do not tie layout changes to the filter.

If you need a quick check, you can use a feature query:

@supports (filter: blur(2px)) {

.soft-focus { filter: blur(2px); }

}

This prevents unexpected visuals in old browsers while still allowing modern ones to get the effect.

Edge Cases and Real-World Scenarios

These are the subtle cases I watch for in production:

  • SVG content: Blurring an SVG can soften its edges in ways that feel fuzzy rather than soft. If you want a blurred SVG, I often export it as a raster image at a higher resolution and then blur it lightly.
  • High-DPI screens: A 2px blur on a dense screen can feel weaker than expected. This is another reason I use rem for blur on text-heavy layouts.
  • Text selection: Blurred text still selects, which can look strange. If a blur indicates disabled, you should also prevent pointer events or selection.
  • Backdrop vs filter: Developers confuse the two. filter: blur() affects the element itself. backdrop-filter affects what is behind it. Pick the one that matches your visual goal.
  • Scroll containers: If the blurred element is inside a container that is frequently repainted (like a smooth-scrolling list), the blur can cause jank and overdraw. Isolate the blur in a separate layer or replace it with a static, pre-blurred image for scrolling contexts.

In addition to those, watch out for transform and filter interactions. A transformed element may create a new stacking context, which can change how the filter is composited. If a blur looks wrong or is clipped, check whether the element or its ancestors have transform, filter, or will-change applied.

The Mental Model I Use for Blur

When I am making design choices, I use a simple mental model:

  • A blur is a post-processing effect, not a layout change.
  • The blur radius is a physical length, not a percentage of the element.
  • The blur expands beyond the original pixels, so it can be clipped by overflow.
  • Blur multiplies cost: the larger the element and the larger the radius, the heavier the filter.

This model keeps me from applying blur to the wrong layer or assuming it will scale with the element size. It also reminds me to separate backgrounds from content so the blur can be targeted without destroying legibility.

Layering Strategy: Keep Text Sharp, Blur the Background

A common real-world need is to blur a background image while keeping text sharp. The simplest, reliable approach is to separate layers with a pseudo-element.

<div class='herocontent‘>

Focus on the Story

A soft background keeps the message clear.

.hero {

position: relative;

min-height: 320px;

padding: 64px 40px;

color: #1b1f1d;

overflow: hidden;

border-radius: 24px;

background: #f4f1ed;

}

.hero::before {

content: ‘‘;

position: absolute;

inset: -20px;

background: url(‘hero.jpg‘) center / cover no-repeat;

filter: blur(12px);

transform: scale(1.05);

z-index: 0;

}

.herocontent {

position: relative;

z-index: 1;

max-width: 520px;

}

I use inset: -20px to give the blur room so it does not clip. The transform: scale(1.05) helps avoid softened edges at the border when the blur pulls pixels inward. This pattern is my default for soft backgrounds.

Cross-Fade Instead of Blur Animation

If you need a blur transition, I typically avoid animating the blur radius. Instead, I cross-fade between sharp and blurred layers. This is visually smooth and cheaper to render.

Sharp scene
.photo-stack {

position: relative;

width: 320px;

height: 200px;

}

.photo {

position: absolute;

inset: 0;

width: 100%;

height: 100%;

object-fit: cover;

transition: opacity 240ms ease;

}

.photo--soft {

filter: blur(12px);

opacity: 0;

}

.photo-stack.is-soft .photo--soft { opacity: 1; }

.photo-stack.is-soft .photo--sharp { opacity: 0; }

This keeps the blur static and leverages opacity, which is usually cheaper to animate. I use this in modals, drawers, and focus states where I need a soft shift without a heavy GPU cost.

Blur for Placeholder Loading (Blur-Up Technique)

A nice, practical use of blur is progressive image loading. You show a small blurred placeholder and swap in the full-resolution image when it loads. This can improve perceived performance and reduce layout shifts.

Mountain sunrise Mountain sunrise
.photo-wrap {

position: relative;

width: 100%;

max-width: 720px;

aspect-ratio: 16 / 9;

overflow: hidden;

border-radius: 16px;

background: #efece8;

}

.photo-wrap img {

position: absolute;

inset: 0;

width: 100%;

height: 100%;

object-fit: cover;

}

.photo-blur {

filter: blur(16px);

transform: scale(1.08);

}

.photo-full {

opacity: 0;

transition: opacity 240ms ease;

}

.photo-wrap.is-loaded .photo-full { opacity: 1; }

.photo-wrap.is-loaded .photo-blur { opacity: 0; }

When the full image finishes loading, toggle is-loaded on the wrapper. I like this because the blur hides compression artifacts in the low-res image, and the transition feels polished without needing heavy JavaScript.

Accessibility and Interaction Considerations

Blur can be confusing if it suggests an interactive state but still allows interaction. I follow a few accessibility rules:

  • If blur indicates disabled, also set pointer-events: none and reduce contrast with opacity.
  • If blur indicates a background state (like a modal open), make sure keyboard focus is trapped in the foreground content.
  • Do not blur text that users must read to complete a task. If you must de-emphasize text, lower opacity or increase spacing.
  • Provide a clear non-visual cue for state changes such as labels, focus outlines, or icon changes.

Blur is visual. Users who rely on assistive technology should still get clear semantic cues.

Performance Tactics I Actually Use

When I need blur in production, I apply a short list of tactics that make it safer:

  • Pre-blur assets: If the background never changes, I ship a pre-blurred image and apply a light blur(2px) at most. It looks cleaner and costs less.
  • Limit blur area: I keep the blurred layer as small as possible, often a pseudo-element limited to a card or header rather than the entire page.
  • Reduce update frequency: If blur changes based on scroll, I use a small range and throttle updates to avoid too many repaints.
  • Avoid stacking many filters: Multiple filters (like blur + brightness) can compound cost. If I need multiple effects, I test on a mid-range phone to confirm it still feels smooth.

A good sign is when performance remains smooth with the browser devtools FPS meter open. If the meter drops during scroll or hover, blur is a likely culprit.

Units Deep Dive: px, rem, and Why It Matters

Most blur examples use px, and that is usually fine. But I also like rem in typography-heavy layouts where I want the blur to scale with font size. For example, a 2px blur might look subtle at a 16px base font but too strong at a 12px base. Using rem ties the blur to the root font size so the effect scales with the user’s settings.

Here is how I decide:

  • Use px when I want a fixed, art-directed blur.
  • Use rem when the blur should feel consistent relative to text size.
  • Avoid % because it is inconsistent across engines and can produce surprising results.

In practice, I rarely go below 1px for visible blur, and I rarely go above 24px unless I am blurring a huge background layer.

Filter vs Backdrop-Filter: Clear Separation

A common confusion is whether to use filter: blur() or backdrop-filter: blur(). I keep it simple:

  • filter: blur() affects the element itself.
  • backdrop-filter: blur() affects everything behind the element.

If you want to blur the contents of a card, use filter. If you want to blur the page behind a glass card, use backdrop-filter. In both cases, provide a fallback because backdrop-filter is not supported everywhere and can have performance costs.

Here is a reliable fallback pattern:

.glass {

background: rgba(255, 255, 255, 0.65);

}

@supports (backdrop-filter: blur(10px)) {

.glass {

backdrop-filter: blur(10px);

background: rgba(255, 255, 255, 0.5);

}

}

The fallback keeps a readable background even when the blur is missing.

Combining Blur with Other Filters

The filter property can take multiple functions. You can combine blur with brightness or contrast to shape the visual mood. But you should do it deliberately, because multiple filters can muddy content quickly.

Example combination:

.soft-backdrop {

filter: blur(10px) brightness(0.9) saturate(1.1);

}

I only use combinations when I am trying to make a photo background support text. For content the user reads, I avoid multi-filter effects because readability drops fast.

Blur and Layout: Avoid the Illusion of Size Changes

Because blur spreads beyond the element’s box, a blurred element may appear larger. This can cause visual misalignment with adjacent elements. If you see it, you can do one of these:

  • Add padding to the container so the blur has room to breathe.
  • Expand the blurred layer with negative inset values.
  • Use a pseudo-element for the blurred layer and leave the original element sharp.

These small layout tweaks prevent the blur from clipping and keep your UI aligned.

Debugging Checklist

When a blur looks wrong or causes performance issues, I run through a short checklist:

  • Is the blur applied to the right layer (background vs content)?
  • Is the blur getting clipped by overflow: hidden?
  • Is the element huge (full-screen) and therefore costly?
  • Are there unnecessary animations that trigger repaints?
  • Is there a transform or filter on a parent creating unexpected stacking contexts?

This checklist saves me time, because blur issues are often layer problems rather than design problems.

Additional Practical Scenario: Modal Focus Haze

A classic use of blur is to soften the background when a modal opens. I prefer to blur the main content area and keep the modal crisp.

...
.page.is-dimmed {

filter: blur(3px);

opacity: 0.7;

}

.modal {

position: fixed;

inset: 0;

display: grid;

place-items: center;

background: rgba(20, 22, 21, 0.4);

}

.modalcard {

background: #fff;

padding: 32px;

border-radius: 16px;

box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2);

}

The key is to blur a container that does not include the modal. That way the modal stays sharp and readable, and the blur makes the modal feel grounded.

Blur and Images: Why Downscaling Helps

If you blur a very large image, the browser still needs to process that large pixel surface. A trick I use is to downscale the image for the blurred layer. You can do this by loading a smaller image file or by using background-size and a low-resolution asset.

For example, if the visible hero image is 2000px wide, I might use a 600px wide blurred version for the background. The blur hides the lower resolution, and the browser has less work to do.

Avoiding Muddy Results

Blur can feel muddy when the source image has high contrast edges. If you see that, try one of these:

  • Reduce the blur radius and add a translucent overlay instead.
  • Lower saturation slightly so edges do not dominate.
  • Use a smoother, lower-contrast image for blurred backgrounds.

I always aim for blur that feels like light diffusion, not a low-quality image.

Testing Across Devices

This is a point I rarely skip anymore. I test blur on:

  • A modern laptop with a high-resolution display.
  • A mid-range phone with average GPU power.
  • A low-end device if the audience includes budget Android devices.

If blur feels muddy or laggy on any of those, I reduce the radius or swap to a pre-blurred asset. Real devices tell the truth more than simulated performance tools.

Production-Safe Fallback Strategy

If you need a blur effect but cannot trust it everywhere, I prefer a layered fallback:

  • Base layer: a solid or translucent color to ensure text readability.
  • Optional blurred layer: if filter is supported, add blur.
  • Optional pre-blurred image: if you want extra smoothness without cost.

Here is a small example:

.panel {

background: rgba(255, 255, 255, 0.82);

}

@supports (filter: blur(6px)) {

.panel::before {

content: ‘‘;

position: absolute;

inset: -16px;

background: url(‘panel-bg-small.jpg‘) center / cover no-repeat;

filter: blur(6px);

z-index: 0;

}

.panel > * { position: relative; z-index: 1; }

}

This approach degrades gracefully: if filters are off, the panel still looks clean and legible.

Quick Reference: Blur Do and Don’t

I keep this list handy when I am reviewing CSS:

Do:

  • Apply blur to background layers, not text.
  • Keep radii small for UI components (1–6px).
  • Use pre-blurred images for large areas.
  • Provide a fallback for older or constrained environments.

Don’t:

  • Animate blur at high frequency.
  • Blur massive elements on low-end devices.
  • Assume blur will behave the same across all browsers and screens.
  • Rely on blur as the only indicator of state.

Final Thoughts

blur() looks like a small, single-function effect, but it touches nearly every part of rendering: performance, compositing, and accessibility. When I use it carefully, it adds a sense of depth and polish without distracting the user. When I use it casually, it quickly becomes muddy or expensive.

If you take away one practical approach, let it be this: blur only what you must, keep the radius modest, and treat it as a background utility rather than a foreground effect. When you do that, blur() becomes a reliable tool in your CSS kit rather than a risky flourish.

Expansion Strategy

Add new sections or deepen existing ones with:

  • Deeper code examples: More complete, real-world implementations
  • Edge cases: What breaks and how to handle it
  • Practical scenarios: When to use vs when NOT to use
  • Performance considerations: Before and after comparisons (use ranges, not exact numbers)
  • Common pitfalls: Mistakes developers make and how to avoid them
  • Alternative approaches: Different ways to solve the same problem

If Relevant to Topic

  • Modern tooling and AI-assisted workflows (for infrastructure/framework topics)
  • Comparison tables for Traditional vs Modern approaches
  • Production considerations: deployment, monitoring, scaling
Scroll to Top