z-index IE8 bug on generated content with :after

2019-03-10 20:31发布

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?

4条回答
我只想做你的唯一
2楼-- · 2019-03-10 21:11

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);
}
查看更多
女痞
3楼-- · 2019-03-10 21:17

No need to set z-indexes, 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.

查看更多
该账号已被封号
4楼-- · 2019-03-10 21:29

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.

  1. 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;
    }
    
  2. 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;
    }
    
  3. 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.

查看更多
何必那么认真
5楼-- · 2019-03-10 21:33

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:

  1. stop using the :before and :after selectors & adjust your HTML/CSS to something that is IE8-friendly.
  2. Use conditional comments or JavaScript to issue a fix that specifically targets IE8
  3. Keep hacking and try to find another HTML/CSS combo that works -- but chances are it won't be any more ideal than your negative 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.

查看更多
登录 后发表回答