Z-index: How to make nested elements appear underneath their parent element - css

This fiddle should demonstrate the issue:
http://jsfiddle.net/5sqxQ/2/
I want the sub menu to appear underneath the parent menu. I was then was looking to extend this with JavaScript to slide the menu from underneath on hover of the parent li element.
Not fussed about the JavaScript but can't figure out how to style the elements to achieve the desired layering.

It doesn't work because you are applying a z-index to the parent element which makes the child element stack relative to the other elements within the parent.
Once you assign an element a value for
z-index (other than auto), that
element establishes its own local
stacking context. This means that all
of the element's descendants have
their own stacking order, relative to
the ancestor element.
So if the parent has z-index: 9 and the child is z-index: 8, it's kind of like assigning a z-index of 9, 8
See the article here for a better explanation.
If you remove the z-index on the parent and set the sibling element to z-index: -1, that should work. I'm not sure about all browsers, but it works in Chrome anyway.
Here is the updated fiddle
Hope that helps.

You don't.
Instead, make the a be the "Sign In" "button".
Something like this: http://jsfiddle.net/5sqxQ/15/

Try setting the parent and siblings containers position to relative.
Its worked for me before.

Look at the rules below for how elements are stacked and you can easily come up with your own solution.
ex. Like thirtydot said, give "Sign In" .users > li > a a position, relative or absolute, and z-index: 1
The Stacking order and stacking context rules below are from this link
Stacking Order within a Stacking Context
The order of elements:
The stacking context’s root element (the <html> element is the only stacking context by default, but any element can be a root element for a stacking context, see rules below)
You cannot put a child element behind a root stacking context element
Positioned elements (and their children) with negative z-index values (higher values are stacked in front of lower values; elements with the same value are stacked according to appearance in the HTML)
Non-positioned elements (ordered by appearance in the HTML)
Positioned elements (and their children) with a z-index value of auto (ordered by appearance in the HTML)
Positioned elements (and their children) with positive z-index values (higher values are stacked in front of lower values; elements with the same value are stacked according to appearance in the HTML)
When a Stacking Context is Formed
When an element is the root element of a document (the <html> element)
When an element has a position value other than static and a z-index value other than auto
When an element has an opacity value less than 1
Several newer CSS properties also create stacking contexts. These include: transforms, filters, css-regions, paged media, and possibly others. See https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
As a general rule, it seems that if a CSS property requires rendering in an offscreen context, it must create a new stacking context.

Related

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.
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):
the background and borders of the element forming the stacking
context.
the stacking contexts of descendants with negative stack levels.
a stacking level containing in-flow non-inline-level descendants.
a stacking level for floats and their contents.
a stacking level for in-flow inline-level descendants.
a stacking level for positioned descendants with 'z-index: auto', and any descendant stacking contexts with 'z-index: 0'.
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.
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
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.

opacity value less than 1 and stacking without z-index

MDN - Stacking without z-index states that when no element in a page has a z-index, elements are stacked in this order:
Background and borders of the root element
Descendant blocks in the normal flow, in order of appearance (in HTML)
Descendant positioned elements, in order of appearance (in HTML)
But that seems not the case when an element of opacity less than 1 is involved:
http://jsfiddle.net/pbQfY/2/
Is it safe to assume that the real order is the following?
Background and borders of the root element
Descendant blocks in the normal flow, in order of appearance (in HTML)
Descendant positioned elements and descendant elements that create stacking context, in order of appearance (in HTML)
Looks like that MDN article is just the basic version of the actual stacking contexts explanation, which is also touched on in the visual formatting module. However, this particular gotcha is from the CSS color module (emphasis mine):
Since an element with opacity less than 1 is composited from a single
offscreen image, content outside of it cannot be layered in z-order
between pieces of content inside of it. For the same reason,
implementations must create a new stacking context for any element
with opacity less than 1. If an element with opacity less than 1 is
not positioned, implementations must paint the layer it creates,
within its parent stacking context, at the same stacking order that
would be used if it were a positioned element with ‘z-index: 0’ and
‘opacity: 1’. If an element with opacity less than 1 is positioned,
the ‘z-index’ property applies as described in [CSS21], except that
‘auto’ is treated as ‘0’ since a new stacking context is always
created. See section 9.9 and Appendix E of [CSS21] for more
information on stacking contexts. The rules in this paragraph do not
apply to SVG elements, since SVG has its own rendering model ([SVG11],
Chapter 3).

possible to set z-index rules which only affect child elements of a certain div?

Is it possible to set z-index that only applies to a certain 'scope', such as only affecting children of a certain element.
I've got an containerDiv with z-index 0. It contains a bunch of circles which should be placed on top of eachother in various depths, but I don't want them to affect any other elements on the page.
I've got a bunch of other elements on the page (popups, dropdowns etc) which have z-index 1, and I would like them to be placed on top of the containerDiv and all of it's childelements.
Since I'm lazy I'd preferably want to avoid having to adjust these element's z-index values based on the circle with the highest z-index...
Much be awesome if there was some way that all other elements could view the containerDiv and all it's children as having the same z-index.
Is this possible to achieve with css?
The answer depends on whether or not your other elements are descendants of the containerDiv or not. To answer the question: Yes, it's almost certainly possible, given a bit of shuffling of the markup.
But what you need to understand is the concept of stacking context:
http://www.w3.org/TR/CSS2/visuren.html#layers
Stacking context is not inherited the way other properties are: "A stacking context is atomic from the point of view of its parent stacking context; boxes in other stacking contexts may not come between any of its boxes." It's not like every element on the page with z-index:2 will be behind everything on the page with z-index:4. Z-index (combined with a position declaration) is typically (though not exclusively) used to resolve the stacking order when two elements share a containing element.

When do nested child elements expand their parent elment?

In many places I have put elmeents nested in other elements. I can't deduce when a child element causes the parent element to expand. I don't have any code to post as this is a general conceptual question so that I can design as needed.
The first thing that you should understand is the CSS Box Model. That will help you understand how properties of an element cause it to have the size and dimensions that it has. Another good resource is here.
To answer your main question in the most simple manner (and being very general):
Block level elements take up as much width as possible (obeying their CSS width rule). Their height is dependent on their content and the CSS height property.
Elements like div, p, and ul are all block.
These will generally cause your parent element to expand.
Inline level elements will continue to flow together in a line, filling up only as much width and height as necessary.
Elements like span, em, strong are all inline.
These will cause your parent element to expand only when there are enough of them on the same line to warrant another line.
There are many ways to tweak the display of elements with CSS.
Get firebug for firefox. You can browse the DOM (the HTML structure of the page) and it will highlight elements according to how the "browser's eye" sees them (versus how they look aesthetically).
A few general rules of thumb:
Children will expand their parent's height as long as they're not floated or absolutely positioned, but...
You can "clear" a series of floated images http://www.quirksmode.org/css/clearing.html to make the parent element expand
If you use top positioning for a relatively positioned child element, the browser will still see that element in the exact same place. In other words the height of the parent element will stay the same regardless of where the child is relatively positioned to.
Using positive or negative margins on a child that is display: block will add or subtract height from its parent

position: relative appearing over position:absolute

Having a strange issue in IE7. In a number of spots, I have a DIV which has position: absolute on it (faux dropdown) whenever there is something behind it which has position: relative the relative positioned item will show through the other div.
Relativly positioned item does not have any z-index set, while the absolutely positioned item (the one I want on top) has a z-index of 1000.
http://skitch.com/louiswalch/dub5h/microsoft-windows-vista
I suspect you've already tried it, but set a z-index on your relatively positioned element that's lower than your absolutely positioned element's z-index as the first test.
If that doesn't work, you need to make sure both elements are in the same stacking context. In IE, whenever you apply the position CSS rule to an element, it generates a new stacking context within that element. That means that z-index will only be properly respected within that element's children and children in other stacking contexts with lower z-indexes may still stack above.
In your case, you either need to put the dropdown and button in the same stacking context or apply z-index to the 2 elements that are generating their separate stacking contexts.

Resources