This is a known error in IE8, look at the last bug here:
http://nicolasgallagher.com/css-typography-experiment/demo/bugs.html
Now, playing a bit with a simple example I found this (test it using IE8):
http://jsfiddle.net/AjCPM/
<div id="target">
<div>div</div>
</div>
#target {
position: relative;
width: 200px;
height: 200px;
z-index: 1;
}
#target>div{
background: red; width: 200px; height: 200px;
position: relative;
z-index: 0;
}
#target:before {
top: 0; left: 10%; width: 100%; height: 100%; background: cyan;
content: "after";
position: absolute;
z-index: 10;
}
IE8 renders the cyan rectangle (the :after) below the red rectangle, even when it has lower z-index.
And now the tricky part:
change the z-index for #target>div from 0 to -1 and voilá ! it's solved !
So I solved my problem now using a lot of z-index: -1;
But I don't feel safe with this.
Do you know a better solution?
I'm using the :after pseudoelement because I have a list of products, and I want to add an image to the the item when it has the class 'sold' for example.
I can create in the server or with JS a new html element for that, but I think using :after is the correct semantic solution.
The problem is that I'm a bit paranoid about the :after pseudoelement now, do you think is better to avoid it?
To answer your last question first, as long as you don't need to support any browsers that completely lack support for generated content (http://caniuse.com/#feat=css-gencontent) then you shouldn't need to avoid it. However, since you note that this is a known bug, you should be careful about it.
In this specific example, I can think of three different ways to work around the bug. Whether these are useful to you depends on your actual use case.
Use :after
instead of :before
and remove positioning from the child div
: http://jsfiddle.net/AjCPM/24/
#target {
position: relative;
width: 200px;
height: 200px;
z-index: 1;
}
#target>div{
background: red;
width: 200px;
height: 200px;
}
#target:after {
content: "after";
position: absolute;
top: 0;
left: 10%;
width: 100%;
height: 100%;
background: cyan;
z-index: 10;
}
Add the after to the child div
instead of the parent: http://jsfiddle.net/AjCPM/26/
#target {
position: relative;
width: 200px;
height: 200px;
z-index: 1;
}
#target>div{
position: relative;
background: red;
width: 200px;
height: 200px;
z-index: 0;
}
#target>div:before{
content: "after";
position: absolute;
top: 0;
left: 10%;
width: 100%;
height: 100%;
background: cyan;
z-index: 10;
}
Use a wrapping element (usually because you already have one) to apply the base styling to: http://jsfiddle.net/AjCPM/29/
<div id="target">
<div id="wrap">
<div>div</div>
</div>
</div>
#target {
position: relative;
width: 200px;
height: 200px;
z-index: 1;
}
#wrap>div{
position: relative;
background: red;
width: 200px;
height: 200px;
z-index: 0;
}
#wrap>div:before{
content: "after";
position: absolute;
top: 0;
left: 10%;
width: 100%;
height: 100%;
background: cyan;
z-index: 10;
}
Basically, when faced with a difference in interpretation between browsers like this, your best bet is to try to rearrange your approach to find something that works cross-browser.