This works just fine if img is not set to absolute:
div img {
filter: blur(5px);
-webkit-filter: blur(5px);
-moz-filter: blur(5px);
-o-filter: blur(5px);
-ms-filter: blur(5px);
margin: -5px -10px -10px -5px;
}
div {
margin: 20px;
overflow: hidden;
}
Example working fine: http://jsfiddle.net/ThinkingStiff/b8fLU/ (taken from another question)
But what if I want to do this with an absolute div using background-image?
<div id="background"></div>
#background {
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 100%;
width: 100%;
filter: blur(5px) brightness(0.75);
-webkit-filter: blur(5px) brightness(0.75);
-moz-filter: blur(5px) brightness(0.75);
-ms-filter: blur(5px) brightness(0.75);
-o-filter: blur(5px) brightness(0.75);
position: absolute;
background-image: url('images/bg.png');
z-index: 1;
}
How can I achieve the same effect (blur but with sharp edges) using the setup above?
Blurring the edges of a photo in CSS is pretty straightforward, with one gotcha. To blur a photo we need to use box-shadow in a way where the shadow "eats" the image. For this effect to work, the blur must be the same color as the surrounding background, and inset must be used.
Blurring the background elements of a div can be achieved using backdrop-filter . All the elements placed under the div are going be blurred by using this.
The blur function applies a blur effect to a specified input image, which you can then use with the “filter” property to blur an image.
put your blur element in a container like this:
<div class="container">
<div id="background"></div>
</div>
then instead of using height:100%
and width:100%
use like this:
.container{
position:relative;
width:300px; /* this is an example */
height:300px; /* this is an example */
overflow:hidden;
}
#background {
left:-15px;
right:-15px;
top:-15px;
bottom:-15px;
/* other styles */
}
you need to remove 15px
(or more/less) from each side of your element.
DEMO - Full DEMO
An alternative to the answers I've been seeing for this, that I think is really clever, is using an svg to blur the img
. It's described really well in this codepen https://codepen.io/johndjameson/full/xVjgPy/ so I'll just copy and paste that over here. Hopefully it'll be much more accessible on this thread.
To sum it up. You make an invisible svg element like this
<svg class='hideSvgSoThatItSupportsFirefox'>
<filter id='sharpBlur'>
<feGaussianBlur stdDeviation='3'></feGaussianBlur>
<feColorMatrix type='matrix' values='1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 9 0'></feColorMatrix>
<feComposite in2='SourceGraphic' operator='in'></feComposite>
</filter>
</svg>
And then use CSS to blur by linking to the invisible svg element
.svgBlur { filter: url("#sharpBlur"); }
Finally you just add svgBlur
to the img
you want blurred
<img class='svgBlur' src='https://unsplash.it/360/240?image=511'>
And that's it! Worked really well for me.
.cssBlur {
-webkit-filter: blur(3px);
filter: blur(3px);
}
.svgBlur {
-webkit-filter: url("#sharpBlur");
filter: url("#sharpBlur");
}
.hideSvgSoThatItSupportsFirefox {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
*,
::before,
::after {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
padding: 40px;
line-height: 1.4;
margin-left: auto;
margin-right: auto;
max-width: 840px;
}
svg {
width: 0;
height: 0;
overflow: hidden;
visibility: hidden;
}
img {
height: auto;
max-width: 100%;
vertical-align: middle;
}
h1,
h2,
h3,
h4,
h5,
h6,
p,
pre {
margin-top: 0;
margin-bottom: 0;
}
h1,
h2,
h3 {
line-height: 1.2;
}
h1 {
margin-bottom: 40px;
}
h2 {
margin-bottom: 20px;
}
p {
margin-bottom: 20px;
}
pre {
margin-bottom: 20px;
overflow: auto;
}
.emoji {
font-size: 40px;
line-height: 1;
}
.grid {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
margin-left: -40px;
}
.grid-box {
padding-left: 40px;
width: 100%;
}
@media screen and (min-width: 600px) {
.grid-box--1of2 {
width: 50%;
}
}
.mbf {
margin-bottom: 0;
}
.mbm {
margin-bottom: 40px;
}
.mbs {
margin-bottom: 20px;
}
@media screen and (min-width: 600px) {
.mbf_m {
margin-bottom: 0;
}
.mbm_m {
margin-bottom: 40px;
}
}
<svg class='hideSvgSoThatItSupportsFirefox'>
<filter id='sharpBlur'>
<feGaussianBlur stdDeviation='3'></feGaussianBlur>
<feColorMatrix type='matrix' values='1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 9 0'></feColorMatrix>
<feComposite in2='SourceGraphic' operator='in'></feComposite>
</filter>
</svg>
<h1>Blurred Image with Sharp Edges</h1>
<div class='grid mbm_m'>
<div class='grid-box grid-box--1of2 mbs mbf_m'>
<img class='mbf' src='https://unsplash.it/360/240?image=511'>
</div>
<div class='grid-box grid-box--1of2 mbm mbf_m'>
<h2>Original image</h2>
<p>
Let’s blur this image in the browser. There are two types of filters we can use: CSS and SVG.
</p>
<p>If you want to keep the orginal’s sharp edges, you’re going to need SVG.</p>
<p class='emoji mbf'>😉</p>
</div>
</div>
<div class='grid mbm'>
<div class='grid-box grid-box--1of2 mbm mbf_m'>
<img class='cssBlur mbs' src='https://unsplash.it/360/240?image=511'>
<h2>Blurred with CSS</h2>
<pre>filter: blur(3px)</pre>
<p class='mbf'>
The syntax in CSS is super simple, but this’ll fuzz up the edges around the image.
</p>
</div>
<div class='grid-box grid-box--1of2'>
<img class='svgBlur mbs' src='https://unsplash.it/360/240?image=511'>
<h2>Blurred with SVG</h2>
<pre>filter: blur('#sharpBlur')</pre>
<p class='mbf'>
Here you reference a filter’s <code>id</code> from the SVG. See the difference? This one looks so clean!
</p>
</div>
</div>
I've noticed on mobile devices the blur sometimes will override the overflow:hidden
. This can be fixed by adding a border: 1px solid transparent;
to the container.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With