Joel
Joel

Reputation: 8988

CSS positioning absolute requires relative position for sibling element

I have a simple set up where I have a hamburger style menu that enables an off canvas menu (something like this) that slides the main content to the right.

<div class="layout-wrapper" >
    <div class="layout-menu"></div>

    <header class="layout-header"></header>

    <div class="layout-content"></div>
</div>

So I have a container div: layout-wrapper.

I have the menu: layout-menu, with absolute positioning so that I can put the main content on top of it.

I have the header: layout-header, with fixed positioning so that it always will remain on top when I scroll the content

I have the content: layout-content.

My problem is that the layout-content is not visible unless i add position: relative to it. Why do I have to do that? Have I done a stupid mistake?

Here is a plunker showing the problem. Enable the commented line in the CSS to see what it should look like.

Upvotes: 0

Views: 2195

Answers (3)

Oriol
Oriol

Reputation: 288680

The problem is that .layout-menu is a positioned element:

.layout-menu {
    position: absolute;
}

But .layout-content is not:

.layout-content {
    position: static; /* default value */
}

According to CSS 2.1 spec,

Each box belongs to one stacking context. Each box in a given stacking context has an integer stack level, which is its position on the z-axis relative to other boxes in the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. [...]

Each stacking context consists of the following stacking levels (from back to front):

  1. the background and borders of the element forming the stacking context.
  2. the stacking contexts of descendants with negative stack levels.
  3. a stacking level containing in-flow non-inline-level descendants.
  4. a stacking level for floats and their contents.
  5. a stacking level for in-flow inline-level descendants.
  6. a stacking level for positioned descendants with 'z-index: auto', and any descendant stacking contexts with 'z-index: 0'.
  7. the stacking contexts of descendants with positive stack levels.

That means that .layout-menu, which falls in the stacking level 6, will be displayed in front of .layout-content, which falls in the stacking level 3.

However, if you use

.layout-content {
    position: relative;
}

Now .layout-content will fall in the stacking level 6 too.

Then,

Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.

Therefore, since .layout-content comes after .layout-menu in the document tree, .layout-content will be displayed in front of .layout-menu.

Upvotes: 1

mxpln
mxpln

Reputation: 91

It's not a mistake, you have to set position: relative for the layout-content so it can overlap layout-menu.

In your Off Canvas Menu example the content has also a position: relative.

Upvotes: 1

Anubhav
Anubhav

Reputation: 7218

This is because an element needs to have a position property other than static (which is the default) for the z-index property to work. This means it will not only work with position: relative. it will also work with position: absolute and position: fixed.

Give this a read to understand z-index better

Upvotes: 1

Related Questions