Elements with transparency appearing over opaque foreground element

Elements with transparency appearing over opaque foreground element

During the course of using some transparency on elements, and an overlay, we’ve come across a CSS oddity we can’t quite work out.

View post on imgur.com

As shown in the screenshot, there are two img elements with 0.4 opacity applied. We then open an overlay on top of these, and they appear in front of this. When opacity is set to 1.0, they no longer show in front.

Other relevant CSS is that the overlay has a Z-Index of 999, and has no ancestral connection with the buttons.

Opacity Affects Stacking Order

Consider the following HTML snippet:

<div class="wrapper tweak">
    <div class="overlay"> 
        <p>The Overlay Panel</p>
    <div class="content">
        <p>The main Content panel with a motif: 
           <b>&hearts;</b> <b class="foggy">&spades;</b></p>

and the following CSS:

.wrapper {
    position: relative;
    outline: 1px solid blue;
.overlay {
    position: absolute;
    top: 0;
    left: 0;
    background-color: white;
    border: 1px dotted blue;
    width: 400px;

.content p b {
    background-color: black;
    color: white;
    padding: 0 10px;
    opacity: 1.0; /* default value */
.content p b.foggy {
    opacity: 0.4;

.tweak .overlay {
    z-index: 1;

Basically, I have a wrapper with two child div’s, .overlay and .content. Note that the overlay is ahead of the content in the code (DOM). If it were after, you would not have seen the problem in the first place.

The content has two bold elements with two different opacity values.

See the basic line in the demo fiddle is at: http://jsfiddle.net/audetwebdesign/DxQZv/

When you enable the overlay, the .foggy element with opacity of 0.4 appears in front of the overlay. The stacking order for this arrangement is, from back to front: the in-flow content with opacity of 1.0 (default), the absolutely positioned overlay, then the element with opacity 0.4.

However, if you explicitly set z-index: 1 to the .overlay (add the .tweak class),
then .overlay gets placed higher in the stacking order.

There are other ways of adjusting the z-index value to get the same effect, but this may be the simplest.


See 9.9.1 Specifying the stack level: the ‘z-index’ property in the CSS2 spec
and 3.2. Transparency: the ‘opacity’ property in the CSS3 Color Module spec.

Technically, adding an opacity value (other than 1.0) to an element creates a new stacking context with z-index of 0, which is also what happens with a positioned element.

However, when two elements have the same z-index, they are painted in the order they appear in the DOM (tree order). In this case, the overlay is painted first followed by the bold element with opacity of 0.4, which is why it appears in front of the overlay.

There is also an earlier question that deals with the same issue:

What has bigger priority: opacity or z-index in browsers?

which I found after I posted my answer.