¿Antes de no funcionar en elementos img?

262

Estoy tratando de usar el :beforeselector para colocar una imagen sobre otra imagen, pero descubro que simplemente no funciona colocar una imagen antes de un imgelemento, solo algún otro elemento. Específicamente, mis estilos son:

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

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

y encuentro que esto funciona bien:

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

pero esto no:

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

Puedo usar un elemento divo en plugar de eso span, y el navegador superpone correctamente mi imagen sobre la imagen en el imgelemento, pero si aplico la clase de superposición a laimg sí mismo, no funciona.

Me gustaría que esto funcione porque eso spanme ofende, pero lo más importante es que tengo alrededor de 100 publicaciones de blog que me gustaría modificar, y puedo hacerlo de una vez si solo pudiera modificar la hoja de estilo, pero si tengo que regresar y agregar un spanelemento adicional entre los elementos ay img, esto será mucho más trabajo.

Joshua Frank
fuente
55
Esto es extraño, especialmente porque el estándar CSS en sí mismo da un ejemplo de uso: antes con un elemento IMG ...
@chharvey: Esa pregunta se hizo después de esta.
Joshua Frank

Respuestas:

263

Desafortunadamente, la mayoría de los navegadores no admiten el uso :aftero:before en etiquetas img.

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

Sin embargo, ES posible que logre lo que necesita con JavaScript / jQuery. Mira este violín:

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

$(function() {

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

});

Editar :

Por la razón por la cual esto no es compatible, consulte la respuesta de coreyward .

cwharris
fuente
3
falta tu violín. Esa es la belleza de los enlaces jsFiddle.
Roko C. Buljan
Arreglado. Lo siento por eso.
cwharris
1
Esta respuesta no explica por qué img no puede tener antes o después. Además, la solución javascript propuesta no es un reemplazo adecuado para ella.
Jasper Kennis
3
No se espera que la solución propuesta funcione en todos los escenarios. Es simplemente un ejemplo de cómo se puede evitar el problema. Si desea proponer una solución más general, no dude en publicar una respuesta.
cwharris
141

Los pseudo-selectores antes y después no insertan elementos HTML: insertan texto antes o después del contenido existente del elemento objetivo. Debido a que los elementos de imagen no contienen texto o tener descendencia, ni img:beforeo img:afterno le hará ningún bien. Este es también el caso de elementos como <br>y <hr>por la misma razón.

coreyward
fuente
Las etiquetas Img son claramente elementos en sí mismas y, sin embargo, se nos permite insertarlas antes o después de otros elementos usando: before y: after psuedo-selectors. ¿No está esto en la especificación css?
cwharris
13
Eso es un poco diferente. Puede insertar una imagen, pero no usar una etiqueta de imagen; debe usar la content: url(/img/foo.jpg);sintaxis. Consulte w3.org/TR/CSS21/generate.html para obtener más detalles.
coreyward
44
Pequeña corrección: insertan elementos psuedo, que son más como elementos que como nodos de texto.
Chris Calo
El contenido generado se convierte en parte del Shadow DOM. Esos nuevos elementos, atributos y nodos de texto son muy reales. Puede verlos, por ejemplo, en el Inspector de Chrome.
Marc Diethelm
@coreyward Quizás confíes en MDN (Elemento reemplazado)
Marc Diethelm
41

Encontré una manera de hacer que esto funcione en css puro:

El método solo soy contenido falso

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

Puede consultar CodePen: solo soy contenido falso o ver la fuente .

Fuente y fragmento

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"  
/>

Soporte del navegador

✓ Chrome 10+

✓ Firefox 11+

✓ Opera 9.8+

✓ Safari

Sin soporte

⊗ Internet Explorer 8/9

Por favor, pruebe en otros navegadores

TimPietrusky
fuente
1
Básicamente, simplemente agrega contenido: "" al estilo de la etiqueta img y: before y: after empezar a trabajar. Buen hallazgo, me pregunto cómo es el navegador cruzado.
w00t
2
Configuré una prueba de ícono jsbin.com/esewow/edit#html,live y puedo confirmar que no funciona en IE8, pero en Chrome y Safari funciona bien.
w00t
14
El ejemplo de CodePen solo funciona en Firefox si el src de la etiqueta img no es válido, lo que hace que el atributo alt se represente como un elemento que realmente permite: antes y: después. Si existe el img src, deja de funcionar: codepen.io/anon/pen/EjtDu
thenickdude
2
Detente si me equivoco, pero parece que ya no funciona con Chrome 46
Gyum Fox
55
img: before e img: after no funcionan en Safari en absoluto . Ni siquiera esto, lo que inicialmente me entusiasmó. Buen intento sin embargo.
Wray Bowling
9

Debido a la naturaleza de <img>ser un elemento reemplazado , el estilo del documento no lo afecta.

Para referenciarlo de todos modos, <picture>proporciona un contenedor nativo ideal que puede tener pseudoelementos adjuntos, de esta manera:

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>

dakab
fuente
3

Aquí hay otra solución que usa un contenedor div para img mientras se usa :hover::afterpara lograr el efecto.

El HTML de la siguiente manera:

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

El CSS de la siguiente manera:

#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 verlo en acción, mira el violín que he creado. Solo para que sepa que esto es compatible con el navegador cruzado y no hay necesidad de engañar al código con 'contenido falso'.

Truleighsyd
fuente
Es útil aplicar display: inline-blocka #img_container. Eso hará que el ancho del contenedor sea igual a la imagen en todos los tamaños de pantalla. Entonces, no terminas teniendo :aftercontenido flotando fuera de la imagen.
Anónimo
1

Creo que la mejor manera de ver por qué esto no funciona es eso: antes y después de insertar su contenido antes o después del contenido dentro de la etiqueta a la que los está aplicando. Por lo tanto, funciona con divs o spans (o la mayoría de las otras etiquetas) porque puede poner contenido dentro de ellos.

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

Sin embargo, un img es una etiqueta auto-contenida y de cierre automático, y dado que no tiene una etiqueta de cierre separada, no puede poner nada dentro de ella. (Eso tendría que verse como<img>Content</img> , pero por supuesto eso no funciona).

Sé que este es un tema antiguo, pero aparece primero en Google, por lo que espero que esto ayude a otros a aprender.

BevansDesign
fuente
1

Esta funciona para mí:

html

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

CSS

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

::after se puede usar para mostrar la imagen alternativa de una imagen


Vea el ejemplo a continuación, las primeras 2 imgetiquetas apuntan a las URL rotas. Pero el segundo muestra la imagen alternativa en lugar del logotipo roto predeterminado del navegador. Sin embargo, no estoy seguro de que esto sea práctico, me resulta un poco complicado hacer que funcione correctamente.

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">

Loi Nguyen Huynh
fuente
0

Prueba 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
}
subindas pm
fuente
-1

Intenté y encontré un método más simple para hacerlo. Aquí está el HTML:

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

Lo que hice fue colocar una <p>etiqueta vacía después de mi etiqueta de imagen. Ahora usaré p :: antes para mostrar la imagen y posicionarla de acuerdo a mis necesidades. Aquí está el 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');
}

Intentalo.

Tajveer Singh Nijjar
fuente
-1

Pruebe :: después en el elemento anterior.

Dmytro Yurchenko
fuente
¿Elaborarías tu publicación?
zmag