Animação CSS3: exibição + opacidade

101

Tenho um problema com uma animação CSS3.

.child {
    opacity: 0;
    display: none;

    -webkit-transition: opacity 0.5s ease-in-out;
    -moz-transition: opacity 0.5s ease-in-out;
    transition: opacity 0.5s ease-in-out;
}

.parent:hover .child {
    opacity: 0.9;
    display: block;
}

Este código só funciona se eu remover a alteração de display.

Desejo alterar a exibição logo após o foco, mas a opacidade deve ser alterada usando a transição.

Alexis Delrieu
fonte
2
Se CSS não funcionar como os outros sugeriram, aqui está um código Javascript muito simples para esmaecimento.
Abhranil Das

Respostas:

118

Com base na resposta de Michaels, este é o código CSS real a ser usado

.parent:hover .child
{
    display: block;

    -webkit-animation: fadeInFromNone 0.5s ease-out;
    -moz-animation: fadeInFromNone 0.5s ease-out;
    -o-animation: fadeInFromNone 0.5s ease-out;
    animation: fadeInFromNone 0.5s ease-out;
}

@-webkit-keyframes fadeInFromNone {
    0% {
        display: none;
        opacity: 0;
    }

    1% {
        display: block;
        opacity: 0;
    }

    100% {
        display: block;
        opacity: 1;
    }
}

@-moz-keyframes fadeInFromNone {
    0% {
        display: none;
        opacity: 0;
    }

    1% {
        display: block;
        opacity: 0;
    }

    100% {
        display: block;
        opacity: 1;
    }
}

@-o-keyframes fadeInFromNone {
    0% {
        display: none;
        opacity: 0;
    }

    1% {
        display: block;
        opacity: 0;
    }

    100% {
        display: block;
        opacity: 1;
    }
}

@keyframes fadeInFromNone {
    0% {
        display: none;
        opacity: 0;
    }

    1% {
        display: block;
        opacity: 0;
    }

    100% {
        display: block;
        opacity: 1;
    }
}
Chris
fonte
1
para suportar todos os navegadores ..?
david_adler
CSS3 não é compatível com todos os navegadores. Se você quiser estender, basta adicionar os prefixos corretos
Chris
17
E quando estiver pairando, como implementar fadeOutToNone?
Verde
4
Como você pode usar frações de uma porcentagem, é melhor prática usar algo como 0,001% em vez de 1%, porque isso minimiza o atraso para "iniciar", que pode se tornar aparente com durações de animação mais longas
Zach Saucier
1
A diretiva -o-keyframes é realmente inútil porque a primeira versão do Opera para suportar animações já era baseada no webkit.
Rico Ocepek
43

Você pode fazer com animações CSS:

0% display:none ; opacity: 0;
1% display: block ; opacity: 0;
100% display: block ; opacity: 1;
Michael Mullany
fonte
Boa ideia, consegui manter a exibição do meu elemento durante o foco com o modo de preenchimento de animação, mas depois que desloquei o mouse, o elemento desapareceu.
Alexis Delrieu
2
você pode usar fill-mode: forward para persistir as alterações após o término da animação.
Michael Mullany
42

Se possível - use em visibilityvez dedisplay

Por exemplo:

.child {
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.3s, visibility 0.3s;
}

.parent:hover .child {
    visibility: visible;
    opacity: 1;
    transition: opacity 0.3s, visibility 0.3s;
}
tomas.satinsky
fonte
24
O problema com a propriedade de visibilidade é que ela não oculta o elemento, apenas o torna invisível. Portanto, ainda ocupará espaço.
Samuel
6
Não apenas invisível, mas também transparente para eventos (cliques etc). Não alterar a exibição significa não refluir o documento, o que é uma coisa boa. A maioria dos elementos que devem aparecer / desaparecer gradualmente através da opacidade provavelmente devem ter uma posição fixa ou absoluta de qualquer maneira.
Rasmus Kaj
13

Esta solução alternativa funciona:

  1. definir um “quadro-chave”:

    @-webkit-keyframes fadeIn { 
      0% { opacity: 0; }
      20% { opacity: 0; }
      40% { opacity: 0.3; }
      60% { opacity: 0.5; }
      80% { opacity: 0.9; }
      100% { opacity: 1; }
    }
    
    @keyframes fadeIn {
      0% { opacity: 0; }
      20% { opacity: 0; }
      40% { opacity: 0.3; }
      60% { opacity: 0.5; }
      80% { opacity: 0.9; }
      100% { opacity: 1; }
    }
  2. Use este “quadro-chave” ao “pairar”:

    div a span { 
      display: none;
    }
    
    div a:hover span {
      display: block;
    
      -webkit-animation-name: fadeIn;
      -webkit-animation-duration: 1s;
      animation-name: fadeIn;
      animation-duration: 1s;
    }
Hermann Schwarz
fonte
9

Eu usei isso para alcançá-lo. Eles desaparecem ao pairar, mas não ocupam espaço quando escondidos, perfeito!

.child {
    height: 0px;
    opacity: 0;
    visibility: hidden;
    transition: all .5s ease-in-out;
}

.parent:hover .child {
    height: auto;
    opacity: 1;
    visibility: visible;
}
felixhirschfeld
fonte
6

Mudei um pouco, mas o resultado é lindo.

.child {
    width: 0px;
    height: 0px;
    opacity: 0;
}

.parent:hover child {
    width: 150px;
    height: 300px;
    opacity: .9;
}

Obrigado a todos.

Alexis Delrieu
fonte
4
Isso não funciona bem com leitores de tela: eles continuarão lendo o conteúdo.
ehdv
1
Você pode adicionar visibility: hidden;a .child / visibility:visible;ao foco e isso deve resolver o problema do leitor de tela
csilk
6

Há outro bom método para fazer isso usando eventos de ponteiro:

.child {
    opacity: 0;
    pointer-events: none;

    -webkit-transition: opacity 0.5s ease-in-out;
    -moz-transition: opacity 0.5s ease-in-out;
    transition: opacity 0.5s ease-in-out;
}

.parent:hover .child {
    opacity: 0.9;
    pointer-events: all;
}

Infelizmente, isso não é compatível com o IE10 e versões anteriores.

RafaelKr
fonte
4

Eu tive o mesmo problema. Tentei usar animações em vez de transições - como sugerido por @MichaelMullany e @Chris - mas só funcionou para navegadores de webkit mesmo se copiei e colei com os prefixos "-moz" e "-o".

Consegui contornar o problema usando em visibilityvez de display. Isso funciona para mim porque meu elemento filho é position: absolute, portanto, o fluxo de documentos não está sendo afetado. Pode funcionar para outras pessoas também.

Esta é a aparência do código original usando minha solução:

.child {
    position: absolute;
    opacity: 0;
    visibility: hidden;

    -webkit-transition: opacity 0.5s ease-in-out;
    -moz-transition: opacity 0.5s ease-in-out;
    transition: opacity 0.5s ease-in-out;
}

.parent:hover .child {
    position: relative;
    opacity: 0.9;
    visibility: visible;
}
Dave
fonte
Se você pairasse de volta para a criança enquanto ela estava animando fora de vista, ela voltaria, já que o elemento está simplesmente escondido. Bastante irritante se você estiver movendo o mouse em qualquer lugar.
adamj
4

Se você estiver acionando a mudança com JS, digamos no clique, há uma boa solução alternativa.

Você vê que o problema acontece porque a animação é ignorada no display: nenhum elemento, mas o navegador aplica todas as alterações de uma vez e o elemento nunca é display: block enquanto não estiver animado ao mesmo tempo.

O truque é pedir ao navegador para renderizar o quadro depois de alterar a visibilidade, mas antes de acionar a animação.

Aqui está um exemplo de JQuery:

    $('.child').css({"display":"block"});
    //now ask the browser what is the value of the display property
    $('.child').css("display"); //this will trigger the browser to apply the change. this costs one frame render
    //now a change to opacity will trigger the animation
    $('.child').css("opacity":100);
daniel.sedlacek
fonte
2
Esta pergunta não está marcada com JavaScript nem jQuery
j08691
Eu sei, eu escrevi para explicar o motivo pelo qual isso está acontecendo. Foi muito útil para mim quando aprendi sobre isso e espero que ajude outras pessoas também.
daniel.sedlacek
1
A propósito, os valores de opacidade estão entre 0 e 1
Amr de
2

Em elementos absolutos ou fixos, você também pode usar Z-index:

.item {
    position: absolute;
    z-index: -100;
}

.item:hover {
    z-index: 100;
}

Outros elementos devem ter um índice z entre -100 e 100 agora.

Luca Steeb
fonte
Infelizmente, isso confunde o símbolo indicador de senha KeePass nos type=passwordcampos. Não é visível.
philk
1
Podemos parar de usar números arbitrários de índice z? Aqui: z-index: 1; vs z-index: -1 será suficiente. Escolher grandes números de índice z torna as coisas incontroláveis.
dudewad
2

Eu sei, esta não é realmente uma solução para sua pergunta, porque você pede por

display + opacidade

Minha abordagem resolve uma questão mais geral, mas talvez esse fosse o problema de fundo que deveria ser resolvido usando displayem combinação com opacity.

Meu desejo era tirar o Elemento do caminho quando não estiver visível. Esta solução faz exatamente isso: move o elemento para fora e pode ser usada para a transição:

.child {
  left: -2000px;
  opacity: 0;
  visibility: hidden;
  transition: left 0s 0.8s, visibility 0s 0.8s, opacity 0.8s;
}

.parent:hover .child {
  left: 0;
  opacity: 1;
  visibility: visible;
  transition: left 0s, visibility 0s, opacity 0.8s;
}

Este código não contém prefixos de navegador ou hacks de compatibilidade com versões anteriores. Isso apenas ilustra o conceito de como o elemento é removido, uma vez que não é mais necessário.

A parte interessante são as duas definições de transição diferentes. Quando o ponteiro do mouse passa sobre o .parentelemento, o .childelemento precisa ser colocado no lugar imediatamente e, em seguida, a opacidade será alterada:

transition: left 0s, visibility 0s, opacity 0.8s;

Quando não há pairar, ou o ponteiro do mouse foi movido para fora do elemento, é necessário esperar até que a mudança de opacidade termine antes que o elemento possa ser movido para fora da tela:

transition: left 0s 0.8s, visibility 0s 0.8s, opacity 0.8s;

Afastar o objeto será uma alternativa viável em um caso em que a configuração display:none não quebraria o layout.

Espero ter acertado em cheio nessa questão, embora não tenha respondido.

Hannes Morgenstern
fonte
Esse filtro da Microsoft foi preterido desde o IE9. Há algum motivo específico para você querer adicioná-lo às respostas em 2016?
TylerH de
@TylerH Quantos usuários se deseja alcançar é uma questão de gosto.
Hannes Morgenstern
Considerando que está obsoleto , e o IE <11 não é mais suportado pela Microsoft, usar essa propriedade é de gosto questionável, na melhor das hipóteses.
TylerH de
@TylerH É comum ter que acomodar clientes que não querem ou não podem atualizar para um navegador mais recente. Tenho um cliente bem conhecido que ainda usa o IE6 e se recusa a atualizar por "motivos".
Marcus Cunningham
@MarcusCunningham A questão está marcada com css3, o que impede o uso do IE6 (e do IE7 e IE8) inteiramente. No navegador mais antigo possível para o qual o OP poderia escrever código, o filtro MS nesta resposta foi descontinuado. E para futuros leitores, é ainda mais inútil, já que nem mesmo é compatível. Não há nenhum argumento para incluí-lo em uma resposta a esta pergunta. É um ponto discutível, entretanto, uma vez que Hannes já o removeu de sua resposta.
TylerH
1

Uma coisa que fiz foi definir a margem do estado inicial para algo como "margem esquerda: -9999px" para que não apareça na tela e, em seguida, redefinir "margem esquerda: 0" no estado de foco. Mantenha "display: block" nesse caso. Fez o truque para mim :)

Editar: Salvar o estado e não reverter para o estado de foco anterior? Ok, aqui precisamos de JS:

<style>
.hovered { 
    /* hover styles here */
}
</style>

<script type="text/javascript">
$('.link').hover(function() {
   var $link = $(this);
   if (!$link.hasclass('hovered')) { // check to see if the class was already given
        $(this).addClass('hovered');
   } 
});
</script>
Joshua
fonte
Boa ideia, mas então eu
desligo o mouse
Alexis, não é isso que você quer fazer? Pairar significa SOMENTE ao passar o mouse. Esclareça o que você está tentando realizar.
Joshua
Sim, desculpe. Eu quero salvar o fade no mouseout.
Alexis Delrieu
Isso muda tudo. Quase. Basicamente, o que você quer é uma função JS que detecte o estado de foco, como outros usuários indicaram, e adicione ... bem ... veja minha resposta atualizada.
Joshua
1

Para ter animação nos dois sentidos no HoverIn / Out fiz essa solução. Espero que ajude alguém

@keyframes fadeOutFromBlock {
  0% {
    position: relative;
    opacity: 1;
    transform: translateX(0);
  }

  90% {
    position: relative;
    opacity: 0;
    transform: translateX(0);
  }

  100% {
    position: absolute;
    opacity: 0;
    transform: translateX(-999px);
  }
}

@keyframes fadeInFromNone {
  0% {
    position: absolute;
    opacity: 0;
    transform: translateX(-999px);
  }

  1% {
    position: relative;
    opacity: 0;
    transform: translateX(0);
  }

  100% {
    position: relative;
    opacity: 1;
    transform: translateX(0);
  }
}

.drafts-content {
  position: relative;
  opacity: 1;
  transform: translateX(0);
  animation: fadeInFromNone 1s ease-in;
  will-change: opacity, transform;

  &.hide-drafts {
    position: absolute;
    opacity: 0;
    transform: translateX(-999px);
    animation: fadeOutFromBlock 0.5s ease-out;
    will-change: opacity, transform;
  }
}
Nicholas
fonte
0

COMO ANIMAR OPACIDADE COM CSS:
este é o meu código:
o código CSS

.item {   
    height:200px;
    width:200px;
    background:red;
    opacity:0;
    transition: opacity 1s ease-in-out;
}

.item:hover {
    opacity: 1;
}
code {
    background: linear-gradient(to right,#fce4ed,#ffe8cc);
}
<div class="item">

</div>
<p><code> move mouse over top of this text</code></p>

ou verifique este arquivo de demonstração

function vote () {
var vote = getElementById ("yourOpinion")
if (this.workWithYou):
vote + = 1};
ri muito

zakizakibzr
fonte
1
Não responde à pergunta, pois a displaypropriedade foi simplesmente removida.
Brinde
-4

display:não é transicionável. Provavelmente, você precisará usar o jQuery para fazer o que deseja.

Fantasma de madara
fonte
3
Você tem que parar de defender o jQuery em todos os lugares, cara.
Benjamin Gruenbaum
1
@BenjaminGruenbaum jQuery é um homem incrível. É ótimo e faz todas as coisas.
Madara's Ghost