Static positioned elements affect Absolute position of subsequent sibling elements - html

I understand that any element with position: absolute will be positioned relative to the nearest ancestor with a positional attribute such as absolute or relative. This is mentioned in various answers for example here. Also on the w3schools site here...
An element with position: absolute; is positioned relative to the
nearest positioned ancestor (instead of positioned relative to the
viewport, like fixed).
However, inserting a static element appears to disrupt this rule and shifts the absolute element. I'd like to understand why that happens. See code snippet below.
If the static element is chaged to absolute, the subsequent elements are displayed as expected (according to the nearesst positional ancestor rule).
div.relative {
position: relative;
width: 440px;
height: 600px;
border: 3px solid #73AD21;
}
div.static {
position: static;
width: 200px;
height: 100px;
border: 3px solid #73ADff;
}
div.absolute {
position: absolute;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
}
div.absolute2 {
left:210px;
position: absolute;
width: 200px;
height: 100px;
border: 3px solid #ffAD21;
}
<div class="relative">This div element has position: relative;
<div class="static">This div element has position: static</div>
<div class="absolute">This div element has position: absolute, but is positioned relative to the preceding static element, not the first positional ancestor.;</div>
<div class="absolute2">This div element also has position: absolute;</div>
</div>

As this answer explains, if there is no (top, left, right, bottom) attributes the position: absolute element will be positioned by default as if it was part of the normal flow , this is helpful in case you want to maintain a position: absolute next to its sibling like a tool tip would, and manipulate it with margin property, let say:
margin-top:-40px;
margin-left:30px;
but if you set any (top,left,right, bottom), this will reset the default position and will be relative to the parent.
top:0

When W3Schools (and the CSS spec) says that an element is "positioned relative to" something, it is never referring to the element's siblings. It's referring to the element's containing block.
The reason a non-positioned element (position: static) affects the layout of subsequent absolutely positioned elements with auto offsets is because absposed elements with auto offsets will assume their static position (see this answer as well as this one RenzoCC links to), and an element's static position, by nature, is influenced by the layout of surrounding elements, especially preceding siblings.
What absolutely positioning an element without changing any of its offsets does, is cause elements that follow it to be laid out as if that element itself were not there. This is what taking an element out of the flow means.

Static position doesn't affect the Absolute position when it comes to the ancestor position which "position: relative".
But the "position: absolute" has a power to position itself whenever you want inside of the (see the additional code I made) "position: relative;" while the "position: static" don't have the ability to used the Top, Right, Bottom and Left because is it a default position where it is only located at the left side.
div.relative {
position: relative;
width: 440px;
height: 600px;
border: 3px solid #73AD21;
}
div.static {
position: static;
width: 200px;
height: 100px;
border: 3px solid #73ADff;
}
div.absolute {
position: absolute;
width: 200px;
height: 100px;
border: 3px solid #73AD21;
/* Absolute Location inside the Relative Position */
top: 0;
left: 0;
}
div.absolute2 {
left:210px;
position: absolute;
width: 200px;
height: 100px;
border: 3px solid #ffAD21;
/* Absolute Location inside the Relative Position */
top: 0;
}
<div class="relative">This div element has position: relative;
<div class="static">This div element has position: static</div>
<div class="absolute">This div element has position: absolute, but is positioned relative to the preceding static element, not the first positional ancestor.;</div>
<div class="absolute2">This div element also has position: absolute;</div>
</div> <!-- / .relative -->

Related

How will absolute positioning search for "relative" in nested div's?

I'm trying to understand how nested divs works. I know that a "position absolute" search for a "position relative". But if we have a "position absolute" inside another "position absolute", what will it use as "position relative".
.box {
border: 2px solid black;
width: 500px;
height: 500px;
position: relative;
}
.box1 {
position: absolute;
width: 220px;
height: 220px;
border: 2px solid black;
background-color: red;
bottom: 25%;
right: 25%;
}
.box2 {
position: absolute;
height: 70px;
width: 70px;
border: 2px solid black;
background-color: green;
left: 10%;
bottom: 10%;
}
<div class="box">
<div class="box1">
<div class="box2"></div>
</div>
</div>
It looks like in the result that box2 is absolute relative to box1. But shouldn't it be box, which is the first parent with "position relative"? Can anybody give an explanation of the mechanics?
I know that a "position absolute" search for a "position relative".
This is misconception.
An absolutely positioned element is positioned with respect to its closest positioned ancestor.
An element is positioned if it has any computed position property value that is not static.
This can be relative, absolute, fixed, or sticky.
position: relative is not a special case for this. It is just a positioning scheme that makes an element positioned without taking it out of normal flow. This makes it a popular choice for making an element the context for some absolute positioning without having side effects on the position of that element.

Positioning a nested DIV relative to the page and not the first positioned ancestor

Is there any way to position a nested DIV (or any other nested HTML element) relative to the page (so 0,0 would put it at the top left of the page) when it has a positioned ancestor, without using javascript.
Using position:fixed won't work because this positions it relative to the viewport, so it does not move if the page is scrolled.
Using position:absolute won't work since I am asking about a nested DIV with a positioned ancestor. This would cause the position will be relative to the positioned ancestor.
No, that can't be done without script ...
... unless the outer element's left/top position is known/fixed, like in this example
.nr1,
.nr2 {
position: absolute;
width: 300px;
height: 100px;
}
.nr1 {
left: 50px;
top: 50px;
background: red;
}
.nr2 {
left: 0;
top: 0;
background: blue;
margin: -50px 0 0 -50px;
}
<div class="nr1">
<div class="nr2">
</div>
</div>

Why absolutely positioned elements render over previous absolutely positioned element?

In this code,
#parent-div{
background: #B3bEb5;
border: 0.1em solid black;
}
#default{
background: #DBE9F4;
}
#centered{
background: #89CFF0;
width: 50%;
margin: auto;
}
/* text-align: left, right, center, justify */
#centered-text{
text-align: center;
}
/* Absolute Positioning : Positioning Based on the Document */
#top-left-pos{
background: #89CFF0;
border: 0.1em solid black;
position: absolute;
width: 200px;
height: 100px;
}
#bottom-right-tl-parent {
background: #DBE9F4;
position: absolute;
bottom: 0px;
right: 0px;
}
#another-pos{
background: #FF0000;
border: 0.1em solid black;
position: absolute;
width: 190px;
height: 110px;
}
<div id="parent-div">
<div id="default">Default</div>
<div id="centered">Centered</div>
<div id="centered-text">Centered Text</div>
</div>
<!-- Demonstrate Absolute Postioning -->
<div id="top-left-pos">Top Left
<div id="bottom-right-tl-parent">Bottom Right Parent</div>
</div>
<div id="another-pos">Top Right
</div>
absolutely positioned top-left-pos element, positions in next row to centered-text element, whose behaviour similar to static positioned elements.
But,
below is the output,
So, Why every new absolutely positioned element another-posis rendered over previous absolutely positioned element top-left-pos? why another-pos element is not rendered as next block element?
With the above code, am expecting another-pos element to be rendered as shown below,
So, Why every new absolutely positioned element another-posis rendered
over previous absolutely positioned element top-left-pos? why
another-pos element is not rendered as next block element?
"The absolutely positioned element is positioned relative to nearest positioned ancestor(non static). If a positioned ancestor doesn't exist, the initial container is used."
Src: CSS/position
This means that if you have 1 or 10 elements using position: absolute, they all start at the same top/left position (if you omit those values in your css rule).
As such they are also taken out of normal flow, which below sample shows, where yet another div, #another-nonpos, using normal flow starts after the previous normal flowed element.
It also shows that positioned elements have a higher z-index than non positioned, making them stay in a higher layer (on top of).
Further reading about z-index: Understanding CSS z-index
#parent-div{
background: #B3bEb5;
border: 0.1em solid black;
}
#default{
background: #DBE9F4;
}
#centered{
background: #89CFF0;
width: 50%;
margin: auto;
}
/* text-align: left, right, center, justify */
#centered-text{
text-align: center;
}
/* Absolute Positioning : Positioning Based on the Document */
#top-left-pos{
background: #89CFF0;
border: 0.1em solid black;
position: absolute;
width: 200px;
height: 100px;
}
#bottom-right-tl-parent {
background: #DBE9F4;
position: absolute;
bottom: 0px;
right: 0px;
}
#another-pos{
background: #FF0000;
border: 0.1em solid black;
position: absolute;
width: 190px;
height: 110px;
}
#another-nonpos{
background: lime;
height: 200px;
text-align: right
}
<div id="parent-div">
<div id="default">Default</div>
<div id="centered">Centered</div>
<div id="centered-text">Centered Text</div>
</div>
<!-- Demonstrate Absolute Postioning -->
<div id="top-left-pos">Top Left
<div id="bottom-right-tl-parent">Bottom Right Parent</div>
</div>
<div id="another-pos">Top Right
</div>
<div id="another-nonpos">Non absolute
</div>
Because the #top-left-pos has greater value of z-index property
When using position:absolute , the div has nothing to do with the document and and gets the parent level regardless of using z-index. in your case, the bottom-right-tl-parent is the child of top-left-pos, thus increasing z-index value wont effect its level. if you move the bottom-right-tl-parent out of top-left-pos, you will be able to apply your z-index and it will work:
<div id="top-left-pos">Top Left</div>
<div id="bottom-right-tl-parent">Bottom Right Parent</div>
The z-index is initially set to auto and applies on all positioned elements. So as the element with id "top-left-pos" has a specified z-index its value is always higher than auto. So, it always stays on top.
Because both the elements have same z index and you have not specified the left and top parameters.If both of them have same z-index and also no coordinates are specified the second one would be placed over the previous one .
#top-left-pos {
top: 0;
}
Set top property to a number will solve the issue
https://jsfiddle.net/00s3f6gj/

How to make the div inside wrapper bigger than wrapper itself without change the structure

How to make the <div> inside wrapper bigger than wrapper itself without change the structure?
HTML
<div class="page row1">
<div class="home-wrapper row2">
<div class="home-slider row3"></div>
</div>
<div>
CSS
.page { width: 100%; height: 400px; border: 1px solid #000; background: #eee; }
.home-wrapper { width: 90%; height: 400px;border: 1px solid red; background: #ccc; margin: 0 auto;}
.home-slider{ width: 100%; height: 200px; border: 1px solid blue; background:#000; }
http://jsfiddle.net/46vpqmgh/1/
I want the black box is same width with the page <div> without change the structure, using only CSS.
Thanks
Add:
position: absolute to .home-slider to pull it out of the normal flow
top: 0 and left: 0 to .home-slider to position it correctly
position: relative to .page to make it's children absolute positioned elements relative to it
Percentage height and width will be calculated based on the size of .page.
Have a fiddle!
Added CSS
.page {
position: relative;
}
.home-slider {
position: absolute;
left: 0;
top: 0;
}
Read more about the CSS position property over on the MDN
Absolute positioning
Elements that are positioned relatively are still considered to be in the normal flow of elements in the document. In contrast, an element that is positioned absolutely is taken out of the flow and thus takes up no space when placing other elements. The absolutely positioned element is positioned relative to nearest positioned ancestor. If a positioned ancestor doesn't exist, the initial container is used.
In our example above, the nearest positioned "ancestor" is .page
Add the following properties. Looks fair to me.
.home-slider {
/* ... */
z-index: 1;
margin-left: -5%;
position: fixed;
}
Change the following class:
.home-slider {
width: 100%;
height: 200px;
border: 1px solid blue;
background:#000;
position: absolute;/*Add position absolute*/
left: 0;/*Add left to 0*/
}
fiddle

IE6 and IE7 absolute positioned div on top of multiple relative divs

Is it possible to make multiple absolute-positioned divs overlap multiple relative-positioned divs in IE6 & IE7?
See this jsFiddle for more information: http://jsfiddle.net/btker/1/
HTML
<div class="wrapper">
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
<div class="wrapper">
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
CSS
.wrapper{
height: 100%;
width: 100%;
}
.relative_div {
height: 75px;
width: 200px;
border: 1px solid #000;
padding: 10px;
background: #e6e6e6;
margin: 0 0 35px 0;
position: relative;
}
.absolute_div {
height: 100px;
width: 250px;
border: 1px solid #000;
background: #c6c6c6;
padding: 10px;
position: absolute;
top: 40px;
left: 100px;
z-index: 100;
}
There are two relative <div>s (placed in identical wrappers) containing each one a absolute <div> that overlap all the relative <div>s. This works great without any problems in updated versions of Chrome, Firefox etc, the absolute <div> with z-index is always placed on top.
In IE6 and IE7 this is not working. The different between this problem and the standard "dropdown in header display its menus behind the page content" is that in those situations its often fixed by give the parent element of that specific menu other z-index etc. In this case the both absolute <div>s are put in identical <div>s.
Can this be solved so the absolute <div>s are always on top of all relative <div>s in IE6 & IE7? Conditional comments for IE can be used to make the solution cross-browser.
It is possible but only by decreasing the z-index of the second .wrapper or increasing the z-index of the first .wrapper.
On a simple level, each positioned element with a non-auto z-index creates a new stacking context, although there are other circumstances in which a new stacking context is created - see The stacking context.
The problem is one that affects IE <= 7, from quirksmode.org
In Internet Explorer positioned elements generate a new stacking context, starting with a z-index value of 0. Therefore z-index doesn't work correctly.
CSS
.wrapper{
height: 100%;
width: 100%;
}
.lower {
position: relative;
z-index: -1;
}
.higher {
position: relative;
z-index: 2;
}
.relative_div {
height: 75px;
width: 200px;
border: 1px solid #000;
padding: 10px;
background: #e6e6e6;
margin: 0 0 35px 0;
position: relative;
}
.absolute_div {
height: 100px;
width: 250px;
border: 1px solid #000;
background: #c6c6c6;
padding: 10px;
position: absolute;
top: 40px;
left: 100px;
z-index: 1;
}
HTML
<div class="wrapper"> <!-- add higher class here -->
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
<div class="wrapper"> <!-- or add lower class here -->
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>