I know absolute positioning breaks normal flow but since the order in HTML is absolute element first then static one, I was expecting it to be reflected in the display order too.
.absolute
{
position: absolute;
width: 100px;
height: 100px;
background-color: black;
}
.static
{
background-color: red;
height: 20px;
width: 400px;
}
<div>
<div class="absolute"></div>
<div class="static"></div>
</div>
The reason I need this is because I want to display a sliding menu (the '.absolute' div) which slides from bottom to up and appears like it's coming from the back of the '.static' div.
The container div will obviously need to have 'overflow: visible'.
Any idea how to accomplish this?
Maybe another technique is needed? Like CSS clip?
As per section 9.9.1 Specifying the stack level: the 'z-index' property of CSS 2.2:
Within each stacking context, the following layers are painted in back-to-front order:
the background and borders of the element forming the stacking context.
the child stacking contexts with negative stack levels (most negative first).
the in-flow, non-inline-level, non-positioned descendants.
the non-positioned floats.
the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
the child stacking contexts with positive stack levels (least positive first).
Third one in list is position:static and 6-th is position:absolute. I marked them for you.
Edit, based on your question edits:
In order to fix your issue (which is what you should have asked in the first place, IMHO) you need to
apply position:relative; to your .static div, bringing it to the same level with the position:absolute one. (Now the'll both be positioned).
If the one you want on top is not the last in DOM, you also need to give it a positive z-index, bigger than it's siblings'. Normally they are rendered back-to-top.
Both the answers above give the adequate explanation to the situation you are facing. Given the problem at hand you can use this solution. Just add position:relative to the static div.
.absolute
{
position: absolute;
width: 100px;
height: 100px;
background-color: black;
}
.static
{
background-color: red;
height: 20px;
width: 400px;
position: relative;
}
<div>
<div class="absolute"></div>
<div class="static"></div>
</div>
Absolute position means you can put such div anywhere, and it won’t affect or be affected by any other element in the flow.
Absolutely positioned element is completly removed from the normal flow.
To obtain the effect you want, you might use z-index and position: relative and position: absolute.
Related
Today after hours of debugging, I learned in the hard way that:
A parent element is never able to cover (stack on top of) its child element if the parent has a z-index of any value, no matter how you change the child's CSS
How can I understand this behavior by logic? Is it in the specs?
.container {
width: 600px;
height: 600px;
background-color: salmon;
position: relative;
z-index: 99;
padding-top: 10px;
}
h1 {
background-color: pink;
position: relative;
z-index: -1;
font-family: monospace;
}
<div class="container">
<h1>1. I can never be covered by parent if my z-index is positive.</h1>
<h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>
There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.
Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
It's clear from this that we first paint elements with negative z-index at step (3), then the one with z-index equal to 0 at step (8), and finally the ones with positive z-index at step (9), which is logical. We can also read in another part of the specification:
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. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.
To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index will do this:
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.
Now we have all the information to better understand each case. If the parent element has a z-index value of something other than auto, then it will create a stacking context, thus the child element will be painted inside whatever their z-index is (negative or positive). The z-index of the child element will simply tell us the order of painting inside the parent element (this covers your second point).
Now, if only the child element has a positive z-index and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.
There is no way to have the parent above a child element when setting a positive z-index to the child. Also there is no way to have the parent above the child if we set a z-index to the parent element different from auto (either positive or negative).1
The only case where we can have a child below its parent is to set a negative z-index on the child element and keep the parent at z-index: auto, thus this one will not create a stacking context and following the painting order the child will be painted first.
In addition to z-index, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.
Some important facts that we can conclude from the above:
Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref
1: there is some hacky ways if we consider the use of 3D transformation.
Example with an element going under its parent element even if this one has a z-index specified.
.box {
position:relative;
z-index:0;
height:80px;
background:blue;
transform-style: preserve-3d; /* This is important */
}
.box > div {
margin:0 50px;
height:100px;
background:red;
z-index:-1; /* this will do nothing */
transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
<div></div>
</div>
Another example where we can place an element between two elements in another stacking context:
.box {
position: relative;
transform-style: preserve-3d;
z-index: 0;
height: 80px;
background: blue;
}
.box>div {
margin: 0 50px;
height: 100px;
background: red;
z-index: 5;
transform: translateZ(2px);
}
.outside {
height: 50px;
background: green;
margin: -10px 40px;
transform: translateZ(1px);
}
body {
transform-style: preserve-3d;
}
<div class="box">
<div></div>
</div>
<div class="outside"></div>
We can also have some crazy stacking order like below:
.box {
width: 100px;
height: 100px;
position: absolute;
}
body {
transform-style: preserve-3d;
}
<div class="box" style="top:100px;left:50px;background:red;"></div>
<div class="box" style="top: 50px;left: 115px;background:blue;"></div>
<div class="box" style="top: 101px;left: 170px;background:green;"></div>
<div class="box" style="top: 175px;left: 115px;background:purple;transform: rotateY(-1deg);"></div>
We should note that using such hack may have some side effect due to the fact that transform-style, perspective and transform will affect position:absolute/fixed element. Related: Why does applying a CSS-Filter on the parent break the child positioning?
A good way to think about this is that each parent contains its own stacking context. Sibling elements share a parent's stacking order and may, therefore, overlap each other.
A child element is ALWAYS getting a stacking context based on its parent. Hence the need for a negative z-index value to push the child "behind" its parent (0) stacking context.
The only way to remove an element from its parent's context is using position: fixed since this essentially forces it to use the window for context.
The Mozilla documentation does say
The z-index CSS property sets the z-order of a positioned element and its descendants or flex items.
Here's some additional logic from another StackOverflow article relating to children vs descendants.
How can I understand this behavior by logic?
For me it's hard to understand your problem by logic. A parent contains its children. A bowl can be covered by another bowl. But you can't cover the soup with the bowl unless you put the soup out of the bowl.
z-Index sets the order for overlapping elements. A parent can't overlap its child.
ImhO that's perfectly logical.
This question already have a good answer, but I'd like to add one more thing: If you found this question, there's a good chance that your problem should be solved by overflow, not z-index.
Today after hours of debugging, I learned in the hard way that:
A parent element is never able to cover (stack on top of) its child element if the parent has a z-index of any value, no matter how you change the child's CSS
How can I understand this behavior by logic? Is it in the specs?
.container {
width: 600px;
height: 600px;
background-color: salmon;
position: relative;
z-index: 99;
padding-top: 10px;
}
h1 {
background-color: pink;
position: relative;
z-index: -1;
font-family: monospace;
}
<div class="container">
<h1>1. I can never be covered by parent if my z-index is positive.</h1>
<h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>
There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.
Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
It's clear from this that we first paint elements with negative z-index at step (3), then the one with z-index equal to 0 at step (8), and finally the ones with positive z-index at step (9), which is logical. We can also read in another part of the specification:
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. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.
To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index will do this:
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.
Now we have all the information to better understand each case. If the parent element has a z-index value of something other than auto, then it will create a stacking context, thus the child element will be painted inside whatever their z-index is (negative or positive). The z-index of the child element will simply tell us the order of painting inside the parent element (this covers your second point).
Now, if only the child element has a positive z-index and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.
There is no way to have the parent above a child element when setting a positive z-index to the child. Also there is no way to have the parent above the child if we set a z-index to the parent element different from auto (either positive or negative).1
The only case where we can have a child below its parent is to set a negative z-index on the child element and keep the parent at z-index: auto, thus this one will not create a stacking context and following the painting order the child will be painted first.
In addition to z-index, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.
Some important facts that we can conclude from the above:
Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref
1: there is some hacky ways if we consider the use of 3D transformation.
Example with an element going under its parent element even if this one has a z-index specified.
.box {
position:relative;
z-index:0;
height:80px;
background:blue;
transform-style: preserve-3d; /* This is important */
}
.box > div {
margin:0 50px;
height:100px;
background:red;
z-index:-1; /* this will do nothing */
transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
<div></div>
</div>
Another example where we can place an element between two elements in another stacking context:
.box {
position: relative;
transform-style: preserve-3d;
z-index: 0;
height: 80px;
background: blue;
}
.box>div {
margin: 0 50px;
height: 100px;
background: red;
z-index: 5;
transform: translateZ(2px);
}
.outside {
height: 50px;
background: green;
margin: -10px 40px;
transform: translateZ(1px);
}
body {
transform-style: preserve-3d;
}
<div class="box">
<div></div>
</div>
<div class="outside"></div>
We can also have some crazy stacking order like below:
.box {
width: 100px;
height: 100px;
position: absolute;
}
body {
transform-style: preserve-3d;
}
<div class="box" style="top:100px;left:50px;background:red;"></div>
<div class="box" style="top: 50px;left: 115px;background:blue;"></div>
<div class="box" style="top: 101px;left: 170px;background:green;"></div>
<div class="box" style="top: 175px;left: 115px;background:purple;transform: rotateY(-1deg);"></div>
We should note that using such hack may have some side effect due to the fact that transform-style, perspective and transform will affect position:absolute/fixed element. Related: Why does applying a CSS-Filter on the parent break the child positioning?
A good way to think about this is that each parent contains its own stacking context. Sibling elements share a parent's stacking order and may, therefore, overlap each other.
A child element is ALWAYS getting a stacking context based on its parent. Hence the need for a negative z-index value to push the child "behind" its parent (0) stacking context.
The only way to remove an element from its parent's context is using position: fixed since this essentially forces it to use the window for context.
The Mozilla documentation does say
The z-index CSS property sets the z-order of a positioned element and its descendants or flex items.
Here's some additional logic from another StackOverflow article relating to children vs descendants.
How can I understand this behavior by logic?
For me it's hard to understand your problem by logic. A parent contains its children. A bowl can be covered by another bowl. But you can't cover the soup with the bowl unless you put the soup out of the bowl.
z-Index sets the order for overlapping elements. A parent can't overlap its child.
ImhO that's perfectly logical.
This question already have a good answer, but I'd like to add one more thing: If you found this question, there's a good chance that your problem should be solved by overflow, not z-index.
Today after hours of debugging, I learned in the hard way that:
A parent element is never able to cover (stack on top of) its child element if the parent has a z-index of any value, no matter how you change the child's CSS
How can I understand this behavior by logic? Is it in the specs?
.container {
width: 600px;
height: 600px;
background-color: salmon;
position: relative;
z-index: 99;
padding-top: 10px;
}
h1 {
background-color: pink;
position: relative;
z-index: -1;
font-family: monospace;
}
<div class="container">
<h1>1. I can never be covered by parent if my z-index is positive.</h1>
<h1>2. Even when my z-index is nagative, I still can never be covered if my parent has any z-index at all.</h1>
</div>
There are two important things you need to know: the painting order and the stacking context. If you refer to the specification, you can find how and when elements are painted.
Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
It's clear from this that we first paint elements with negative z-index at step (3), then the one with z-index equal to 0 at step (8), and finally the ones with positive z-index at step (9), which is logical. We can also read in another part of the specification:
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. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked bottom-to-top according to document tree order.
To understand when each element will be painted you need to know its stacking context and its stack level inside this stacking context (defined by z-index). You also need to know whether that element establishes a stacking context. This is the tricky part, because setting z-index will do this:
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.
Now we have all the information to better understand each case. If the parent element has a z-index value of something other than auto, then it will create a stacking context, thus the child element will be painted inside whatever their z-index is (negative or positive). The z-index of the child element will simply tell us the order of painting inside the parent element (this covers your second point).
Now, if only the child element has a positive z-index and we set nothing on the parent element, then considering the painting order, the child will be painted later (in step (9)) and the parent in step (8). The only logical way to paint the parent above is to increase the z-index, but doing this will make us fall into the previous case where the parent will establish a stacking context and the child element will belong to it.
There is no way to have the parent above a child element when setting a positive z-index to the child. Also there is no way to have the parent above the child if we set a z-index to the parent element different from auto (either positive or negative).1
The only case where we can have a child below its parent is to set a negative z-index on the child element and keep the parent at z-index: auto, thus this one will not create a stacking context and following the painting order the child will be painted first.
In addition to z-index, there are other properties that create a stacking context. In case you face an expected stacking order, you need to consider those properties, too, in order to see if there is a stacking context created.
Some important facts that we can conclude from the above:
Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
Each stacking context is completely independent of its siblings: only descendant elements are considered when stacking is processed.
Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context. ref
1: there is some hacky ways if we consider the use of 3D transformation.
Example with an element going under its parent element even if this one has a z-index specified.
.box {
position:relative;
z-index:0;
height:80px;
background:blue;
transform-style: preserve-3d; /* This is important */
}
.box > div {
margin:0 50px;
height:100px;
background:red;
z-index:-1; /* this will do nothing */
transform:translateZ(-1px); /* this will do the magic */
}
<div class="box">
<div></div>
</div>
Another example where we can place an element between two elements in another stacking context:
.box {
position: relative;
transform-style: preserve-3d;
z-index: 0;
height: 80px;
background: blue;
}
.box>div {
margin: 0 50px;
height: 100px;
background: red;
z-index: 5;
transform: translateZ(2px);
}
.outside {
height: 50px;
background: green;
margin: -10px 40px;
transform: translateZ(1px);
}
body {
transform-style: preserve-3d;
}
<div class="box">
<div></div>
</div>
<div class="outside"></div>
We can also have some crazy stacking order like below:
.box {
width: 100px;
height: 100px;
position: absolute;
}
body {
transform-style: preserve-3d;
}
<div class="box" style="top:100px;left:50px;background:red;"></div>
<div class="box" style="top: 50px;left: 115px;background:blue;"></div>
<div class="box" style="top: 101px;left: 170px;background:green;"></div>
<div class="box" style="top: 175px;left: 115px;background:purple;transform: rotateY(-1deg);"></div>
We should note that using such hack may have some side effect due to the fact that transform-style, perspective and transform will affect position:absolute/fixed element. Related: Why does applying a CSS-Filter on the parent break the child positioning?
A good way to think about this is that each parent contains its own stacking context. Sibling elements share a parent's stacking order and may, therefore, overlap each other.
A child element is ALWAYS getting a stacking context based on its parent. Hence the need for a negative z-index value to push the child "behind" its parent (0) stacking context.
The only way to remove an element from its parent's context is using position: fixed since this essentially forces it to use the window for context.
The Mozilla documentation does say
The z-index CSS property sets the z-order of a positioned element and its descendants or flex items.
Here's some additional logic from another StackOverflow article relating to children vs descendants.
How can I understand this behavior by logic?
For me it's hard to understand your problem by logic. A parent contains its children. A bowl can be covered by another bowl. But you can't cover the soup with the bowl unless you put the soup out of the bowl.
z-Index sets the order for overlapping elements. A parent can't overlap its child.
ImhO that's perfectly logical.
This question already have a good answer, but I'd like to add one more thing: If you found this question, there's a good chance that your problem should be solved by overflow, not z-index.
Is there any documentation that specifies what the default behaviour is for an element with position fixed, inside an element with position relative, absolute or static?
.parent {
position: relative; /* or absolute/static */
height: 200px;
width: 200px;
top: 30px;
left: 50px;
background-color: red;
}
.child {
position: fixed;
height: 100px;
width: 100px;
left: 10px;
top: 20px;
background-color: blue;
}
<div class='parent'>
<div class='child'></div>
</div>
My own experiance is that it is positioned relative to the browser viewport (unless transform is used, or left/top is omitted in child), but how can i justify that this should always will be the case? How do i know if any browsers renders this differently? Perhaps positioning the child relative to the parent, or maybe not showing the element at all...
The position of the parent element or any ancestor is irrelevant when it comes to position:fixed. From the specification:
Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport.
But there is some special cases where the containing block can change. It happens when using filter like I explained here, transform like explained here and sometimes will-change (explained here)
Concerning the use of top/left/bottom/right you need to consider the static position. If you don't set any of those values the browser will consider the static position to place the element. Still From the specification:
For the purposes of this section and the next, the term "static position" (of an element) refers, roughly, to the position an element would have had in the normal flow. More precisely ...
A position:fixed element always consider the viewport as its containing block (the reference for its placement) unless there is some particular properties used in a upper level (transform, filter, etc). The position of that element is either defined by top/left/right/bottom or by the static position like described in the specification.
Related question to get more details about the static position: Why aren't my absolutely-positioned elements located where I expect?
This question already has an answer here:
How to reverse the order of nested child elements
(1 answer)
Closed 8 years ago.
I am trying to figure out why a child element does not appear behind its parent element when given a lower z-index value than the parent. It only appears to work when you do not touch the parent's default z-index value.
Here's a basic example.
HTML:
<div class="a">
A DIV
<div class="b">
B DIV
</div>
</div>
CSS:
.a {
position: relative;
background: #eaeaea;
height: 200px;
width: 200px;
z-index: 20;
}
.b {
position: relative;
z-index: -20;
background: #d6d6d6;
height: 100px;
width: 100px;
}
Link to example:
http://jsfiddle.net/V4786/2/
Any thoughts would be appreciated.
It only appears to work when you do not touch the parent's default z-index value.
This is because setting z-index to something other than its default auto on a positioned element causes it to establish a new stacking context, and an element cannot be positioned behind the element that created the stacking context that it's in. (An element cannot be positioned behind the root stacking context, for example, as Scotty C. states.)
When you leave the z-index of the parent element untouched, the parent and the child both participate in the same stacking context, which is the one established by the root element, or the root stacking context. This is why you can position the child behind the parent in such a case.
All the details can be found in the spec, but that's the gist of it given your question.
Because Z-Index levels are relative to their parents. This is the same as saying "Why doesn't the element show behind the browser window if I set a negative Z-Index?" Generally if you're going to do something funky with levels, you might consider having two sibling elements with absolute or relative positioning. Although that approach is sometimes considered "hacky."