Como posso fazer um efeito de vidro / desfoque CSS funcionar para uma sobreposição?

102

Estou tendo problemas para aplicar um efeito de desfoque em uma div de sobreposição semitransparente. Eu gostaria que tudo atrás do div fosse desfocado, assim:

Imagem SFW

Aqui está um jsfiddle que não funciona: http://jsfiddle.net/u2y2091z/

Alguma ideia de como fazer isso funcionar? Eu gostaria de manter isso o mais simples possível e para vários navegadores. Aqui está o CSS que estou usando:

#overlay {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;

    background:black;
    background:rgba(0,0,0,0.8);

    filter:blur(4px);
    -o-filter:blur(4px);
    -ms-filter:blur(4px);
    -moz-filter:blur(4px);
    -webkit-filter:blur(4px);
}
Chad Johnson
fonte
1
Para sua informação - CSS filternão é compatível com Firefox, você não deveria usá-lo.
Weafs.py de
2
Talvez torne o div opaco, mas use um pseudoelemento com a imagem como fundo que pode ser desfocado de forma independente.
bjb568
1
@ chipChocolate.py Os filtros CSS são suportados no FF35 + por padrão. Mas concordo com você, nós, como desenvolvedores, não devemos confiar nele, pois não é um recurso para vários navegadores.
Hashem Qolami

Respostas:

71

Aqui está um exemplo que usa svgfiltro.

A ideia é usar um svgelemento com o heightmesmo que o #overlaye aplicar o feGaussianblurfiltro nele. Este filtro é aplicado em um svg imageelemento. Para dar um efeito de extrusão, você pode usar um box-shadowna parte inferior da sobreposição.

Suporte do navegador para svgfiltros .

Demo on Codepen

body {
  background: #222222;
}
#container {
  position: relative;
  width: 450px;
  margin: 0 auto;
}
img {
  height: 300px;
}
#overlay {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 1;
  color: rgba(130, 130, 130, 0.5);
  font-size: 50px;
  text-align: center;
  line-height: 100px;
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
}
<div id="container">
  <img src="http://lorempixel.com/450/300/sports" />
  <div id="overlay">WET</div>
  <svg width="450" height="100" viewBox="0 0 450 100" style="position: absolute; top: 0;">
    <defs>
      <filter id="blur">
        <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
      </filter>
    </defs>
    <image filter="url(#blur)" xlink:href="http://lorempixel.com/450/300/sports" x="0" y="0" height="300px" width="450px" />
  </svg>
</div>

Weafs.py
fonte
70

Para uma resposta mais simples e atualizada:

backdrop-filter: blur(6px);

Observe que o suporte do navegador não é perfeito, mas na maioria dos casos um desfoque não é essencial.

Jon Catmull
fonte
1
Esta é de longe a melhor resposta.
Tanner Burton
51

Consegui reunir informações de todos aqui e de mais pesquisas no Google e encontrei o seguinte, que funciona no Chrome e no Firefox: http://jsfiddle.net/xtbmpcsu/ . Ainda estou trabalhando para que isso funcione no IE e no Opera.

A chave é colocar o conteúdo dentro do div ao qual o filtro é aplicado:

<div id="mask">
    <p>Lorem ipsum ...</p>
    <img src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

E então o CSS:

body {
    background: #300000;
    background: linear-gradient(45deg, #300000, #000000, #300000, #000000);
    color: white;
}
#mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.5;
}
img {
    filter: blur(10px);
    -webkit-filter: blur(10px);
    -moz-filter: blur(10px);
    -o-filter: blur(10px);
    -ms-filter: blur(10px);
    position: absolute;
    left: 100px;
    top: 100px;
    height: 300px;
    width: auto;
}

Portanto, a máscara tem os filtros aplicados. Além disso, observe o uso de url () para um filtro com uma <svg>tag para o valor - essa ideia veio de http://codepen.io/AmeliaBR/pen/xGuBr . Se acontecer de você reduzir seu CSS, pode ser necessário substituir todos os espaços na marcação do filtro SVG por "% 20".

Agora, tudo dentro da máscara div está desfocado.

Chad Johnson
fonte
é tão inteligente
Gangsar Swapurba,
3
O Chrome não gosta do final filter: url(.... Remova isso e o Chrome o usará com sucesso filter: blur(10px);.
Doug S,
2
Eu entendi mal? Não é o que o OP deseja. Os textos não devem ser desfocados.
Eric
2
@Eric, você claramente entendeu mal, já que quem responde é o OP.
tao
10

Se você está procurando uma abordagem confiável para vários navegadores hoje , não encontrará uma ótima. A melhor opção que você tem é criar duas imagens (isso pode ser automatizado em alguns ambientes) e organizá-las de forma que uma se sobreponha à outra. Criei um exemplo simples abaixo:

<figure class="js">
    <img src="http://i.imgur.com/3oenmve.png" />
    <img src="http://i.imgur.com/3oenmve.png?1" class="blur" />
</figure>
figure.js {
    position: relative;
    width: 250px; height: 250px;
}

figure.js .blur {
    top: 0; left: 0;
    position: absolute;
    clip: rect( 0, 250px, 125px, 0 );
}

Embora eficaz, mesmo essa abordagem não é necessariamente ideal. Dito isso, ele produz o resultado desejado .

insira a descrição da imagem aqui

Sampson
fonte
8

Aqui está uma solução possível.

HTML

<img id="source" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />

<div id="crop">
    <img id="overlay" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

CSS

#crop {
    overflow: hidden;

    position: absolute;
    left: 100px;
    top: 100px;

    width: 450px;
    height: 150px;
}

#overlay {
    -webkit-filter:blur(4px);
    filter:blur(4px);

    width: 450px;
}

#source {
    height: 300px;
    width: auto;
    position: absolute;
    left: 100px;
    top: 100px;
}

Eu sei que o CSS pode ser simplificado e você provavelmente deve se livrar dos ids. A ideia aqui é usar um div como contêiner de recorte e, em seguida, aplicar desfoque na duplicata da imagem. Violino

Para fazer isso funcionar no Firefox, você teria que usar o hack SVG .

Juho Vepsäläinen
fonte
@ chipChocolate.py Acho que você precisa usar o hack SVG nesse caso, demosthenes.info/blog/534/Crossbrowser-Image-Blur .
Juho Vepsäläinen
Observe que, para o filtro CSS, você pode omitir os prefixos do fornecedor, exceto -webkit-porque não está implementado nesses navegadores. É melhor colocar a declaração padrão no final - depois de todas as versões prefixadas.
Hashem Qolami
@HashemQolami Concluído. Obrigado.
Juho Vepsäläinen
FF está OK, agora (54.0.1 (32 bits)). Simplesmente perfeito! Tx!
Pedro Ferreira
6
background: rgba(255,255,255,0.5);
backdrop-filter: blur(5px);

Em vez de adicionar outro fundo desfocado ao seu conteúdo, você pode usar o filtro de fundo . FYI IE 11 e Firefox podem não suportá-lo. Verifique caniuse .

Demo:

header {
  position: fixed;
  width: 100%;
  padding: 10px;
  background: rgba(255,255,255,0.5);
  backdrop-filter: blur(5px);
}
body {
  margin: 0;
}
<header>
  Header
</header>
<div>
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
</div>

Allen Wong
fonte
A mesma solução já foi proposta: stackoverflow.com/a/58083568/3702797
Kaiido
4

#bg, #search-bg {
  background-image: url('https://images.pexels.com/photos/719609/pexels-photo-719609.jpeg?w=940&h=650&auto=compress&cs=tinysrgb');
  background-repeat: no-repeat;
  background-size: 1080px auto;
}

#bg {
  background-position: center top;
  padding: 70px 90px 120px 90px;
}

#search-container {
  position: relative;
}

#search-bg {
  /* Absolutely position it, but stretch it to all four corners, then put it just behind #search's z-index */
  position: absolute;
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  z-index: 99;

  /* Pull the background 70px higher to the same place as #bg's */
  background-position: center -70px;

  -webkit-filter: blur(10px);
  filter: url('/media/blur.svg#blur');
  filter: blur(10px);
}

#search {
  /* Put this on top of the blurred layer */
  position: relative;
  z-index: 100;
  padding: 20px;
  background: rgb(34,34,34); /* for IE */
  background: rgba(34,34,34,0.75);
}

@media (max-width: 600px ) {
  #bg { padding: 10px; }
  #search-bg { background-position: center -10px; }
}

#search h2, #search h5, #search h5 a { text-align: center; color: #fefefe; font-weight: normal; }
#search h2 { margin-bottom: 50px }
#search h5 { margin-top: 70px }
<div id="bg">
  <div id="search-container">
    <div id="search-bg"></div>
    <div id="search">
      <h2>Awesome</h2>
      <h5><a href="#">How it works »</a></h5>
    </div>
  </div>
</div>

Prajeesh Loremine
fonte
1

Eu vim com esta solução.

Clique para ver a imagem do efeito desfocado

É uma espécie de truque que usa um filho posicionado absolutamente div, define sua imagem de fundo igual à do pai dive então usa a background-attachment:fixedpropriedade CSS junto com as mesmas backgroundpropriedades definidas no elemento pai.

Em seguida, você aplica filter:blur(10px)(ou qualquer valor) no div filho.

*{
    margin:0;
    padding:0;
    box-sizing: border-box;
}
.background{
    position: relative;
    width:100%;
    height:100vh;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-size:cover;
    background-position: center;
    background-repeat:no-repeat;
}

.blur{
    position: absolute;
    top:0;
    left:0;
    width:50%;
    height:100%;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-position: center;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-size:cover;
    filter:blur(10px);
    transition:filter .5s ease;
    backface-visibility: hidden;
}

.background:hover .blur{
    filter:blur(0);
}
.text{
    display: inline-block;
    font-family: sans-serif;
    color:white;
    font-weight: 600;
    text-align: center;
    position: relative;
    left:25%;
    top:50%;
    transform:translate(-50%,-50%);
}
<head>
    <title>Blurry Effect</title>
</head>
<body>
    <div class="background">
        <div class="blur"></div>
        <h1 class="text">This is the <br>blurry side</h1>
    </div>
</body>
</html>

ver no codepen

CptGeo
fonte
0

Esta é uma solução que funciona com fundos fixos. Se você tiver um fundo fixo e alguns elementos sobrepostos e precisar de fundos borrados para eles, esta solução funciona:

Imagem temos este HTML simples:

<body> <!-- or any wrapper -->
   <div class="content">Some Texts</div>
</body>

Um plano de fundo fixo para <body>ou o elemento wrapper:

body {
  background-image: url(http://placeimg.com/640/360/any);
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

E aqui, por exemplo, temos um elemento sobreposto com um fundo branco transparente:

.content {
  background-color: rgba(255, 255, 255, 0.3);
  position: relative;
}

Agora precisamos usar exatamente a mesma imagem de fundo de nosso wrapper para nossos elementos de sobreposição também, eu a uso como uma :beforeclasse psuedo:

.content:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  filter: blur(5px);
  background-image: url(http://placeimg.com/640/360/any);
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

Como o plano de fundo fixo funciona da mesma maneira nos elementos wrapper e sobrepostos, temos o plano de fundo exatamente na mesma posição de rolagem do elemento sobreposto e podemos simplesmente desfocá-lo. Aqui está um violino que funciona, testado no Firefox, Chrome, Opera e Edge: https://jsfiddle.net/0vL2rc4d/

NOTA: No firefox há um bug que faz a tela piscar ao rolar e há fundos borrados corrigidos. se houver alguma correção, me avise

Amin
fonte
0

Isso fará com que o desfoque se sobreponha ao conteúdo:

.blur{
 display:block;
 bottom: 0;
 left: 0;
 position: fixed;
 right: 0;
 top: 0;
 -webkit-backdrop-filter: blur(15px);
 backdrop-filter: blur(15px);
 background-color: rgba(0, 0, 0, .5);
}
Magnettoo
fonte