Размытие CSS и сохранение острых краев с использованием абсолютного div

Это работает отлично, если img не установлен в абсолютный:

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;
}

Пример работы отлично: http://jsfiddle.net/ThinkingStiff/b8fLU/ (взято из другого вопроса)

Но что, если я хочу сделать это с помощью абсолютного div с использованием фонового изображения?

<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;
}

Как я могу достичь такого же эффекта (размытие, но с острыми краями), используя настройку выше?

Ответ 1

поместите свой элемент размытия в контейнер следующим образом:

<div class="container">
    <div id="background"></div>
</div>

то вместо использования height:100% и width:100% используйте следующее:

.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 */
}

вам нужно удалить 15px (или больше/меньше) с каждой стороны вашего элемента.

DEMO - Полный DEMO

Ответ 2

Я заметил, что на мобильных устройствах размытие иногда отменяет overflow:hidden. Это можно устранить, добавив в контейнер border: 1px solid transparent;.

Ответ 3

Альтернативой ответам, которые я видел для этого, я думаю, действительно умный, использует svg, чтобы размыть img. Это очень хорошо описано в этом кодепе https://codepen.io/johndjameson/full/xVjgPy/, поэтому я просто скопирую и вставьте это здесь. Надеюсь, он будет гораздо более доступным в этой теме.

Подводя итог. Вы делаете невидимый элемент svg следующим образом

 <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>

И затем используйте CSS для размытия путем ссылки на невидимый элемент svg

.svgBlur { filter: url("#sharpBlur"); }

Наконец, вы просто добавляете svgBlur в img, который хотите размыть

<img class='svgBlur' src='https://unsplash.it/360/240?image=511'>

И это! Работала очень хорошо для меня.

.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>