Definir opacidade da imagem de plano de fundo sem afetar os elementos filho

214

É possível definir a opacidade de uma imagem de plano de fundo sem afetar a opacidade dos elementos filho?

Exemplo

Todos os links no rodapé precisam de um marcador personalizado (imagem de plano de fundo) e a opacidade do marcador personalizado deve ser de 50%.

HTML

<div id="footer">
    <ul>
        <li><a href="#">Link 1</a></li>
        <li><a href="#">Link 2</a></li>
        <li><a href="#">Link 3</a></li>
        <li><a href="#">Link 4</a></li>
        <li><a href="#">Link 5</a></li>
    </ul>
</div>  

CSS

#footer ul li {
    background: url(/images/arrow.png) no-repeat 0 50%;
}  

O que eu tentei

Tentei definir a opacidade dos itens da lista como 50%, mas a opacidade do texto do link também é de 50% - e não parece haver uma maneira de redefinir a opacidade dos elementos filho:

#footer ul li {
    background: url(/images/arrow.png) no-repeat 0 50%;
    /* will also set the opacity of the link text */        
    opacity: 0.5;
}

Também tentei usar o rgba, mas isso não afeta a imagem de fundo:

#footer ul li {
    /* rgba doesn't apply to the background image */
    background: rgba(255, 255, 255, 0.5) url(/images/arrow.png) no-repeat 0 50%;
}
jmohr
fonte

Respostas:

119

Você pode usar CSS linear-gradient()com rgba().

div {
  width: 300px;
  height: 200px;
  background: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.5)), url("https://i.imgur.com/xnh5x47.jpg");
}
span {
  background: black;
  color: white;
}
<div><span>Hello world.</span></div>

Adesivos
fonte
Essa é a melhor solução!
Dzenis H.
93

Leve sua imagem para um editor de imagens, diminua a opacidade, salve-a como um .png e use-a.

2ToneKenobi
fonte
8
Hmm ... acabei de votar, mas olhe para esta resposta aceita: stackoverflow.com/a/6502295/131809 votou 10 vezes e é praticamente idêntico.
7284 Alex
9
Esta é uma boa opção, não faço ideia do porquê de tantos votos negativos. Se eu pudesse votar duas vezes, eu faria. Um elemento filho de um elemento pai parcialmente opaco será parcialmente opaco e deve ser. Todas as "soluções alternativas" são erros que eventualmente devem ser corrigidos.
RobW 28/11/12
6
@mystrdat Você já está baixando a imagem, este não é um pedido extra.
22413 brad
2
@mystrdat Mas ele já está baixando a imagem da seta. Você não forneceu uma solução sem imagem, então esse foi o meu ponto. Ele já está baixando a imagem da seta, e pode vir conforme necessário, o que não seria uma solicitação extra. Não estou entendendo de onde você vem.
22313
1
@brad Peço desculpas, acontece que li a pergunta errada agora que verifiquei novamente.
mystrdat
41

Isso funcionará com todos os navegadores

div {
 -khtml-opacity:.50; 
 -moz-opacity:.50; 
 -ms-filter:"alpha(opacity=50)";
  filter:alpha(opacity=50);
  filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
  opacity:.50; 
}

Se você não deseja que a transparência afete o contêiner inteiro e seus filhos, verifique esta solução alternativa. Você deve ter um filho absolutamente posicionado com um pai relativamente posicionado.

Verifique a demonstração em http://www.impressivewebs.com/css-opacity-that-doesnt-affect-child-elements/

Hussein
fonte
Acho que você precisa para mudar as”aspas no código acima para" em ordem para que ele funcione quando em linha reta copy-colado.
nsantorello
6
Essa resposta ainda é a melhor solução que as pessoas encontraram para o problema de: "como fazer um elemento filho não herdar o valor de opacidade do elemento pai no CSS"? Eu preciso que o filho realmente seja filho .. e no fluxo de documentos ... e também não quero trazer javascript / flash para isso; prefira CSS puro.
Govinda
Eu tenho 50% dos pais opacos <li> 's contendo imagens filhas que eu quero 100% opacos. Definir o <li> como position:relative;e o img para position:absolute;NÃO me permite substituir a opacidade herdada no img, e não posso usar o posicionamento absoluto para os próprios <li> (isso é uma bagunça ;-). Em Javascript, tentei imgs[i].style.opacity = '1';, mas isso também não funciona para substituir a opacidade herdada. Se entendi corretamente, também não posso usar o rgba porque preciso afetar as imagens, não apenas a cor de fundo. Alguém tem uma recomendação para mim?
Govinda 14/05
26
Toda essa resposta não faz sentido. O código fornecido, além de ser exatamente o que o solicitante não deseja, porque não funciona , não corresponde à descrição ou ao link. Estou tendo muita dificuldade para entender por que tantas pessoas votaram nele.
BoltClock
Se a pergunta fosse 'Como definir 50% de transparência em um elemento', essa seria uma boa resposta.
Lharby 25/04/19
29

Se você estiver usando a imagem como marcador, considere o pseudo-elemento: before.

#footer ul li {
}

#footer ul li:before {
    content: url(/images/arrow.png);
    filter:alpha(opacity=50);
    filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
    opacity:.50;
}
Mr Griever
fonte
3
Filtro é apenas uma solução de IE
Hussein
1
Eu acho que essa é provavelmente a melhor solução. É uma solução CSS pura. Também é possível hackear o suporte ao IE7 usando *zoom: expression( … );(consulte : after e: before pseudo elementos css hack para o IE 7 ), mas o IE7 está finalmente se tornando um passé.
Terceira
9
#footer ul li {
  position: relative;
  opacity: 0.99;
}

#footer ul li::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -1;
  background: url(/images/arrow.png) no-repeat 0 50%;
  opacity: 0.5;
}

Hackear com opacidade .99 (menos de 1) cria o contexto do índice z, assim você não pode se preocupar com os valores globais do índice z. (Tente removê-lo e veja o que acontece na próxima demonstração em que o wrapper pai possui um índice z positivo.)
Se o seu elemento já possui um índice z, você não precisa desse hack.

Demonstração desta técnica .

do utilizador
fonte
Você sabe por que precisamos definir um valor menor que 1 para a opacidade? É uma solução para vários navegadores?
zVictor
1
@zVictor sim, esse é um comportamento padronizado pelo w3c. Consulte Noções básicas sobre z-index CSS: o contexto de empilhamento .
usuário
4

Infelizmente, no momento em que escrevemos esta resposta, não havia uma maneira direta de fazer isso. Você precisa:

  1. use uma imagem semitransparente como plano de fundo (muito mais fácil).
  2. adicione um elemento extra (como div) ao lado dos filhos que você deseja opaco, adicione fundo a ele e depois de torná-lo semitransparente, posicione-o atrás dos filhos mencionados.
Reyraa
fonte
4

Outra opção é a abordagem CSS Tricks de inserir um pseudo-elemento do tamanho exato do elemento original logo atrás dele para falsificar o efeito de fundo opaco que estamos procurando. Às vezes, você precisará definir uma altura para o pseudo elemento.

div {
  width: 200px;
  height: 200px;
  display: block;
  position: relative;
}

div::after {
  content: "";
  background: url(image.jpg);
  opacity: 0.5;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  position: absolute;
  z-index: -1;   
}
kaleazy
fonte
3

A propriedade "filter" precisa de um número inteiro para a porcentagem de opacidade, em vez de duas vezes, para trabalhar no IE7 / 8.

filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);

PS: Postei isso como resposta, já que o SO precisa de pelo menos 6 caracteres alterados para uma edição.

lyubeto
fonte
2

Para realmente ajustar as coisas, recomendo colocar as seleções apropriadas nos wrappers de segmentação por navegador. Essa foi a única coisa que funcionou para mim quando não consegui fazer com que o IE7 e o IE8 "brincassem bem com os outros" (como atualmente trabalho para uma empresa de software que continua a apoiá-los).

/* color or background image for all browsers, of course */            
#myBackground {
    background-color:#666; 
}
/* target chrome & safari without disrupting IE7-8 */
@media screen and (-webkit-min-device-pixel-ratio:0) {
    #myBackground {
        -khtml-opacity:.50; 
        opacity:.50;
    }
}
/* target firefox without disrupting IE */
@-moz-document url-prefix() {
    #myBackground {
        -moz-opacity:.50;
        opacity:0.5;
    }
}
/* and IE last so it doesn't blow up */
#myBackground {
    opacity:.50;
    filter:alpha(opacity=50);
    filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.5);
}

Talvez eu tenha redundâncias no código acima - se alguém quiser limpá-lo ainda mais, fique à vontade!

código-sushi
fonte
3
Não é necessário segmentar cada navegador separadamente, basta usar os prefixos do navegador em um único bloco seletor. Com os prefixos do navegador, o navegador usará apenas a propriedade CSS apropriada. À medida que o tempo passa e a sintaxe dessa propriedade se torna padronizada, os fornecedores de navegadores abandonam o suporte para os prefixos e usam a propriedade CSS sem nenhum prefixo (por exemplo, o Firefox abandonou o suporte -moz-border-radiusno Firefox 13 e agora apenas procura a border-radiuspropriedade padrão ). IE7 e IE8 são uma história diferente, mas isso é apenas IE :-P
thirdender
Eu gostaria de saber quem votou negativamente e por que, por favor. A votação é inútil sem feedback informativo. Eu gostaria de poder melhorar minhas respostas. Se foi apenas porque as informações estavam desatualizadas, verifique a data. :) Obrigado.
code-sushi
@ code-sushi: Se o voto negativo ocorreu ao mesmo tempo que o seu comentário, considere que pode ter sido de outra pessoa que concordou com o comentário do terceiro (observe os votos positivos no próprio comentário). Não votei na sua resposta, mas tenho que concordar - gostaria de acrescentar que 1) o KHTML nunca verá o arquivo -khtml-opacityporque não entende a consulta de mídia, tornando-o inútil 2) O IE é mais estável do que você pensa; ele não "explodirá" apenas porque você adiciona prefixos não pertencentes ao IE a uma regra que se aplica ao IE. O problema, no momento em que você o enfrentou, deve ter vindo de outro lugar.
BoltClock
Minha resposta original foi de quase dois anos atrás e a votação para baixo ocorreu recentemente, como este ano. Eu só estava curioso. Quanto aos comentários do IE, eles pertenciam a 7 quando isso ainda precisava de apoio; Tenho certeza de que não há problema em ignorar o IE 7 atualmente. Obrigado pelo seu feedback!
code-sushi
1

Se você precisa definir a opacidade apenas como marcador, por que não define o canal alfa diretamente na imagem? A propósito, acho que não há uma maneira de definir a opacidade para uma imagem de plano de fundo via css sem alterar a opacidade de todo o elemento (e de seus filhos também).

Minkiele
fonte
1

Apenas para adicionar ao exposto ... você pode usar o canal alfa com os novos atributos de cores, por exemplo. rgba (0,0,0,0) ok, então isso é preto, mas com opacidade zero, para que, como pai, não afete a criança. Isso funciona apenas no Chrome, FF, Safari e ...

converta suas cores hexadecimais em RGBA

frontsideup
fonte
4
Isso não funcionará com o background-imagesolicitado pelo OP.
Torsten Walter
1

Encontrei um tutorial muito bom e simples sobre esse problema. Eu acho que funciona muito bem (e, embora seja compatível com o IE, eu apenas digo aos meus clientes para usar outros navegadores):

Transparência em segundo plano CSS sem afetar elementos filho, através de RGBa e filtros

A partir daí, você pode adicionar suporte ao gradiente etc.

Francisco
fonte
Bem, não vai funcionar diretamente. Você precisaria colocar uma div como elemento aparente com a cor de fundo: (255,255,255,0,5) por exemplo
Francisco
0
#footer ul li
     {
       position:relative;
       list-style:none;
     }
    #footer ul li:before
     {
       background-image: url(imagesFolder/bg_demo.png);
       background-repeat:no-repeat;
       content: "";
       top: 5px;
       left: -10px;
       bottom: 0;
       right: 0;
       position: absolute;
       z-index: -1;
       opacity: 0.5;
    }

Você pode tentar este código. Eu acho que vai dar certo. Você pode visitar a demo

Jakir Hossain
fonte