Antes: não funciona em elementos img?


262

Estou tentando usar o :beforeseletor para colocar uma imagem sobre outra imagem, mas estou descobrindo que simplesmente não funciona para colocar uma imagem antes de um imgelemento, apenas algum outro elemento. Especificamente, meus estilos são:

.container
{
   position: relative;
   display: block;
}

.overlay:before
{
    content: url(images/[someimage].png);
    position: absolute;
    left:-20px;
    top: -20px;
}

e acho que isso funciona bem:

<a href="[url]" class="container">
  <span class="overlay"/>
  <img width="200" src="[url]"/>
</a>

mas isso não:

<a href="[url]" class="container">
  <img width="200" src="[url]" class="overlay"/>
</a>

Posso usar um elemento divou em pvez disso span, e o navegador sobrepõe minha imagem corretamente sobre a imagem no imgelemento, mas se eu aplicar a classe de sobreposição a imgela mesma, ela não funcionará.

Gostaria de fazer isso funcionar porque isso spanme ofende mais, mas o mais importante é que tenho cerca de 100 postagens que gostaria de modificar e posso fazer isso de uma só vez, se puder modificar a folha de estilo, mas se eu tiver que voltar e adicionar um spanelemento extra entre os elementos ae img, isso será muito mais trabalhoso.


5
Isso é estranho, principalmente porque o próprio padrão CSS fornece um exemplo de uso: before com um elemento IMG…


@ chharvey: Essa pergunta foi feita depois desta.
Joshua Frank

Respostas:


263

Infelizmente, a maioria dos navegadores não suporta o uso :afterou :beforeem tags img.

http://lildude.co.uk/after-css-property-for-img-tag

No entanto, é possível realizar o que você precisa com JavaScript / jQuery. Confira este violino:

http://jsfiddle.net/xixonia/ahnGT/

$(function() {

    $('.target').after('<img src="..." />');

});

Editar :

Por esse motivo, isso não é suportado, verifique a resposta do coreyward .


3
seu violino está faltando. Essa é a beleza dos links jsFiddle.
Roko C. Buljan

Corrigido. Me desculpe por isso.
cwharris

1
Esta resposta não explica por que o img não pode ter antes ou depois. Além disso, a solução javascript proposta não é um substituto adequado para ela.
Jasper Kennis

3
Não se espera que a solução proposta funcione em todos os cenários. É simplesmente um exemplo de como alguém pode contornar o problema. Se você deseja propor uma solução mais geral, fique à vontade para postar uma resposta.
cwharris

141

Os pseudo-seletores de antes e depois não inserem elementos HTML - eles inserem texto antes ou depois do conteúdo existente do elemento de destino. Como os elementos de imagem não contêm texto ou têm descendentes, nem img:beforeou img:aftervai fazer nenhum bem. Esse também é o caso de elementos como <br>e <hr>pelo mesmo motivo.


As tags img são claramente elementos em si mesmas, e ainda assim podemos inseri-las antes ou depois de outros elementos usando os seletores psuedo: before e: after. Isso não está na especificação css?
Cwharris

13
Isso é um pouco diferente. Você pode inserir uma imagem, mas não usando uma tag de imagem - é necessário usar a content: url(/img/foo.jpg);sintaxe. Consulte w3.org/TR/CSS21/generate.html para obter detalhes.
coreyward

4
Correção pequena: Eles inserem elementos psuedo, que são mais parecidos com elementos do que com nós de texto.
Chris Calo

O conteúdo gerado se torna parte do DOM da Shadow. Esses novos elementos, atributos e nós de texto são muito reais. Você pode vê-los, por exemplo, no Inspetor do Chrome.
Marc Diethelm

@coreyward Talvez você vai confiar MDN (Substituído Element)
Marc Diethelm

41

Eu encontrei uma maneira de fazer isso funcionar em css puro:

O método " Eu sou apenas conteúdo falso "

um método CSS puro para habilitar img: after.

Você pode conferir o CodePen: sou apenas um conteúdo falso ou vejo a fonte .

Origem e snippet

img {
    /* hide the default image */
    height:0;
    width:0;

    /* hide fake content */
    font-size:0;
    color:transparent;

    /* enable absolute position for pseudo elements */
    position:relative;

    /* and this is just fake content */
    content:"I'm just fake content";
}

/* initial absolute position */
img:before,
img:after {
    position:absolute;
    top:0;
    left:0;    
}

/* img:before - chrome & others */
img:before {
    content:url(http://placekitten.com/g/250/250);
}

/* img:before - firefox */
body:not(:-moz-handler-blocked) img:before {
    padding:125px;
    background:url(http://placekitten.com/g/250/250) no-repeat;
}

/* img:after */
img:after {
    /* width of img:before */
    left:250px;

    content:url(http://lorempixel.com/350/200/city/1);
}
<img
    alt="You are watching the ~ I'm just fake content ~ method"  
/>

Suporte do navegador

✓ Chrome 10 ou superior

✓ Firefox 11 ou superior

✓ Opera 9.8 ou superior

✓ Safari

Sem suporte

⊗ Internet Explorer 8/9

Teste em outros navegadores


1
Então, basicamente, você apenas adiciona conteúdo: "" ao estilo da tag img e: before e: after começam a trabalhar. Boa descoberta, gostaria de saber como é o navegador cruzado.
W00t

2
Configurei um teste de ícone jsbin.com/esewow/edit#html,live e posso confirmar que não funciona no IE8, mas no Chrome e Safari funciona bem.
W00t

14
O exemplo do CodePen só funciona no Firefox se o src da tag img for inválido - isso faz com que o atributo alt seja renderizado como um elemento que realmente permita: before e: after. Se existe o src img, ele pára de funcionar: codepen.io/anon/pen/EjtDu
thenickdude

2
Pare-me se eu estiver errado, mas parece que ele não funciona mais com o Chrome 46
Gyum Fox 17/11/2015

5
img: before e img: after não funcionam no Safari . Nem isso, que inicialmente me deixou empolgado. Boa tentativa embora.
Wray Bowling

9

Devido à natureza de <img>ser um elemento substituído , o estilo do documento não o afeta.

Para referenciá-lo de qualquer maneira, <picture>fornece um invólucro nativo ideal que pode ter pseudoelementos anexados a ele, assim:

img:after, picture:after{
    content:"\1F63B";
    font-size:larger;
    margin:-1em;
}
<img src="//placekitten.com/110/80">

<picture>
    <img src="//placekitten.com/110/80">
</picture>


3

Aqui está outra solução usando um contêiner div para img enquanto estiver usando :hover::afterpara obter o efeito.

O HTML da seguinte maneira:

<div id=img_container><img src='' style='height:300px; width:300px;'></img></div>

O CSS da seguinte maneira:

#img_container { 
    margin:0; 
    position:relative; 
} 

#img_container:hover::after { 
    content:''; 
    display:block; 
    position:absolute; 
    width:300px; 
    height:300px; 
    background:url(''); 
    z-index:1; 
    top:0;
} 

Para vê-lo em ação, confira o violino que eu criei. Só para você saber que isso é compatível com vários navegadores e não há necessidade de enganar o código com 'conteúdo falso'.


É útil aplicar display: inline-block- se a #img_container. Isso tornará a largura do contêiner igual à imagem em todos os tamanhos de tela. Portanto, você não acaba tendo :afterconteúdo flutuando fora da imagem.
Anônimo

1

Acho que a melhor maneira de analisar por que isso não funciona é: antes e: depois de inserir o conteúdo antes ou depois do conteúdo na tag à qual você está aplicando. Portanto, ele funciona com divs ou spans (ou com a maioria das outras tags), porque você pode colocar conteúdo dentro delas.

<div>
:before
Content
:after
</div>

No entanto, um img é uma tag independente e de fechamento automático e, como não possui uma tag de fechamento separada, você não pode colocar nada nela. (Isso precisa parecer <img>Content</img>, mas é claro que não funciona.)

Sei que esse é um tópico antigo, mas aparece primeiro no Google; espero que isso ajude outras pessoas a aprender.


1

Este funciona para mim:

html

<ul>
    <li> name here </li>
</ul>

CSS

ul li::before {
    content: url(../images/check.png);
}


1

::after pode ser usado para exibir a imagem de fallback de uma imagem


Veja o exemplo abaixo, as duas primeiras imgtags apontam para os URLs quebrados. Mas o segundo exibe a imagem de fallback em vez do logotipo quebrado padrão do navegador. No entanto, não tenho certeza se isso é prático, acho meio complicado fazê-lo funcionar corretamente.

img {
  position: relative;
  display: inline-block;
  width: 300px;
  height: 200px;
  vertical-align: top;
}
img:not(:first-child)::after {
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  content: "<" attr(alt) "> NOT FOUND";
  border: 1px dashed #999;
  background: url(https://cdn.dribbble.com/users/1012566/screenshots/4187820/topic-2.jpg) center/100%;
}
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100/75" alt="logo">
<img src="https://source.unsplash.com/random/100x75" alt="logo">


0

Experimente este código

.button:after {
    content: ""
    position: absolute
    width: 70px
    background-image: url('../../images/frontapp/mid-icon.svg')
    display: inline-block
    background-size: contain
    background-repeat: no-repeat
    right: 0
    bottom: 0
}

-1

Eu tentei e encontrei um método mais simples para fazer isso. Aqui está o HTML:

    <img id="message_icon" src="messages2.png">
    <p id="empty_para"></p>

O que fiz foi colocar uma <p>tag vazia após a minha tag de imagem. Agora usarei p :: before para mostrar a imagem e posicioná-la de acordo com minhas necessidades. Aqui está o CSS:

#empty_para
{
    display:inline;
    font-size:40;
    background:orange;
    border:2px solid red;
    position:relative;
    top:-400px;
    left:100px;
}
#empty_para::before
{
    content: url('messages.png');
}

Tente.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.