Does :before not work on img elements?

HtmlCss

Html Problem Overview


I'm trying to use the :before selector to place an image over another image, but I'm finding that it simply doesn't work to place an image before an img element, only some other element. Specifically, my styles are:

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

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

and I find that this works fine:

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

but this does not:

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

I can use a div or p element instead of that span, and the browser correctly overlays my image over the image in the img element, but if I apply the overlay class to the img itself, it doesn't work.

I'd like to get this working because that extra span offends me, but more importantly, I've got about 100 blog posts that I'd like to modify, and I can do this in one go if I could just modify the stylesheet, but if I have to go back and add an extra span element in between the a and img elements, this will be a lot more work.

Html Solutions


Solution 1 - Html

Unfortunately, most browsers do not support using :after or :before on img tags.

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

However, it IS possible for you to accomplish what you need with JavaScript/jQuery. Check out this fiddle:

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

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

Edit:

For the reason why this isn't supported, check out coreyward's answer.

Solution 2 - Html

The before and after pseudo-selectors don't insert HTML elements — they insert text before or after the existing content of the targeted element. Because image elements don't contain text or have descendants, neither img:before or img:after will do you any good. This is also the case for elements like <br> and <hr> for the same reason.

Solution 3 - Html

I found a way to make this work in pure css:

The I'm just fake content-method

a pure CSS method to enable img:after.

You can check out the CodePen: I'm just fake content or see the source.

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

Browser support

✓ Chrome 10+

✓ Firefox 11+

✓ Opera 9.8+

✓ Safari

No support

⊗ Internet Explorer 8 / 9

Please test in other browsers

Solution 4 - Html

Due to the nature of <img> being a replaced element, document styling doesn’t affected it.

To reference it anyway, <picture> provides an ideal, native wrapper that can have pseudo-elements attached to it, like so:

img::after,
picture::after{
    content:"\1F63B";
    font-size:larger;
    margin:-1em;
}

Solution 5 - Html

Here's another solution using a div container for img while using :hover::after to achieve the effect.

The HTML as follows:

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

The CSS as follows:

#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;
} 

To see it in action, check out the http://jsfiddle.net/D7C88/">fiddle</a> I've created. Just so you know this is cross browser friendly and there's no need to trick the code with 'fake content'.

Solution 6 - Html

The pseudo-elements generated by ::before and ::after are contained by the element's formatting box, and thus don't apply to replaced elements such as img, or to br elements.

https://developer.mozilla.org/en-US/docs/Web/CSS/::after

Solution 7 - Html

I think the best way to look at why this doesn't work is that :before and :after insert their content before or after the content within the tag you're applying them to. So it works with divs or spans (or most other tags) because you can put content inside them.

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

However, an img is a self-contained, self-closing tag, and since it has no separate closing tag, you can't put anything inside of it. (That would need to look like <img>Content</img>, but of course that doesn't work.)

I know this is an old topic, but it pops up first on Google, so hopefully this will help others learn.

Solution 8 - Html

::after may be used to display the fallback image of an image


See the example below, first 2 img tags are point to the broken urls. But the second one displays the fallback image instead of the default broken logo from the browser. However, I'm not sure this's any practical, I find it kind of tricky to get it to work right.

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

Solution 9 - Html

In these cases it is preferable to use the <figure> tag, which allows you to manage the css in an optimal way This way you can use after just on the figure

Example

<div class="exemple">
  <figure>
    <img src="img1.jpg"/>
  </figure>
  <figure>
    <img src="img2.jpg"/>
  </figure>
</div>

Solution 10 - Html

This one works for me:

html

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

CSS

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

Solution 11 - Html

Try this code

.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
}

Solution 12 - Html

<img> is a replaced element and using :before or :after pseudo-elements on it works if the image fails to load and otherwise it does not work. If you intend to have a fallback in case of image load failure,please refer to https://stackoverflow.com/a/71478688/14204452

Solution 13 - Html

Try ::after on previous element.

Solution 14 - Html

I tried and found a simpler method to do so. Here is the HTML:

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

What I did was place an empty <p> tag after my image tag. Now I will use p::before to show the image and position it according to my needs. Here is the 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');
}

Try it.

Solution 15 - Html

Just give the Image "position: relative" and it will work

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoshua FrankView Question on Stackoverflow
Solution 1 - HtmlcwharrisView Answer on Stackoverflow
Solution 2 - HtmlcoreywardView Answer on Stackoverflow
Solution 3 - HtmlTimPietruskyView Answer on Stackoverflow
Solution 4 - HtmldakabView Answer on Stackoverflow
Solution 5 - HtmltruleighsydView Answer on Stackoverflow
Solution 6 - HtmlGoda AView Answer on Stackoverflow
Solution 7 - HtmlBevansDesignView Answer on Stackoverflow
Solution 8 - HtmlLoi Nguyen HuynhView Answer on Stackoverflow
Solution 9 - HtmlGiuseppe RuffaView Answer on Stackoverflow
Solution 10 - HtmlSaifView Answer on Stackoverflow
Solution 11 - Htmlsubindas pmView Answer on Stackoverflow
Solution 12 - HtmlNasim B. DView Answer on Stackoverflow
Solution 13 - HtmlDmytro YurchenkoView Answer on Stackoverflow
Solution 14 - HtmlTajveer Singh NijjarView Answer on Stackoverflow
Solution 15 - HtmlMr_sordumView Answer on Stackoverflow