Andrew Eisenberg
Andrew Eisenberg

Reputation: 28757

Why is overflow interacting with z-index?

I am trying to understand the rules behind z-index and how it interacts with the overflow property.

I have this html:

<body>
  <div class="cell">
    Here is some text to keep things interesting
    <div class="boxy"></div>
  </div>
</body>

And this css:

.boxy {
  position: absolute;
  z-index: 9999;
  top:70px;
  width: 50px;
  height: 50px;
  background: #0FF;
}

.cell {
  border: 2px solid #F00;
  position: relative;

  /* comment these two lines out and the box appears */
  /* or change them both to 'visible' */
  /* changing only one of them to 'visible' does not work */
  overflow-y: auto;
  overflow-x: auto;
}

I would have expected that the cyan box appears even though it is out of the size of the div.cell because its z-index and its position are set.

However, the only way to make the cyan box appear is to comment out the overflow-x and -y lines.

My question is: How can I make the cyan box appear on the screen while keeping the overflow as either hidden or auto? But more importantly, I'm looking to understand why this is happening. What are the css and layout rules being applied here?

See my Plunkr. This example, is of course a much simplified version of the HTML/CSS I am actually working with.


EDIT There seems to be some confusion in the answers below because I didn't explain things well enough. If you comment the two overflow lines out, you can see that the cyan box appears. It appears outside of the border of .cell. Why does this happen? How can I make the cyan box appear, while still hiding overflow and z-index?

Upvotes: 38

Views: 51352

Answers (5)

DragonLord
DragonLord

Reputation: 6611

Z-indices are local inside their clipping hierarchical parent context. This is very non-intuitive. They have their own z-stack context, which normally parallels that of the enclosure hierarchy. But they're still subject to clipping! Which can be a real pain if you're intuitively expecting the z-indices to be absolute.

Note that some jquery containers, such as accordion, quietly specify overflow: auto. Even if it's not explicitly in your code. (This can be overridden locally after it's found.)

Also note that if overflow-x: visible is set, but overflow-y is set to a non-visible, then the rendering engine quietly internally changes overflow-x to be the same as overflow-y for your amusement. But you found this out already.

You probably should be able to circumvent the unwanted non-"visible" overflow clipping, even with your high z-index, by invoking transform: translate(0,0); [or whatever desired offset, % or pixels] inside the style of the div that you want to levitate. Transform should create a new local z-stack for that element and its children. Which will let you get around an overly-restrictive parent or grandparent.

Upvotes: 1

BoltClock
BoltClock

Reputation: 723598

The reason the cyan box appears only when overflow-x and overflow-y are visible, and disappears otherwise, is simply because the cyan box is overflowing the cell box. overflow: visible simply means "paint this box even if it is overflowing its containing block" — the cell box is the containing block of the cyan box because its position is relative. Any other values of overflow cause overflowing content to be clipped from view. There is nothing special going on here; in particular, the z-index is completely irrelevant and there is no such interaction as the question title alludes to (and there really is no reason to set it to such a huge number unless you're worried about scripts injecting other elements into the cell).

The only way to allow the cyan box to appear while the cell has a non-visible overflow is to remove position: relative from the cell and apply that declaration to the parent of the cell (in your example, it's the body). Like this:

body {
  position: relative;
}

.boxy {
  position: absolute;
  z-index: 9999;
  top: 70px;
  width: 50px;
  height: 50px;
  background: #0FF;
}

.cell {
  border: 2px solid #F00;
  overflow: auto;
}
<div class="cell">
  Here is some text to keep things interesting
  <div class="boxy"></div>
</div>

Upvotes: 20

gevorg
gevorg

Reputation: 5055

Your problem

Your problem is related to cell node that hides boxy when overflow is specified on cell node.

The reason

The reason behind is that boxy with position absolute does not contribute to height of cell and overflow hides it.

Why is it shown without overflow?

By default overflow is visible, which for browser means do not do anything special for overflow functionality and it does not need to render overflow => does not hide boxy.

Upvotes: 1

Gautam Jha
Gautam Jha

Reputation: 1473

The Parent Class cell need to be set it's height. because height of absolute element doesn't affect it;s parent.

 .boxy {
      position: absolute;
      z-index: 9999;
      top:70px;
      width: 50px;
      height: 50px;
      background: #0FF;

    }

    .cell {
      border: 2px solid #F00;
      position: relative;

      /* comment these two lines out and the box appears */
      /* or change them both to 'visible' */
      /* changing only one of them to 'visible' does not work */
      overflow-y: auto;
      overflow-x: auto;
      min-height: 120px; /* height 70px(Top)+50px*/
    }

Upvotes: 2

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Absolute-positioned elements do not contribute to the dimensions of their parents.

Therefore, the .cell DIV has no content that affects its dimensions, making it 100% wide by 0px high.

To make the element appear, you'll have to add a height to .cell that will encompass the DIV, in this case 120px (70px top + 50px height).

Upvotes: 4

Related Questions