Transição de imagem de fundo CSS3

121

Estou tentando fazer um efeito "fade-in fade-out" usando a transição CSS. Mas não consigo fazer isso funcionar com a imagem de fundo ...

O CSS:

.title a {
    display: block;
    width: 340px;
    height: 338px;
    color: black;
    background: transparent;
    /* TRANSITION */
    -webkit-transition: background 1s;
    -moz-transition: background 1s;
    -o-transition: background 1s;
    transition: background 1s;
}

.title a:hover {
    background: transparent;
    background: url(https://lh3.googleusercontent.com/-p1nr1fkWKUo/T0zUp5CLO3I/AAAAAAAAAWg/jDiQ0cUBuKA/s800/red-pattern.png) repeat;
    /* TRANSITION */
    -webkit-transition: background 1s;
    -moz-transition: background 1s;
    -o-transition: background 1s;
    transition: background 1s;
}​

Dê uma olhada: http://jsfiddle.net/AK3La/

Nick Zani
fonte

Respostas:

104

Você pode fazer a transição background-image. Use o CSS abaixo no imgelemento:

-webkit-transition: background-image 0.2s ease-in-out;
transition: background-image 0.2s ease-in-out;

Isso é suportado nativamente pelo Chrome, Opera e Safari. O Firefox ainda não o implementou ( bugzil.la ). Não tenho certeza sobre o IE.

Hengjie
fonte
105
background-imagenão é uma propriedade animável ( w3.org/TR/css3-transitions/#animatable-properties ), portanto, sua solução não é compatível com o padrão.
TLindig de
12
Isso não é uma solução - FF e IE não oferecem suporte, e como observado acima, não é uma propriedade que a especificação diz que deve ser compatível.
Sentinel de
Veja também para o desenvolvimento atual no Fx: bugzilla.mozilla.org/show_bug.cgi?id=546052
Volker E.
2
@TLindig Deve ser uma propriedade animável.
3
A propriedade animatable é background, e é isso que deve ser usado (funciona no Chrome para mim). Talvez a especificação (ou impl) tenha mudado desde que a pergunta foi postada
fps
37

A solução (que encontrei por mim mesmo) é um truque ninja, posso oferecer-lhe duas maneiras:

primeiro você precisa fazer um "contêiner" para o <img>, ele conterá os estados normal e de foco ao mesmo tempo:

<div class="images-container">
    <img src="http://lorempixel.com/400/200/animals/9/">
    <img src="http://lorempixel.com/400/200/animals/10/">
</div>

Basicamente, você precisa ocultar o estado "normal" e mostrar seu "foco" quando você passa

e é isso, espero que alguém ache útil.

Ruffo
fonte
Ótima solução. Ao fazer experiências com a primeira amostra, percebi que, se você aumentar a duração da transição para 4s, poderá ver um salto muito perceptível quando o z-index muda no meio da transição. Pelo menos no Chrome 35, você pode mudar o tempo da chave do z-index e limpar a transição alterando o valor da propriedade para "all 4s facilmente, z-index 1ms" ( jsfiddle.net/eD2zL/330 ).
Neal Stublen
2
@NealS. você está certo. Esta resposta tem 2 anos, porém, eu removeria o Z-index, parece desnecessário. As imagens só precisam estar em ordem.
Ruffo
Muito obrigado. Sua solução é muito útil para mim.
Slam
É possível "carregamento lento" se eu usar essa solução?
Daniel
16

Eu descobri uma solução que funcionou para mim ...

Se você tiver um item de lista (ou div) contendo apenas o link, digamos que seja para links sociais em sua página do Facebook, Twitter, etc. e você está usando uma imagem de sprite, você pode fazer isso:

<li id="facebook"><a href="facebook.com"></a></li>

Faça do fundo "li" a sua imagem de botão

#facebook {
   width:30px;
   height:30px;
   background:url(images/social) no-repeat 0px 0px;
}

Em seguida, transforme a imagem de plano de fundo do link no estado de foco do botão. Adicione também o atributo opacity a isso e defina-o como 0.

#facebook a {
   display:inline-block;
   background:url(images/social) no-repeat 0px -30px;
   opacity:0;
}

Agora tudo que você precisa é "opacidade" em "a: hover" e defina como 1.

#facebook a:hover {
   opacity:1;
}

Adicione os atributos de transição de opacidade de cada navegador para "a" e "a: hover" para que o css final seja parecido com este:

#facebook {
   width:30px;
   height:30px;
   background:url(images/social) no-repeat 0px 0px;
}
#facebook a {
   display:inline-block;
   background:url(images/social) no-repeat 0px -30px;
   opacity:0;
   -webkit-transition: opacity 200ms linear;
   -moz-transition: opacity 200ms linear;
   -o-transition: opacity 200ms linear;
   -ms-transition: opacity 200ms linear;
   transition: opacity 200ms linear;
}
#facebook a:hover {
   opacity:1;
   -webkit-transition: opacity 200ms linear;
   -moz-transition: opacity 200ms linear;
   -o-transition: opacity 200ms linear;
   -ms-transition: opacity 200ms linear;
   transition: opacity 200ms linear;
}

Se eu expliquei corretamente, isso deve permitir que você tenha um botão de imagem de fundo esmaecido, espero que ajude pelo menos!

Austin Parrish Thomas
fonte
3
Eu também fiz uma versão em vídeo tutorial disso. youtube.com/watch?v=6ieR5ApVpr0
Austin Parrish Thomas
Você não deve, AFAIK, precisar especificar as transições na pseudoclasse de foco; a definição de transição para o tipo de tag âncora será transportada para o comportamento de foco, tudo o que você precisa alterar é a opacidade. Lembre-se de que este exemplo funciona bem porque os estilos são aplicados diretamente a IDs / tipos de tag; se você fizer isso com classes, certifique-se de não adicionar e remover a classe com a transição definida.
KeithS
15

Infelizmente, você não pode usar a transição background-image, consulte a lista w3c de propriedades animáveis .

Você pode querer fazer alguns truques com background-position.

Olwaro
fonte
13

Você pode usar o pseudoelemento para obter o efeito que deseja, como fiz naquele Fiddle .

CSS:

.title a {
    display: block;
    width: 340px;
    height: 338px;
    color: black;
    position: relative;
}
.title a:after {
    background: url(https://lh3.googleusercontent.com/-p1nr1fkWKUo/T0zUp5CLO3I/AAAAAAAAAWg/jDiQ0cUBuKA/s800/red-pattern.png) repeat;
    content: "";
    opacity: 0;
    width: inherit;
    height: inherit;
    position: absolute;
    top: 0;
    left: 0;
    /* TRANSISITION */
    transition: opacity 1s ease-in-out;
    -webkit-transition: opacity 1s ease-in-out;
    -moz-transition: opacity 1s ease-in-out;
    -o-transition: opacity 1s ease-in-out;
}
.title a:hover:after{   
    opacity: 1;
}

HTML:

<div class="title">
    <a href="#">HYPERLINK</a>
</div>
MaxCloutier
fonte
2
Isso funciona muito bem, mas você pode ter 2 problemas: 1) se você não vê o :afterelemento, tente definir widthe heightcomo em 100%vez de inherit, 2) se o background-imagefor realmente exibido em primeiro plano , use o índice negativo para o :afterelemento:z-index: -1;
Radek Pech
9

Se você pode usar jQuery, você pode tentar o plugin BgSwitcher para mudar a imagem de fundo com efeitos, é muito fácil de usar.

Por exemplo :

$('.bgSwitch').bgswitcher({
        images: ["style/img/bg0.jpg","style/img/bg1.jpg","style/img/bg2.jpg"],
        effect: "fade",
        interval: 10000
});

E adicione seu próprio efeito, consulte como adicionar tipos de efeito

MaxDhn
fonte
Obrigado, resolvi o problema com a animação da mudança de fundo da mesa com o uso deste plugin.
userlond
4

Tente fazer isso, fará com que o plano de fundo animado funcione na web, mas o aplicativo móvel híbrido não funciona

@-webkit-keyframes breath {
 0%   {  background-size: 110% auto; }
 50%  {  background-size: 140% auto; }
 100% {  background-size: 110% auto; }      
}
body {
   -webkit-animation: breath 15s linear infinite;
   background-image: url(images/login.png);
    background-size: cover;
}
Hesham Nasser
fonte
4

Considerando que as imagens de fundo não podem ser animadas, criei um pequeno mixin SCSS que permite a transição entre 2 imagens de fundo diferentes usando pseudo seletores antes e depois . Eles estão em diferentes camadas de índice z. O que está à frente começa com opacidade 0 e se torna visível com o cursor do mouse.

Você também pode usar a mesma abordagem para criar animações com gradientes lineares.

scss

@mixin bkg-img-transition( $bkg1, $bkg2, $transTime:0.5s ){  
  position: relative;  
  z-index: 100; 
  &:before, &:after {
    background-size: cover;  
    content: '';    
    display: block;
    height: 100%;
    position: absolute;
    top: 0; left: 0;    
    width: 100%;    
    transition: opacity $transTime;
  }
  &:before {    
    z-index: -101;
    background-image: url("#{$bkg1}");    
  }
  &:after {    
    z-index: -100;
    opacity: 0;
    background-image: url("#{$bkg2}");    
  }
  &:hover {
     &:after{
       opacity: 1; 
     }
  }  
}

Agora você pode simplesmente usá-lo com

@include bkg-img-transition("https://picsum.photos/300/300/?random","https://picsum.photos/g/300/300");

Você pode conferir aqui: https://jsfiddle.net/pablosgpacheco/01rmg0qL/

Pablo SG Pacheco
fonte
Solução muito boa! Me deu uma compreensão melhor de como fazer bom uso dos estados de elemento ': before' e ': after' como um bônus :-)
joronimo
3

Se a animação opacitynão for uma opção, você também pode animar background-size.

Por exemplo, usei este CSS para definir um backgound-imagecom um atraso.

.before {
  background-size: 0;
}

.after {
  transition: background 0.1s step-end;
  background-image: $path-to-image;
  background-size: 20px 20px;
}
shock_one
fonte
Se você quiser um efeito de fade-out de .afterem .beforepara a imagem de fundo, você deve definir a imagem de fundo para o .before. Caso contrário, ele simplesmente desaparecerá sem animação.
Radek Pech
2

Salam, esta resposta funciona apenas no Chrome, porque o IE e o FF suportam a transição de cores.

Não há necessidade de fazer seus elementos HTML opacity:0, pois algumas vezes eles contêm texto, e não há necessidade de dobrar seus elementos !.

A questão com link para um exemplo no jsfiddle precisava de uma pequena mudança, que é colocar uma imagem vazia .title acomo a background:url(link to an empty image);mesma que você colocou, .title a:hovermas torná-la uma imagem vazia, e o código funcionará.

.title a {
display: block;
width: 340px;
height: 338px;
color: black;
background: url(https://upload.wikimedia.org/wikipedia/commons/5/59/Empty.png) repeat;
/* TRANSISITION */
transition: background 1s;
-webkit-transition: background 1s;
-moz-transition: background 1s;
-o-transition: background 1s;
  }
  .title a:hover{   background: transparent;
   background: url(https://lh3.googleusercontent.com/-p1nr1fkWKUo/T0zUp5CLO3I/AAAAAAAAAWg/jDiQ0cUBuKA/s800/red-pattern.png) repeat;
/* TRANSISITION */
transition: background 1s;
-webkit-transition: background 1s;
-moz-transition: background 1s;
-o-transition: background 1s;
}

Confira https://jsfiddle.net/Tobasi/vv8q9hum/

Mohammed Suleiman
fonte
Ainda não está funcionando no Fire Fox ou IE :(, mas parece bem em cromo
mohammed Suleiman
1

Com a postagem inspiradora de Chris aqui:

https://css-tricks.com/different-transitions-for-hover-on-hover-off/

Eu consegui pensar nisso:

#banner
{
    display:block;
    width:100%;
    background-repeat:no-repeat;
    background-position:center bottom;
    background-image:url(../images/image1.jpg);
    /* HOVER OFF */
    @include transition(background-image 0.5s ease-in-out); 

    &:hover
    {
        background-image:url(../images/image2.jpg);
        /* HOVER ON */
        @include transition(background-image 0.5s ease-in-out); 
    }
}
Carol McKay
fonte
0

Isso pode ser alcançado com maior suporte para vários navegadores do que a resposta aceita usando pseudo-elementos, conforme exemplificado por esta resposta: https://stackoverflow.com/a/19818268/2602816

vaer-k
fonte
0

Eu estava lutando com isso por um tempo, primeiro usei uma pilha de imagens uma em cima da outra e, a cada três segundos, estava tentando animar para a próxima imagem na pilha e jogando a imagem atual para o final da pilha. Ao mesmo tempo, estava usando animações como mostrado acima. Eu não conseguia fazer isso funcionar pela minha vida.

Você pode usar esta biblioteca que permite ** imagem de fundo com capacidade de apresentação de slides com redimensionamento dinâmico ** usando jquery-backstretch.

https://github.com/jquery-backstretch/jquery-backstretch

Akhil Khanna
fonte