How to apply a CSS filter to a background image
Categories:
Applying CSS Filters to Background Images

Learn how to apply various CSS filter effects like blur, grayscale, and brightness directly to background images without affecting foreground content.
CSS filters provide a powerful way to apply visual effects to elements on a webpage. While commonly used on <img>
tags, applying filters directly to background-image
properties can be a bit more nuanced. This article will guide you through the techniques to achieve this, ensuring your background images have the desired visual treatment without impacting the content layered on top.
The Challenge: Direct Filter Application
The primary challenge with applying CSS filters to background images stems from the fact that the filter
property in CSS applies to the entire element, including its content. If you apply a filter directly to an element with a background image and text, both the image and the text will be filtered, which is often not the desired outcome. We want to isolate the filter effect to just the background.
flowchart TD A[Element with Background Image] --> B{Apply `filter` property?} B -->|Yes| C[Background Image AND Content Filtered] B -->|No| D[Explore Alternative Methods] D --> E[Use Pseudo-elements] D --> F[Use Nested Elements] E --> G[Background Image Filtered, Content Unaffected] F --> G
Decision flow for applying CSS filters to background images.
Solution 1: Using Pseudo-elements (::before
or ::after
)
The most common and robust method to apply filters exclusively to a background image is by using a pseudo-element (::before
or ::after
). This approach involves creating a pseudo-element, positioning it behind the main content, assigning the background image to it, and then applying the filter to the pseudo-element. This keeps the main element's content unaffected.
<div class="hero-section">
<h1>Welcome to My Site</h1>
<p>This text remains sharp!</p>
</div>
.hero-section {
position: relative;
height: 300px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
z-index: 1; /* Ensure content is above pseudo-element */
}
.hero-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://picsum.photos/id/1015/800/300'); /* Replace with your image */
background-size: cover;
background-position: center;
filter: blur(5px) grayscale(50%); /* Apply desired filters here */
z-index: -1; /* Position behind the content */
}
position: relative;
on the parent element and position: absolute;
on the pseudo-element for proper positioning. Also, adjust z-index
values to ensure the pseudo-element is behind the content.Solution 2: Using Nested Elements
Another approach involves using a nested div
element specifically for the background image. This div
can then have the background image and filter applied to it, while the sibling elements (or children of a parent wrapper) hold the main content. This method is less common than pseudo-elements but can be useful in certain layout scenarios.
<div class="hero-wrapper">
<div class="background-filter-layer"></div>
<div class="content-layer">
<h1>Nested Element Approach</h1>
<p>This text is also unaffected by the filter.</p>
</div>
</div>
.hero-wrapper {
position: relative;
height: 300px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.background-filter-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://picsum.photos/id/1018/800/300'); /* Replace with your image */
background-size: cover;
background-position: center;
filter: brightness(0.6) contrast(1.2); /* Apply different filters */
z-index: -1;
}
.content-layer {
position: relative; /* Ensure content is above the background layer */
z-index: 1;
text-align: center;
}
div
to your HTML structure, which might be considered less semantic than using pseudo-elements for purely decorative backgrounds.