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.
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
}
I found a way to make this work in pure css:
a pure CSS method to enable img:after.
You can check out the CodePen: I'm just fake content or see the source.
img {_x000D_
/* hide the default image */_x000D_
height:0;_x000D_
width:0;_x000D_
_x000D_
/* hide fake content */_x000D_
font-size:0;_x000D_
color:transparent;_x000D_
_x000D_
/* enable absolute position for pseudo elements */_x000D_
position:relative;_x000D_
_x000D_
/* and this is just fake content */_x000D_
content:"I'm just fake content";_x000D_
}_x000D_
_x000D_
/* initial absolute position */_x000D_
img:before,_x000D_
img:after {_x000D_
position:absolute;_x000D_
top:0;_x000D_
left:0; _x000D_
}_x000D_
_x000D_
/* img:before - chrome & others */_x000D_
img:before {_x000D_
content:url(http://placekitten.com/g/250/250);_x000D_
}_x000D_
_x000D_
/* img:before - firefox */_x000D_
body:not(:-moz-handler-blocked) img:before {_x000D_
padding:125px;_x000D_
background:url(http://placekitten.com/g/250/250) no-repeat;_x000D_
}_x000D_
_x000D_
/* img:after */_x000D_
img:after {_x000D_
/* width of img:before */_x000D_
left:250px;_x000D_
_x000D_
content:url(http://lorempixel.com/350/200/city/1);_x000D_
}
_x000D_
<img_x000D_
alt="You are watching the ~ I'm just fake content ~ method" _x000D_
/>
_x000D_
✓ Chrome 10+
✓ Firefox 11+
✓ Opera 9.8+
✓ Safari
⊗ Internet Explorer 8 / 9
Please test in other browsers
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.
This one works for me:
html
<ul>
<li> name here </li>
</ul>
CSS
ul li::before {
content: url(../images/check.png);
}
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.
Just give the Image "position: relative" and it will work
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.
Try ::after on previous element.
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 fiddle I've created. Just so you know this is cross browser friendly and there's no need to trick the code with 'fake content'.
::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 {_x000D_
position: relative;_x000D_
display: inline-block;_x000D_
width: 300px;_x000D_
height: 200px;_x000D_
vertical-align: top;_x000D_
}_x000D_
img:not(:first-child)::after {_x000D_
position: absolute;_x000D_
left: 0; top: 0; right: 0; bottom: 0;_x000D_
content: "<" attr(alt) "> NOT FOUND";_x000D_
border: 1px dashed #999;_x000D_
background: url(https://cdn.dribbble.com/users/1012566/screenshots/4187820/topic-2.jpg) center/100%;_x000D_
}
_x000D_
<img src="https://source.unsplash.com/random/100/75" alt="logo">_x000D_
<img src="https://source.unsplash.com/random/100/75" alt="logo">_x000D_
<img src="https://source.unsplash.com/random/100x75" alt="logo">
_x000D_
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{_x000D_
content:"\1F63B";_x000D_
font-size:larger;_x000D_
margin:-1em;_x000D_
}
_x000D_
<img src="//placekitten.com/110/80">_x000D_
_x000D_
<picture>_x000D_
<img src="//placekitten.com/110/80">_x000D_
</picture>
_x000D_
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.
Source: Stackoverflow.com