Please see this very simple snippet to illustrate my question below:
#container {
position: relative;
padding: 20px;
border: 2px solid gray;
}
#back {
position: absolute;
top: 0;
bottom: 50%;
left: 0;
right: 0;
background-color: #bbb;
}
<div class="col-sm-12" id="container">
<div id="back"></div>
<h1>Some Text</h1>
</div>
The h1 tag is after the back element, in the HTML code.
As I don't change its position property, it must be static.
And, as far as I know, static elements are positioned according to the flow of the page.
So… Why is the absolute-positioned div is shown above its sibling h1?
I am expecting to see it behind the h1 since it comes first.
Note that I know how to correct this behaviour, I'm just asking why!
Snippet with correction:
#container {
position: relative;
padding: 20px;
border: 2px solid gray;
}
#back {
position: absolute;
top: 0;
bottom: 50%;
left: 0;
right: 0;
background-color: #bbb;
}
/* Adding the below corrects this behaviour */
h1 {
position: relative;
}
<div class="col-sm-12" id="container">
<div id="back"></div>
<h1>Some Text</h1>
</div>
… And why using position: relative on the h1 corrects this behaviour?
This is how the painting order works. As described here you have the following order:
For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block
equivalent:
In this step you will print the background and border of the h1 element
Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:
In this complex step you will print the content of the h1 element
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
All positioned descendants with 'z-index: auto'
And in this step you will print the positioned element #back; thus it will be on the top of h1 even if in the DOM it's before.
In other words, we first consider the in-flow elements then the postioned ones. Of course, changing z-index and/or other properties will affect the order because more steps can be consider.
For example adding a negative z-index to #back will trigger this rule:
Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then
tree order.
This will make the #back to be behind since h1 is printed later in the step (4) and (7).
Adding position:relative (or absolute or fixed) to h1 will make it a positioned element so like #back it will trigger the (8) and in this case the tree order will decide.
You may also notice that both background and content are printed in 2 different steps and this may also lead to some non intuitive painting behavior.
Try following. Add style for h1 as follows
#container {
position: relative;
padding: 20px;
border: 2px solid gray;
}
#back {
position: absolute;
top: 0;
bottom: 50%;
left: 0;
right: 0;
background-color: #bbb;
}
#container h1 {
position : relative;
z-index: 1;
}
<div class="col-sm-12" id="container">
<div id="back"></div>
<h1>Some Text</h1>
</div>
static elements do not have a z-index, however, the others default to 0 that is why it stays at the bottom most layer of html and the non-static element covers it. If you wish to show them above, set the position of static elements to relative and give any positive z-index value.
The top, right, bottom, left, and z-index properties have no effect for position: static which is the default value for elements, in your case which h1 tag is. When position is set to relative it creates a new stacking context when the value of z-index is other than auto.
For more read on stacking context:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
Related
This question already has answers here:
Position Relative vs Absolute?
(10 answers)
Difference between style = "position:absolute" and style = "position:relative"
(10 answers)
Closed 2 years ago.
So css positions can be relative and absolute, among other types. Also, usually the parent container is set to position: relative; , and the children is set to position: absolute; to place children relative to its parent.
So when I set the below css example, child1 will be at the bottom left corner of parent container;
.parent{
position: relative;
}
.child1{
position: absolute;
bottom: 0;
left: 0;
}
But, I am wrapping other elements in the child1 class like below, basically child1 is acting like another container relatively positioned in the parent container:
<div class="parent">
<div class='child1'>
<div class-'childOfchild1'>
<h1> Some text or button </h1>
</div>
//some other divs...
</div>
</div>
Where, childOfchild1 will have a position: absolute; so its relative to child1. However, if I turn child1 into relative, it changes its position to the parent. I also tried to set the childOfchild1 to the bottom left corner of child1, but it seems like it doesn't follow the logic I have in mind.
Can someone explain what happens to this? What happens when a relative container is placed within another relative container? Hopefully with examples. Thank you!
An element with position: relative is laid out in normal flow and then shifted from that position the distances specified by the left, right, top and bottom properties.
Ancestors with position: relative have no direct effect on it.
Elements with position: absolute are positioned with respect to the closest ancestor that has position: some-value-that-is-not-static (which includes ancestors with either position: absolute or position: relative).
Positioning is one of the spearheads of CSS. You do well to ask the question because it is not always easy to understand.
To summarize CSS positioning, from the moment you have a position different from static (the default value), your element becomes the new positioning reference for all its direct and indirect children (grandchildren).
There are different potential behaviors of a positioned element though: if we take the case of an element with an absolute position, this is how the browser will position your element:
if its direct parent is positioned (absolute or relative), it will be its positioning reference.
if its direct parent is not positioned, it will go back up to its grandparent, then to its grandparent until it finds a positioned item
otherwise it takes body as a positioning reference (the last positioned parent)
Here is a code example that illustrates some of the cases. You will find in the example squares, the smallest is also the deepest in HTML. (grandson), they all have a semi-transparent color, if it gets dark it means they are overlapping.
The code example with StackOverflow tool
.relative {
position: relative;
}
.absolute {
position: absolute;
}
/* Second */
.ex2 .child {
position: absolute;
bottom: 0;
left: 0;
}
/* Third */
.ex3 .child {
position: relative;
bottom: -10px;
left: 10px;
}
.ex3 .grandchild {
position: absolute;
bottom: 0;
left: 0;
}
/* Fourth */
.ex4 .grandchild {
position: absolute;
bottom: 0;
left: 0;
}
div {
float: left;
margin: 20px;
width: 200px;
height: 200px;
background: rgba(255, 34, 56, .25);
}
div div {
margin: 0;
width: 5em;
height: 5em;
}
div div div {
width: 2em;
height: 2em;
}
<div class=" ex1 normal">
<div class="child">
<div class="grandchild"></div>
</div>
</div>
<div class="ex2 relative">
<div class="child">
<div class="grandchild"></div>
</div>
</div>
<div class="ex3 relative">
<div class="child">
<div class="grandchild"></div>
</div>
</div>
<div class="ex4 relative">
<div class="child">
<div class="grandchild"></div>
</div>
</div>
To summarize: it's all about the question "does this positioned element have a positioned parent, if not, what is the closest positioned parent?"
Do not hesitate to ask further if you have more question.
I'll be glad to help.
Have a nice day!
relatively positioned elements are positioned relative to their normal position "normal flow", and when you adjust the position"top, left,.." it will refer to its normal position as a starting point. so when a relative container positioned inside another relative one, they will not be affected by each other
This question already has an answer here:
How can i make an element from a bottom stacking context stays in front of another higher stacking context? [duplicate]
(1 answer)
Closed 4 years ago.
#twitter{
width:50px;
height:50px;
position: absolute;
right: 0%;
bottom: 0%;
background-color: orange;
z-index:-2;
}
#socialButton {
position: relative;
width: 80px;
height: 80px;
background-color: green;
z-index: 2;
}
#socialButtonRoot {
width: 100px;
height: 100px;
top:20%;
left:20%;
position: absolute;
background-color: hotpink;
z-index: 5;
}
<div id="socialButtonRoot">
<div id="socialButton">
<div id="twitter"></div>
</div>
</div>
This is a simplified version.
In my react project there's component created some Dom nodes, after that I set the styles for them in the CSS file, most styles works fine, but only the z-index style doesn't work, people said we should set the position, yes I've all of them set, but it still doesn't work. So I think it maybe something to do with React or JS, but after I extracted code from React and JS and test it on jsfiddle, z-index still doesn't work. Then, I changed changed the z-index value from 2 to "2" (a string ) , it works, but I can see the value "2" is invalid in the chrome's debug console.
It should be div socialButtonRoot on the front which have highest z-index(5) and div socialButton in the middle which have the second high z-index(2) and div twitter in the back, which have the lowest z-index.
but in the result below, it shows, div twitter on the front and div socialButton in the middle and div socialButtonRoot on the back, which isn't right.
What's the problem here?
See The Stacking Context on MDN.
A stacking context is formed, anywhere in the document, by any element in the following scenarios: … Element with a position value "absolute" or "relative" and z-index value other than "auto".
…
Within a stacking context, child elements are stacked according to the same rules previously explained. Importantly, the z-index values of its child stacking contexts only have meaning in this parent. Stacking contexts are treated atomically as a single unit in the parent stacking context.
The z-index positions an element inside the stacking context it is associated with.
Giving an element position: absolute or position: relative establishes a new stacking context.
Thus #twitter is positioned inside the 3-d box represented by #socialButton.
The z-index is for that box, and not for the entire document.
(And #socialButton is inside #socialButtonRoot in the same way).
If you want A to be rendered below B then either:
Do not position A or
Do not make B a descendant of A
When you place an element inside another element, The child element will display on top of its parent element. This is the same for many nested elements and is the default CSS behaviour. Even setting a higher z-index for the parent than its child element won't change the result. In your example:
<div id="socialButtonRoot">
<div id="socialButton">
<div id="twitter"></div>
</div>
</div>
#socialButtonRoot will be displayed at the bottom. #socialButton will display on top of #socialBuuttonRoot. On top of all, #twitter will show. The z-index will be ignored as it only affects elements of the same level.
I suggest you create a parent <div> and place all three <div>s inside:
#parent {
position: relative;
width: 100px;
height: 100px;
margin-top: 20vh;
margin-left: 20vw;
}
#socialButtonRoot {
position: absolute;
width: 100px;
height: 100px;
z-index: 5;
background-color: hotpink;
}
#socialButton {
position: relative;
width: 80px;
height: 80px;
z-index: 2;
background-color: green;
}
#twitter {
position: absolute;
width: 50px;
height: 50px;
right: 20%;
bottom: 20%;
background-color: orange;
z-index: -2;
}
<div id="parent">
<div id="socialButtonRoot"></div>
<div id="socialButton"></div>
<div id="twitter"></div>
</div>
I used position:relative for the parent <div> so that I can position the children <div>s using percentages. I also used margin-top and margin-left instead of top and left respectively, since the latter don't work with relatively positioned elements.
Since #socialButtonRoot is the largest <div> and is placed in front of the other two, it is the only one that appears when you run the snippet. You can change the z-index for each <div> as you wish
I have this code
#mtitle {
display: inline-block;
margin: 0;
background-color: #000000;
z-index: 999;
}
#tsub {
display: inline-block;
margin-left: 0;
left: 0;
position: absolute;
font-size: 85px;
z-index: 0;
}
<header>
<h1 id="mtitle">Tepid Beans</h1>
<div id="tsub"><span>- Games</span>
</div>
</header>
#tsub is appearing on top of #mtitle, and I do not know why.
z-index works on positioned elements, but with CSS3 elements which are flex items or grid items can use z-index when elements are static
From MDN
The z-index property specifies the z-order of an element and its
descendants. When elements overlap, z-order determines which one
covers the other. An element with a larger z-index generally covers an
element with a lower one.
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 local stacking context.
Applies to positioned elements
Set position:relative to parent header and position:absolute to #mtitle and change z-index value
body {
margin: 0
}
header {
position: relative
}
#mtitle {
display: inline-block;
background-color: #000000;
position: absolute;
margin:0;
z-index: 0;
color: #fff
}
#tsub {
display: inline-block;
left: 0;
position: absolute;
font-size: 85px;
z-index: -1;
background: red
}
<header>
<h1 id="mtitle">Tepid Beans</h1>
<div id="tsub">- Games</div>
</header>
Although other answers posted here solve the problem, they are not entirely correct.
The following statements are false:
z-index only works on positioned elements.
z-index only works on elements that are positioned.
z-index only works on elements which are not position:static ie the default position.
In many cases an element must be positioned for z-index to work. But this is not true for all cases.
Elements that are flex items or grid items can create stacking contexts with z-index, even when position is static (see demo).
In terms of this specific question, the reason #tsub is appearing on top of #mtitle is because:
div#tsub comes after h1#mtitle in the HTML, AND
the z-index property applied to #mtitle is being ignored since #mtitle is not positioned, nor is it a flex or grid item.
Here are two possible solutions:
change z-index: 0 on #tsub to z-index: -1, OR
add position: relative to #mtitle
#mtitle {
display: inline-block;
margin: 0;
background-color: aqua; /* changed for illustration purposes */
z-index: 999;
}
#tsub {
display: inline-block;
margin-left: 0;
left: 0;
position: absolute;
font-size: 85px;
z-index: -1; /* adjustment here */
}
<header>
<h1 id="mtitle">Tepid Beans</h1>
<div id="tsub"><span>- Games</span>
</div>
</header>
z-index only works on elements that are positioned. So if you add position: relative; to #mtitle the z-indexing will work.
concerning the last part of your question,
tsub is appearing on top of #mtitle, and I do not know why.
elements with position: absolute are "taken out" of the regular flow of elements, they don't take up any space in their parent elements (which need a position setting other than static for that to work), they are only anchored to them (= will move with them). But that way they can overlap other elements.
Among several absolutely positioned elements, the z-index will determine which one is on top of another one..
I have DIV container with relative position, and the child with absolute position.
here is my code source:
JSFIDDLE
HTML:
<div class="wrapper">
<h1>Hello</h1>
</div>
CSS
.wrapper {
background: red;
width: 100px;
height: 100px;
position: relative;
}
.wrapper h1 {
color: #333;
position: absolute;
top: 60px;
}
when I put in top 60px, the child element jump to the bottom , normally the container has a relative position so the child element should be under the container not over the container.
Please, someone can explain me why this happen ?
I hope I explained, well my question.
When you have an element with position: absolute that element is placed relatively to its closest positioned parent. A positioned element is any element with position different from static, be it relative, absolute or fixed.
In your case you have a .wrapper with position: relative and h1 inside it with position: absolute, that is why the latter is positioned 60 pixels from the top of its parent.
If you insist of the child element being below the parent, add z-index: -1 to it - http://jsfiddle.net/jt92sedr/4/
This property applies only to positioned elements.
You can check: http://www.barelyfitz.com/screencast/html-training/css/positioning/
The CSS is actually doing what you think (sort of), but there is also (in Firefox, at least) a 21 pixel top margin which pushes the "text" down a bit farther.
Add a rule to remove the top margin:
.wrapper h1 {
color: #333;
position: absolute;
margin-top: 0; /* added this */
top: 60px;
}
Try adding "margin:0; to the h1 element:
.wrapper h1 {
color: #333;
position: absolute;
top: 60px;
margin:0;
display:block;}
Its the other way around, Relative always means relative to the parent. if you want to the child to be set in relation to parent, then make it relative.
the relative in your case on parent does not mean anything.
Are you wondering why 60px from top of the div looks like 80px or 90 px? If this is your question, answer is easy. Browsers add some margin to h1, div and body elements. Simply clear that efect:
body, div, h1 {
margin: 0;
padding: 0;
}
http://jsfiddle.net/14sLb8jg/
Modern browsers, like Chrome and Firefox, are putting a 0.67em margin on top and bottom of h1 tags.
In your case declaring a margin 0 for .wrapper h1 will solve your problem.
Your code should be:
.wrapper {
background: red;
width: 100px;
height: 100px;
position: relative;
}
.wrapper h1 {
color: #333;
position: absolute;
top: 60px;
margin: 0;
}
If you are in doubt, use your browser's inspection / developer tools to find out what default stylings the browser is giving into any given element so you know which one you need to override.
Jsfiddle Example
View on Jsfiddle
I'm trying to get a div to show as a partial background below the inline content of is containing div but above the background of its container. If I set the z-index of just the partial background to -1 it appears behind the background. But if i set the containing divs z-index to 1 while the contained div's z-index is -1 it displays as desired.
Can someone explain to me why this is and if this is a reliable method or not?
.container {
position: relative;
width: 80%;
height: 18px;
padding: 6px 10px;
background: #666;
z-index: 1;
}
.partialbg {
position: absolute;
left: 0px;
top: 0px;
height: 30px;
width: 80%;
background: #0CC;
z-index: -1;
}
<div class="container">Text here
<div class="partialbg"></div>
</div>
The reason this is occurring, is because there is a child and a parent. If you set a z-index on the parent, the child is going to be the same, since the z-index is stacked.
Thus, by setting a z-index of 1 on the parent, the child is now also 1.
It is systematically impossible for the child to be behind the parent, as that doesn't make any sense. However, the text is a sibling of the child. By setting a z-index of -1 on the child, there is essentially no effect between the child and the parent, however since the sibling is effected, the child now goes behind the sibling.