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 e
A quick note on the :before and :after selectors in IE8: for them to work you need to declare a DOCTYPE. See this W3Schools page. I am guessing you have already done this though.
See the answer to this question if you haven't already (I think you probably have).
Basically, the bottom line is that it's a bug. Your solution of using a z-index
of -1 is not ideal, but then again NO work around for the bug is going to be ideal. I don't think that using a z-index of -1 is something to be overly concerned about, unless it causes issues in your layout. If you are very concerned, then why don't you ONLY target IE8 w/ the fix. For example, you could use a conditional comment like so:
<!--[if IE 8]>
<style>
#target>div{
z-index:-1;
}
</style>
<![endif]-->
Behaviors like the one you are experiencing is one of the reasons many developers despise IE. In many cases, including this one, there is no perfect solution. You could:
:before
and :after
selectors & adjust your HTML/CSS to something that is IE8-friendly.z-index
solution.Unfortunately, in many cases there is no such thing as a "semantically correct" cross-browser website.
My two cents is to create an IE8 stylesheet and use the conditional comment I displayed above to load the stylesheet. Within the stylesheet, use the z-index: -1
solution you came up with. Many websites use IE-targeted stylesheets.
I use a different method to solve this problem:
The HTML for each product contains a "sold out" banner that can be positioned over the main image. By default the CSS hides this element. If the wrapping "product" DIV contains a class of "soldOut" the CSS will override the default declaration and display the banner.
<div class="product soldOut">
... product html ...
<div class="soldOutBanner"></div>
</div>
CSS:
.soldOutBanner {
display:none
}
.soldOut .soldOutBanner {
display:block;
width:133px;
height:130px;
position:absolute;
top:0px;
right:0px;
z-index:10;
background-image:url(../SoldOut.png);
}
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.
No need to set z-index
es, just make sure you use :after
instead of :before
(demo):
#target {
position: relative;
width: 200px;
height: 200px;
}
#target>div{
background: red;
width: 200px;
height: 200px;
}
#target:after {
content: "after";
position: absolute;
top: 0;
left: 10%;
width: 100%;
height: 100%;
background: cyan;
}
Since the generated content comes after #target
, it will naturally be stacked above.
BTW Whether a product is "sold" or not is semantic information, and so the correct semantic solution would be to include it in the HTML, rather than adding the image through CSS.