Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS blur and retain sharp edges using absolute div

Tags:

html

css

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?

like image 202
jskidd3 Avatar asked Dec 07 '13 15:12

jskidd3


People also ask

How do you blur the edge of a div in CSS?

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.

Can you blur a div?

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.

Which CSS property can be used with Blur 10px to blur an image?

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.


3 Answers

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

like image 83
Mohsen Safari Avatar answered Oct 08 '22 19:10

Mohsen Safari


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>
like image 37
nmu Avatar answered Oct 08 '22 20:10

nmu


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.

like image 32
Fredrik Avatar answered Oct 08 '22 20:10

Fredrik