fox
fox

Reputation: 5809

How to apply a CSS filter to a background image

I have a JPEG file that I'm using as a background image for a search page, and I'm using CSS to set it because I'm working within Backbone.js contexts:

background-image: url("whatever.jpg");

I want to apply a CSS 3 blur filter only to the background, but I'm not sure how to style just that one element. If I try:

-webkit-filter: blur(5px);
-moz-filter: blur(5px);
-o-filter: blur(5px);
-ms-filter: blur(5px);
filter: blur(5px);

just underneath background-image in my CSS, it styles the whole page, rather than just the background. Is there a way to select just the image and apply the filter to that? Alternatively, is there a way to just turn the blur off for every other element on the page?

Upvotes: 565

Views: 1853919

Answers (22)

hitautodestruct
hitautodestruct

Reputation: 20820

As stated in other answers this can be achieved with:

  • A copy of the blurred image as the background.
  • A pseudo element that can be filtered then positioned behind the content.

You can also use backdrop-filter

There is a supported property called backdrop-filter, and it is currently supported in Chrome, Firefox, Edge, Safari, and iOS Safari (see caniuse.com for statistics).

From Mozilla devdocs:

The backdrop-filter property provides for effects like blurring or color shifting the area behind an element, which can then be seen through that element by adjusting the element's transparency/opacity.

See caniuse.com for usage statistics.

You would use it like so. If you do not want content inside to be blurred use the utility class .u-non-blurred

.background-filter::after {
  -webkit-backdrop-filter: blur(4px); /* Use for Safari 9+, Edge 17+ (not a mistake) and iOS Safari 9.2+ */
  backdrop-filter: blur(4px); /* Supported in all major browsers */

  content: "";
  display: block;
  position: absolute;
  width: 100%; height: 100%;
  top: 0;
}

.background-filter {
  position: relative;
}

.background {
  background-image: url('https://placekeanu.com/200/200');
  width: 200px;
  height: 200px;
}

/* Use for child content that should not be blurred */
.u-non-blurred {
  position: relative;
  z-index: 1;
  
  /* For text decoration, not mandatory */
  filter: invert(100%);
  padding: 7px;
}
<div class="background background-filter">
  <h1 class="u-non-blurred">Keanu C. Reeves</h1>
</div>

Upvotes: 98

Necrone
Necrone

Reputation: 1257

Abolishing the need for an extra element, along with making the content fit within the document flow rather than being fixed/absolute like other solutions.

Achieved using

.content {
  /* this is needed or the background will be offset by a few pixels at the top */
  overflow: auto;
  position: relative;
}

.content::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: -1;

  display: block;
  background-image: url('https://i.sstatic.net/CjzQS.jpg');
  background-size:cover;
  width: 100%;
  height: 100%;

  -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(5px);
  -ms-filter: blur(5px);
  filter: blur(5px);
}
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>

If you are interested in removing the white borders at the edges, use a width and height of 110% and a left and top of -5%. This will enlarge your backgrounds a tad, but there should be no solid colour bleeding in from the edges.

.content {
  /* this is needed or the background will be offset by a few pixels at the top */
  overflow: auto;
  position: relative;
}

.content::before {
  content: "";
  position: fixed;
  top: -5%;
  left: -5%;
  right: -5%;
  z-index: -1;

  display: block;
  background-image: url('https://i.sstatic.net/CjzQS.jpg');
  background-size:cover;
  width: 110%;
  height: 110%;

  -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(5px);
  -ms-filter: blur(5px);
  filter: blur(5px);
}
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>

Upvotes: 108

Aniket
Aniket

Reputation: 9758

You will have to use two different containers, one for the background image and the other for your content.

In the example, I have created two containers, .background-image and .content.

Both of them are placed with position: fixed and left: 0; right: 0;. The difference in displaying them comes from the z-index values which have been set differently for the elements.

.background-image {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 1;
  display: block;
  background-image: url('https://i.sstatic.net/CjzQS.jpg');
  width: 1200px;
  height: 800px;
  -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(5px);
  -ms-filter: blur(5px);
  filter: blur(5px);
}

.content {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 9999;
  margin-left: 20px;
  margin-right: 20px;
}
<div class="background-image"></div>
<div class="content">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquam erat in ante malesuada, facilisis semper nulla semper. Phasellus sapien neque, faucibus in malesuada quis, lacinia et libero. Sed sed turpis tellus. Etiam ac aliquam tortor, eleifend
    rhoncus metus. Ut turpis massa, sollicitudin sit amet molestie a, posuere sit amet nisl. Mauris tincidunt cursus posuere. Nam commodo libero quis lacus sodales, nec feugiat ante posuere. Donec pulvinar auctor commodo. Donec egestas diam ut mi adipiscing,
    quis lacinia mauris condimentum. Quisque quis odio venenatis, venenatis nisi a, vehicula ipsum. Etiam at nisl eu felis vulputate porta.</p>
  <p>Fusce ut placerat eros. Aliquam consequat in augue sed convallis. Donec orci urna, tincidunt vel dui at, elementum semper dolor. Donec tincidunt risus sed magna dictum, quis luctus metus volutpat. Donec accumsan et nunc vulputate accumsan. Vestibulum
    tempor, erat in mattis fringilla, elit urna ornare nunc, vel pretium elit sem quis orci. Vivamus condimentum dictum tempor. Nam at est ante. Sed lobortis et lorem in sagittis. In suscipit in est et vehicula.</p>
</div>

Matthew Wilcoxson suggested implementation using .content::before to avoid a second div: https://codepen.io/akademy/pen/FlkzB

Upvotes: 599

quwuwuza
quwuwuza

Reputation: 394

This answer is for a Material Design horizontal card layout with dynamic height and an image.

To prevent distortion of the image due to the dynamic height of the card, you could use a background placeholder image with blur to adjust for changes in height.

 

Explanation

  • The card is contained in a <div> with class wrapper, which is a flexbox.
  • The card is made up of two elements, an image which is also a link, and content.
  • The link <a>, class link, is positioned relative.
  • The link consists of two sub-elements, a placeholder <div> class blur and an <img> class pic which is the clear image.
  • Both are positioned absolute and have width: 100%, but class pic has a higher stack order, i.e., z-index: 2, which places it above the placeholder.
  • The background image for the blurred placeholder is set via inline style in the HTML.

 

Code

.wrapper {
  display: flex;
  width: 100%;
  border: 1px solid rgba(0, 0, 0, 0.16);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.16), 0 1px 1px rgba(0, 0, 0, 0.23);
  background-color: #fff;
  margin: 1rem auto;
  height: auto;
}

.wrapper:hover {
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}

.link {
  display: block;
  width: 200px;
  height: auto;
  overflow: hidden;
  position: relative;
  border-right: 2px solid #ddd;
}

.blur {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  width: 100%;
  height: 100%;
  filter: blur(5px);
  -webkit-filter: blur(5px);
  -moz-filter: blur(5px);
  -o-filter: blur(5px);
  -ms-filter: blur(5px);
}

.pic {
  width: calc(100% - 20px);
  max-width: 100%;
  height: auto;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
}

.pic:hover {
  transition: all 0.2s ease-out;
  transform: scale(1.1);
  text-decoration: none;
  border: none;
}

.content {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 100%;
  padding: 20px;
  overflow-x: hidden;
}

.text {
  margin: 0;
}
<div class="wrapper">
  <a href="#" class="link">
    <div class="blur" style="background: url('https://i.imgur.com/5SZI6qZ.jpeg') 50% 50% / cover;"></div>
    <img src="https://i.imgur.com/5SZI6qZ.jpeg" alt="Title" class="pic" />
  </a>

  <div class="content">
    <p class="text">Agendum dicendo memores du gi ad. Perciperem occasionem ei ac im ac designabam. Ista rom sibi vul apud tam. Notaverim to extendere expendere concilium ab. Aliae cogor tales fas modus parum sap nullo. Voluntate ingressus infirmari ex mentemque ac manifeste
      eo. Ac gnum ei utor sive se. Nec curant contra seriem amisit res gaudet adsunt. </p>
  </div>
</div>

Upvotes: 0

Sumitava Das
Sumitava Das

Reputation: 91

Please check the below code:-

.backgroundImageCVR{
    position:relative;
    padding:15px;
}
.background-image{
    position:absolute;
    left:0;
    right:0;
    top:0;
    bottom:0;
    background:url('https://i.imgur.com/5SZI6qZ.jpeg');
    background-size:cover;
    z-index:1;
    -webkit-filter: blur(10px);
  -moz-filter: blur(10px);
  -o-filter: blur(10px);
  -ms-filter: blur(10px);
  filter: blur(10px);   
}
.content{
    position:relative;
    z-index:2;
    color:#fff;
}
<div class="backgroundImageCVR">
    <div class="background-image"></div>
    <div class="content">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquam erat in ante malesuada, facilisis semper nulla semper. Phasellus sapien neque, faucibus in malesuada quis, lacinia et libero. Sed sed turpis tellus. Etiam ac aliquam tortor, eleifend rhoncus metus. Ut turpis massa, sollicitudin sit amet molestie a, posuere sit amet nisl. Mauris tincidunt cursus posuere. Nam commodo libero quis lacus sodales, nec feugiat ante posuere. Donec pulvinar auctor commodo. Donec egestas diam ut mi adipiscing, quis lacinia mauris condimentum. Quisque quis odio venenatis, venenatis nisi a, vehicula ipsum. Etiam at nisl eu felis vulputate porta.</p>
      <p>Fusce ut placerat eros. Aliquam consequat in augue sed convallis. Donec orci urna, tincidunt vel dui at, elementum semper dolor. Donec tincidunt risus sed magna dictum, quis luctus metus volutpat. Donec accumsan et nunc vulputate accumsan. Vestibulum tempor, erat in mattis fringilla, elit urna ornare nunc, vel pretium elit sem quis orci. Vivamus condimentum dictum tempor. Nam at est ante. Sed lobortis et lorem in sagittis. In suscipit in est et vehicula.</p>
    </div>
</div>

Upvotes: 9

Temani Afif
Temani Afif

Reputation: 272880

The Specification introduced a new filter() function that you can use with background images like below:

background: filter(url("whatever.jpg"), blur(5px));

The <filter()> function takes two arguments. The first argument is an <image>. The second is a filter function list as specified for the CSS filter property. The function takes the parameter and applies the filter rules, returning a processing image.

But there is no browser support for this: https://caniuse.com/css-filter-function. You can only test on Safari for now.

Upvotes: 4

user18009835
user18009835

Reputation: 1

<!-- Q:Create the blur on parenttal div without effecting the child div -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    *{
        margin: 0; padding: 0; box-sizing: border-box;
        font-size: 30px;
    }
    .parent{
background-image:url(hobby.jpg) ;
height: 100vh;
width: 100vw;
background-repeat: no-repeat;
background-size: cover;
background-position: center;

display: flex;
justify-content: center;
align-items: center;
    }
    .child{
   
    height: 90vh;
    width: 90vw;
    backdrop-filter: blur(10px);
    border: 1px solid rgba(0, 0, 0, 0.418);
  justify-content: center;
  align-items: center;
    display: flex;
    
 
    }
  .text{
    
      height: 300px;
      width: 300px;
      border-radius: 500px;
      background-image: url(50cf380e5c78eb174faa8e6ac2cb654a.jpg);
      background-size: cover;
      background-position: center;
      

  }
    
    
</style>
<body>
    <div class="parent">
        <div class="child">
       <div class="text"></div>
        </div>
    </div>
</body>
</html>

Upvotes: 0

Jyesht Pratham
Jyesht Pratham

Reputation: 1

Steps to successfully apply the background image

  1. ensure you've correctly linked your html and css using the link tag <link rel="stylesheet" ref="yourcssdocument.css">

  2. I have no idea about relative and sub directories so I can't comment on it

  3. The best method that worked for me is when I used a URL link in css

#yourcssdoc .image {
   background-image: url("paste your link here with the quotations")
}

Upvotes: -4

posit labs
posit labs

Reputation: 9431

You need to re-structure your HTML in order to do this. You have to blur the whole element in order to blur the background. So if you want to blur only the background, it has to be its own element.

Upvotes: 28

s1n7ax
s1n7ax

Reputation: 3069

CSS grid is easier for me to understand. :)

html, body {
  width: 100%;
  height: 100%;
}

.container {
  width: 100%;
  height: 100%;
  
  display: grid;
  grid-template-columns: 1fr 6fr 1fr;
  grid-template-rows: 1fr 6fr 1fr;
  grid-template-areas: 
  '. . .'
  '. content .'
  '. . .'; 
  justify-content: center;
  align-items: center;
}

.backbround {
  width: 100%;
  height: 100%;
  
  grid-area: 1/1/5/5;
  
  background-image: url(https://i.imgur.com/aUhpEz3.jpg);
  filter: blur(5px);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.content {
  height: 200px;
  position: relative;
  
  grid-area: content;
  display: flex;
  
  justify-content: center;
  align-items: center;
  color: white;
}
<div class="container">
  <div class="backbround"></div>
  <div class="content"><h1>Hello World</h1></div>
</div>

Upvotes: 1

pat
pat

Reputation: 68

You can create a div over the image you want to apply the filter and use backdrop-filter to its CSS class. Check out this link

Upvotes: -1

code builders
code builders

Reputation: 159

Without using the pseudo-class from

body{
    background:#cecece;
    font-family: "Scope One", serif;
    font-size: 12px;
    color:black;
    margin:0 auto;
    height:100%;
    width:100%;
    background-image: 
       linear-gradient(to bottom, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.81)), 
        url(https://i.imgur.com/2rRMQh7.jpg);
       -webkit-background-size: cover;
        -moz-background-size: cover;
        -o-background-size: cover;
        background-size: cover; 
}
<body></body>

Upvotes: -1

Carlos Boyzo
Carlos Boyzo

Reputation: 1

$fondo: url(/grid/assets/img/backimage.png);    
{ padding: 0; margin: 0; } 
body { 
    ::before{
        content:"" ; height: 1008px; width: 100%; display: flex; position: absolute; 
        background-image: $fondo ; background-repeat: no-repeat ; background-position: 
        center; background-size: cover; filter: blur(1.6rem);
    }
}

Upvotes: 0

Eljeddi Oussema
Eljeddi Oussema

Reputation: 133

Now this become even simpler and more flexible by using CSS GRID.You just have to overlap the blured background(imgbg) with the text(h2)

<div class="container">
 <div class="imgbg"></div>
 <h2>
  Lorem ipsum dolor sit amet consectetur, adipisicing elit. Facilis enim
  aut rerum mollitia quas voluptas delectus facere magni cum unde?:)
 </h2>
</div>

and the css:

.container {
        display: grid;
        width: 30em;
      }

.imgbg {
        background: url(bg3.jpg) no-repeat center;
        background-size: cover;
        grid-column: 1/-1;
        grid-row: 1/-1;
        filter: blur(4px);
      }


     .container h2 {
        text-transform: uppercase;
        grid-column: 1/-1;
        grid-row: 1/-1;
        z-index: 2;
      }

Upvotes: 1

user7226407
user7226407

Reputation: 1

If you want to content to be scrollable, set the position of the content to absolute:

content {
   position: absolute;
   ...
}

I don't know if this was just for me, but if not that's the fix!

Also since the background is fixed, it means you have a "parallax" effect! So now, not only did this person teach you how to make a blurry background, but it is also a parallax background effect!

Upvotes: -6

prajeesh loremine
prajeesh loremine

Reputation: 37

div {
    background: inherit;
    width: 250px;
    height: 350px;
    position: absolute;
    overflow: hidden;  /* Adding overflow hidden */
}

div:before {
    content: ‘’;
    width: 300px;
    height: 400px;
    background: inherit;
    position: absolute;
    left: -25px;  /* Giving minus -25px left position */
    right: 0;
    top: -25px;   /* Giving minus -25px top position */
    bottom: 0;
    box-shadow: inset 0 0 0 200px rgba(255, 255, 255, 0.3);
    filter: blur(10px);
}

Upvotes: -2

a99
a99

Reputation: 301

The following is a simple solution for modern browsers in pure CSS with a 'before' pseudo element, like the solution from Matthew Wilcoxson.

To avoid the need of accessing the pseudo element for changing the image and other attributes in JavaScript, simply use inherit as the value and access them via the parent element (here body).

body::before {
    content: ""; /* Important */
    z-index: -1; /* Important */
    position: inherit;
    left: inherit;
    top: inherit;
    width: inherit;
    height: inherit;
    background-image: inherit;
    background-size: cover;
    filter: blur(8px);
}

body {
  background-image: url("xyz.jpg");
  background-size: 0 0;  /* Image should not be drawn here */
  width: 100%;
  height: 100%;
  position: fixed; /* Or absolute for scrollable backgrounds */
}

Upvotes: 10

Max Tusken
Max Tusken

Reputation: 29

Of course, this is not a CSS-solution, but you can use the CDN Proton with filter:

body {
    background: url('https://i0.wp.com/IMAGEURL?w=600&filter=blurgaussian&smooth=1');
}

It is from https://developer.wordpress.com/docs/photon/api/#filter

Upvotes: 1

codeWithMe
codeWithMe

Reputation: 892

All you actually need is "filter":

blur(«WhatEverYouWantInPixels»);"

body {
    color: #fff;
    font-family: Helvetica, Arial, sans-serif;
}

#background {
    background-image: url('https://cdn2.geckoandfly.com/wp-content/uploads/2018/03/ios-11-3840x2160-4k-5k-beach-ocean-13655.jpg');
    background-repeat: no-repeat;
    background-size: cover;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;

    /* START */
    /* START */
    /* START */
    /* START */

    /* You can adjust the blur-radius as you'd like */
    filter: blur(3px);
}
<div id="background"></div>

<p id="randomContent">Lorem Ipsum</p>

Upvotes: 1

Jonathan
Jonathan

Reputation: 7098

I didn't write this, but I noticed there was a polyfill for the partially supported backdrop-filter using the CSS SASS compiler, so if you have a compilation pipeline it can be achieved nicely (it also uses TypeScript):

https://codepen.io/mixal_bl4/pen/EwPMWo

Upvotes: -1

SharpC
SharpC

Reputation: 7454

Although all the solutions mentioned are very clever, all seemed to have minor issues or potential knock on effects with other elements on the page when I tried them.

In the end to save time I simply went back to my old solution: I used Paint.NET and went to Effects, Gaussian Blur with a radius 5 to 10 pixels and just saved that as the page image. :-)

HTML:

<body class="mainbody">
</body

CSS:

body.mainbody
{
    background: url('../images/myphoto.blurred.png');
    -moz-background-size: cover;
    -webkit-background-size: cover;
    background-size: cover;
    background-position: top center !important;
    background-repeat: no-repeat !important;
    background-attachment: fixed;
}

EDIT:

I finally got it working, but the solution is by no means straightforward! See here:

Upvotes: 1

saikat
saikat

Reputation: 167

In the .content tab in CSS change it to position:absolute. Otherwise, the page rendered won't be scrollable.

Upvotes: 3

Related Questions