Como fazer um overlay sobre uma imagem, mas por baixo de um texto, e que altere a opacidade no hover? Talvez com pseudo-elements, se o HTML já estiver montado, sendo necessário apenas alterar o CSS ou usando elementos básicos.
A primeira vista, usar :pseudo-elements me parece mais prático, já que preciso mexer apenas no CSS do projeto, evitando qualquer modificação no HTML. Mas sabemos que é possível obter o mesmo resultado usando elementos básicos, e com o mesmo (quase o mesmo) CSS obter visualmente o mesmo resultado.
Vale ressaltar que esse post não faz um comparativo de performance (mas poderia), tão pouco irá apontar a melhor maneira ou a correta de resolver esse problema. Esse comparativo é apenas para fins didáticos.
Ponto de partida
A partir de dois cards idênticos, onde o card recebe uma imagem de fundo e comporta apenas duas div, sendo respectivamente título e subtitulo.
O texto no rodapé do card com a cor branca é apenas para ficar elegante :)
Veremos então como fazer um overlay sobre uma imagem, mas por baixo de um texto, e que altere a opacidade no hover...
Pseudo-element
O pseudo-element :before e :after para ser visível é necessário especificar um conteúdo, sendo essa a dificuldade mais corriqueira, já que é bem fácil esquece-lo.
Nesse caso, como não precisamos de conteúdo, adicionamos uma string vazia apenas para o mesmo ser inserido no DOM:
content: '';
Para estilizar e posicionar afim de obter o overlay, é necessário aplicar o pseudo-element no próprio card, além de alterar a posição do mesmo para relative, dessa maneira:
Acrescentei uma classe modificadora no primeiro card chamada card--pseudo-elements, para diferencia-lo do padrão.
.card--pseudo-elements {
position: relative;
}
.card--pseudo-elements:before {
/* requerido */
content: '';
/* estilo de preto quase transparente */
background-color: black;
opacity: 0.5;
/* posiciona nos limites do elemento pai */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* suavização básica */
transition: 200ms all;
}
Feito isso, para fazer o efeito de escurecer o overlay, é necessário apenas aplicar o hover no card, e manipular o pseudo-element, assim:
.card--pseudo-elements:hover:before {
opacity: 1;
}
Estaria pronto se não fosse por um problema: o overlay cobre todo o conteúdo do card. Isso ocorre por quê (de modo resumido) o elemento com posição absoluta fica numa camada superior (z-index).
Contornamos isso apenas definindo o z-index dos elementos, dentro do card:
.card--pseudo-elements .card__title,
.card--pseudo-elements .card__subtitle {
z-index: 1;
}
Nesse estágio você pode ter se questionado ou tentado aplicar um z-index negativo para o seu :pseudo-element, afim de empurra-lo para trás do texto, mas isso não funciona. Veja mais sobre z-index para entender melhor.
O resultado final com :pseudo-elements você confere abaixo:
Elemento
Neste método, precisamos acrescentar um elemento no HTML. Além da classe módificadora card--element para diferenciar do outro método. O código fica assim:
<div class="card">
<div class="card__title">
Maceió
</div>
<div class="card__subtitle">
Alagoas
</div>
<span class="card__overlay">
<!-- div overlay vazia -->
</span>
</div>
Você pode inserir no início ou no final do card, pessoalmente prefiro inserir no final e como span visando reduzir o risco de interferência no layout atual.
No CSS o código é quase idêntico, mudando apenas os seletores, e a não obrigatoriedade do content. Veja:
.card--element .card__overlay {
background-color: black;
opacity: 0.5;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: 200ms all;
}
/* aplicando o hover */
.card--element:hover .card__overlay {
opacity: 0.9;
}
Aqui encontramos o mesmo problema do :pseudo-element, o overlay sobrepõe todo o conteúdo do card, sendo assim a solução é a mesma:
.card--element .card__title,
.card--element .card__subtitle {
z-index: 1;
}
Abaixo você confere o resultado final com elemento básico:
Conclusão
Nota-se que a diferença entre os métodos é mínima, como o seletor diferente para o CSS e, de modo geral, uma linha a mais de código para ambos.
Se com o :pseudo-element é necessário adicionar o content à sua regra de estilo e dispensa a marcação HTML, com elemento básico não precisamos do content, mas é necessário adicionar o elemento ao HTML. O estilo e posicionamento do overlay é feito exatamente da mesma maneira.
Abaixo deixo o resultado final com os dois métodos:
Não esqueça de comentar com suas dúvidas e/ou sugestões. Obrigado.
Talvez continue com a parte 2, abordando acessibilidade e performance.
Top comments (4)
Muito bom, esclarecedor e de fácil entendimento. Parabéns pela didática, continue, por favor.
Show, muito bom!!
show! me ajudou bastante, já apliquei, valeu!
Massa