birderic
birderic

Reputation: 3765

Display fixed position element's child above absolutely positioned overlay

I have a layout containing two columns. The left column scrolls vertically and the right column is fixed. The right column contains multiple sections.

At some point, an overlay will be displayed. I want it to cover all content except for the first section in the right column (<aside class="one">...</aside>).

Right now, when the overlay is displayed it covers everything, including the aside.one element even though it has a higher z-index value.

HTML:

<!-- ... -->

<section id="sidebar">
    <aside class="one">...</aside>
    <aside class="two">...</aside>
</section>

<!-- ... -->

<div class="overlay"></div>

CSS:

#sidebar {
    position: fixed;
}

.one {
    z-index: 3;
}

.overlay {
    bottom: 0;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 2;
}

Here is a jsFiddle illustrating a more complete example of my problem: http://jsfiddle.net/ncSWz/10/

I know I will need to change some of my HTML structure to get this working, but I'm unsure exactly where to start.

Thanks in advance.

Upvotes: 6

Views: 16489

Answers (2)

thgaskell
thgaskell

Reputation: 13226

There's actually a bit of stacking context that's involved in this problem.

The idea is essentially, you need to have both the .overlay and aside.one in the same stacking context. You can accomplish that by moving the .overlay into the #sidebar (since it is position: fixed - this creates a stacking context).

Next, you need to create a couple more nested stacking contexts inside the sidebar. By changing the positioning on aside.one to relative and .overlay to fixed, you create another 2 stacking contexts that allow you to play with z-indexing of the elements.

Finally, you need to change the z-index on #header so that its below the overlay.

  • the root element (HTML),
  • positioned (absolutely or relatively) with a z-index value other than "auto",
  • elements with an opacity value less than 1.
  • on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto"

Source: MDN: The stacking context

Updated jsFiddle: http://jsfiddle.net/ncSWz/17/

HTML

    <section id="sidebar">
        
        <!-- Should be on top of the overlay -->
        <aside class="one">...</aside>
        
        <aside class="two">...</aside>
        
        <!-- Should cover all elements except for aside.one -->
        <div class="overlay"></div>
    </section>

CSS

header {
    z-index: 0;
}

...

.one {
    position: relative;
    width: 100%;
    z-index: 3;
}

.overlay {
    bottom: 0;
    display: none;
    left: 0;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 1;
}

Upvotes: 4

Andrea Ligios
Andrea Ligios

Reputation: 50203

Put position: absolute on both one and two, and set the top of two; since their parent is fixed, they're absolutely positioned to it.

Running Demo

CODE ADDED

.one {
    position: absolute;
}

.two {
    position: absolute;
    top: 25px;
}

Upvotes: 1

Related Questions