CSS positioning absolute requires relative position for sibling element - css

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.

Related

How does position:absolute change element's overlay properties?

In the example here, I notice if you take away the margin-left:200px from the first section element, it expands its width to fully match the container, but it doesn't go below the nav element, which is has position:absolute. Instead, it's overlaid by the nav element, as if it got a lower z-index. Why is that? Aren't both these elements in the flow of the document? So that means they should come one right after the other right, with the section element appearing under the nav element (this happens when I remove the position:absolute)? Why are they overlaid each other instead?
Aren't both these elements in the flow of the document?
Nope! position: absolute; specifically removes elements from the flow.
As referenced in this answer, absolute positioning uses current positioning context. An element with position: absolute; is still affected by its parent, however it is completely independent of its siblings.

Drop down menu overlapped by lower divs

The issue can be found on my test site: http://udkcf.geekgirlcoding.com/
I created a drop-down menu (the gray box on top). When I expand the menu, the menu items are overlapped by either the branding div or the site content. I tried setting/changing the z-index value, but with no luck.
'z-index'
...
For a positioned box, the 'z-index' property specifies:
The stack level of the box in the current stacking context.
Whether the box establishes a stacking context.
Values have the following meanings:
<integer>
This integer is the stack level of the generated box in the current stacking context. The box also establishes a new stacking context.
auto
The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.
http://www.w3.org/TR/CSS2/visuren.html#propdef-z-index
All of the surrounding elements will have a z-index of 0, meaning that they don't define a new stacking order and will stack in the order they appear.
You can therefore simply apply a z-index of 1 to take the element in question out of the natural stacking order.
This will tell the browser that you want that element to be above every other element
unless there are any following elements with the same z-index value
or there are any elements, which may come before or after, which have a higher z-index value.
.dl-menuwrapper {
z-index: 1;
}
Add the below code in your stylesheet.
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary {
display: block;
z-index: -999;
position: relative;
}

Why is my perspective on body causing FF to not display correctly

I have an element (div) which I position: fixed;. This element should not influence the content flow.
But in a CSS-Theme I use, this rule
body {
perspective: 800;
}
is applied. This causes my element to flow inside my body in Firefox. My body becomes scrollable to the right. (as if I set position: absolute;, but actually I'm using position:fixed)
http://codepen.io/anon/pen/zxWweY
This looks good in Chrome, so what exactly is happening in FF? Is this an expected behaviour?
This is because perspective & transform both establish a containing block for fixed positioned elements (sort of like how relative positioned container does with absolutely positioned descendants). This is stated in the Transforms Module:
For transform
For elements whose layout is governed by the CSS box model, any value
other than none for the transform results in the creation of both a
stacking context and a containing block. The object acts as a
containing block for fixed positioned descendants.
And for perspective:
The use of this property with any value other than none establishes a
stacking context. It also establishes a containing block (somewhat
similar to position: relative), just like the transform property does.
So this means .loading-circle is initally positioned to the top & right of the body (which by itself doesn't cause a scrollbar) but then you transform this element in the X direction by 50% (to the right) and rotate it by 45 degrees.
So when you remove perspective, this element is positioned relative to the viewport (which won't add a scrollbar if elements overflows) but when perspective is added the body becomes the new containing block and since it overflows the body scrollbar is added.

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

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.

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