Is there any way to have opacity apply to absolutely positioned child elements in ie8

mikepr picture mikepr · May 26, 2011 · Viewed 7k times · Source

In most browsers, when an html element is only partially opaque, its children "inherit" this opacity. (It isn't quite inheritance--more correctly, the entire image is assembled, including the parent and its children recursively, and then the opacity is applied to the entire thing.)

In IE8 (and I would assume also for earlier versions of IE), this is not always what happens with opacity. If the child elements have position:static (the default if no position is specified), then it does work as I described above. However, it appears to be the case that, if the position is set to anything else (e.g., absolute, or relative), then the child element is fully opaque.

I want to know how to make the opacity correctly affect both the parent and the child elements but still keep the child element with position:absolute;

Here is an example of the problem. The following code is supposed to make a translucent gray box with a translucent blue surrounding area, on top of a vertical red bar. On Firefox, Chrome, etc., This is what is actually seen. On IE8, the blue box is correctly translucent, but the gray part is opaque.

<!doctype html>
<html>
  <head>
    <style>
      div.parentElem
      {
        background-color:#0000ff;
        position: absolute;
        left:75px;
        top:75px;
        width:300px;
        height:225px;        
        opacity:0.5;
        filter:alpha(opacity=50);
      }
      div.childElem
      {
        background-color:#808080;
        position: absolute;
        left: 10px;
        right: 10px;
        top: 10px;
        bottom: 10px;
      }
      div.redBar
      {
        position: absolute;
        left:150px;
        top:50px;
        height:350px;
        width:25px;
        background-color: #ff0000;        
      }
    </style>
  </head>
  <body>
    <div class="redBar"></div>
    <div class="parentElem">
      <div class="childElem"></div>
    </div>
  </body>
</html>

Obviously, this is just a toy example--I could have had a single div with a blue border and a gray background to achieve the desired effect. In the real scenario, I am layering several different divs, each of which has a png background image to dynamically build an image.

My first attempted workaround was to apply opacity to both the parent and the child, either by setting the filter on the child to alpha(opacity=50); or simply setting filter:inherit;. This does not achieve the desired result because it makes a translucent blue rectangle with a translucent gray rectangle on top of it. The empty space in the middle ends up being translucent blue-ish gray whereas it should be translucent gray. Similarly, it does not work to make the elements siblings. Any solution needs to compose the two images before applying any transparency to anything.

In my research, I found some suggestions that applying either zoom:1; or float:none; to the inner element might resolve the issue, but neither worked for me.

My eventual workaround was to give the child element position:static. It's kind of an ugly solution, but what I would do to apply it to the above example is change the style of the child element to look like:

  div.childElem
  {
    background-color:#808080;
    position:static;
    margin-left:10px; 
    margin-right:10px;
    height:205px;
    margin-top:10px;
  }

It's kind of an ugly solution because it means that I have to know the height of the object. Also, in the real case where I am composing several different png's, and I would like them to be logical siblings, I have to put them all in a nested parent-child-grandchild-etc. relationship. It also prevents me from adding any textual elements except on the very top of the stack (the innermost div) without messing up the positioning. It does work, though, and it looks the same in all browsers.

Is there any way to avoid such a horrid workaround and have opacity correctly affect the child elements without making the position static? Thanks!

Answer

gibbitz picture gibbitz · Jun 2, 2012