Unexpected behaviour of position relative on body - html

So, let's say we have the following code:
body {
margin: 0;
/* position: relative; */
}
.container {
width: 300px;
height: 300px;
margin: 100px;
background: gray;
}
.absolute {
width: 100px;
height: 100px;
background: red;
position: absolute;
top: 10px;
}
<div class="container">
<div class="absolute"></div>
</div>
In this case the .absolute element is positioned relative to the body, as expected.
Not let's add position: relative to the body.
The element is now positioned relative to the .container. Which doesn't make sense, as absolutely positioned element is positioned relative to nearest positioned ancestor (non-static) which is body in this case.
Is body positioning treated differently from other elements?
CODEPEN

From the specification about absolute positioning:
The containing block for a positioned box is established by the nearest positioned ancestor (or, if none exists, the initial containing block, as in our example).
Ok, you have none nearest positioned ancestors, move along to the initial containing block:
The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:
The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media.
Good, and what is the root element in your case:
The html element represents the root of an HTML document.
It means that by default your the .absolute element is positioned not relative to the <body>, but to the <html>.

In fact, if you do not specify the position: relative, then the elements will have a position of :static ( https://www.w3schools.com/cssref/pr_class_position.asp ). You actually need to insert position relative to the .container element if you want to place .absolute depending on the container element. This is why you have the strange behavior.

Related

Child element positioned fixed relative to viewport

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?

position a child <div> inside a fixed positioned parent <div>

So I'm trying to build a modal window (with a white background) with HTML/CSS and I want the modal window itself to be fixed positioned relative to the browser window. In addition, the modal contains a child img at the top and a child div at the bottom that will contain some description text in it. My purpose is to position the child div relative to the parent fixed modal window so that the child div has a left offset of about 8.33% of the width of the parent.
So initially I thought I should absolute position the child div, but once I do that the background of the parent modal windows does not extend to the child div:
here is the html/css for the above:
html:
<div class="modal col-4 l-offset-4" id="robot-modal">
<img src="media/robot_modal.jpg">
<div class="col-10 l-offset-1">
</div>
</div>
css:
.col-10 {
width: 83.33333%;
}
.l-offset-1 {
left: 8.33333%;
}
.modal {
#include align-vertically(fixed);
display: none;
z-index: 2000;
background: white;
img {
width: 100%;
}
div{
position: absolute;
background-color: blue;
height: 100px;
}
}
But when I change the child div's position to 'relative', then the correct background will show up:
I don't get the intuition why I should always relative position an element inside a fixed parent. Wouldn't positioning an element as relative make it impossible to adjust offset relative to its parent ? According to this article: http://www.webdevdoor.com/html-css/css-position-child-div-parent , if we want to position an element relative to its immediate parent, the parent better be absolute or relative positioned and the child must be absolute positioned. So in my case why does adjusting the offset of a relative positioned child also work? I don't want to assign a height to the parent modal. i want it to automatically enlarge itself when new elements are contained in it.
A parent does not take into account the size of the absolute child. According to MDN:
Absolute: Do not leave space for the element. Instead, position it at a specified position relative to its closest positioned ancestor or to the containing block
If you put something after the absolute element, it goes on top, because the absolute element is no longer in the document flow.
You can do position: relative; left: 8.33%; right: 8.33%, or just leave it as static with margin: 0 8.33%;, or if you do absolute, you can set .modal { margin-bottom: [height of absolute DIV] }, if the height is set and won't change.

CSS Positioning is not working as expected

Here is my code
CSS
h2
{
position: absolute;
left: 100px;
top: 150px;
}
h1
{
position: fixed;
top: 300px;
}
HTML
<h1>
Heading for Fixed Position
<h2>
This is a heading with an absolute position</h2>
</h1>
I'm new to CSS so was experimenting with positioning. I read some where
An absolute position element is positioned relative to the first parent element that has a position other than static. If no such element is found, the containing block is <html>:
If that is right then This is a heading with an absolute position message must be below the Heading for Fixed Position since h1 is the parent object and h2 being a absolute object must be positioned relative to h1. Please correct if I'm wrong.
Here is the JSFiddle link:
http://jsfiddle.net/KXmgG/
I would like to explain you how positioning actually works, there are 4 types
Static (Default)
Relative
Absolute
Fixed
Static position is nothing but a normal flow of the document where elements render on after the another (Excluding floats)
Relative position is something special, which turns out to be a great power when used with position absolute. When you want to use top, left, bottom and right instead of margins, you need to assign position: relative; to that element, after doing so, top, left, right and bottom properties will work.
When you use position: absolute; it gets out of the document flow, so if you have an element called div width class a. Now if you assign position: absolute; to class a, it will get out of the document flow, so when you use top: 0; it will fly away to the top of the document. So in order to restrict it, we wrap a container with position: relative; so that when you use position: absolute;, it will be absolute to that particular element and not the entire document.
Demo 1
Demo 2
Position fixed is entirely different, it is also out of the document flow as same as position: absolute; but the difference is that fixed positioned element cannnot be relative to any element, it has no contact whatsoever with any element, it is always calculated from the top, left, right and bottom of the window and not the element, also a fixed position element will flow as the user scrolls the document.
Demo
Coming to your answer, you are using fixed position and absolute position, both are out of the document flow, so they have no relation what so ever...
You are using top: 300px; for fixed position and top:: 150px; for absolute positioned element, so the fixed element will render below the absolute element, but when you try to scroll, your fixed element will scroll along where as position: absolute; element won't.
Edit as you commented
Go to w3c Validator and validate your document here
"An absolute position element is positioned relative to the first parent element that has a position other than static. If no such element is found, the containing block is :"
Yes but you dont have position:relative declared.
If you want you're parent transform you're html by this :
<div class="parent">
<h1 class="child">blabla</h1>
<h2 class="child">blabla</h2>
</div> <!-- end parent -->
<div class="relative">
<h1>
Heading for Fixed Position</h1>
<h2>
This is a heading with an absolute position</h2>
</div>
CSS :
.relative{
position:relative;
}
JSFIDDLE with
position relative / fixed / absolute /]
http://jsfiddle.net/KXmgG/1/

Why is this absolutely positioned element not positioning relative to its container?

I have this simple code to place two div #container elements side by side. In each of these there is a child div #child which I would like to position relative to its parent (div #container).
<style>
.container {
float:left;
margin-right: 10px;
}
.child {
position: absolute;
left: 0.2ex;
}
</style>
<div class="container">a<br/>
<div class="child">b</div>
</div>
<div class="container">c<br/>
<div class="child">d</div>
</div>​
However, rather than the result I would expect - 'd' is positioned below 'c' but pushed slightly to the right, 'd' is instead positioned over 'b' and slightly to the right. In other words the absolute position has been rendered relative to the page rather than to its containing element.
Why is this the case? What have I misunderstood about absolute positioning here?
How can I get the behaviour I was expecting?
See this jsFiddle.
Absolutely positioned elements are positioned with respect to the edges of their containing block, which is defined as the first ancestor that is not position: static.
None of the ancestor elements are position: static, so it is with respect to the initial position of the viewport.
Set position: relative on the .container elements if you really want to absolutely position them.
That said, it looks like you would be better off doing this instead:
.child {
margin-left: 0.2ex;
}
To position the child relative to its parent, just add position:relative to the PARENT'S style - then all children with position:absolute will be absolute relative to the parent.
.container {
float:left;
margin-right: 10px;
position:relative;
}

How to make the wrapping div element with relative position match child elements height?

I have a simple problem where I have 2 divs, 1 is relative positioned. The child element is absolute positioned. This child has varying height.
The code so far:
HTML
<div id="wrap"><div id="inner"></div></div>
CSS
#wrap {
width: 100%;
background: #ccc;
position: relative;
min-height: 20px;
}
#inner {
width:30%;
background: #000;
position: absolute;
right: 0;
top: 0;
height: 200px;
}
The problem I have is that the #wrap element doesn't adjust its height to match the child element and therefor the child element hangs outside the edge of the parent. Can this be done with relative and absolute positioned elements?
I know this can be achieved with floating elements and following them with css => cleared: both, but I'd like to know if its possible with this method.
I've created a jsfiddle of this problem over here if anybody would like to help me out!
Thanks a lot.
Absolute positionned elements are outside the flow so parents can't adjust their height.
But you can simply use:
#wrap {
width: 100%; /* useless */
background: #ccc;
overflow:hidden; /* establish a new formatting context */
min-height: 20px;
}
#inner {
width:30%;
background: #000;
float:right;
}
No, you can't make a parent with position: relative adjust its height to fit a child element with position: absolute.
This is because:
In the absolute positioning model, a
box is explicitly offset with respect
to its containing block. It is removed
from the normal flow entirely (it has
no impact on later siblings). An
absolutely positioned box establishes
a new containing block for normal flow
children and absolutely (but not
fixed) positioned descendants.
However, the contents of an absolutely
positioned element do not flow around
any other boxes.
http://www.w3.org/TR/CSS21/visuren.html#absolute-positioning
If you wanted to stick with your position based code, you'd have to use JavaScript to set the height of the parent div.
Otherwise, stick to using floats if they work for your case. #MatTheCat's answer looks good to me.
Just for completeness, here's a demo of #MatTheCat's answer with height: 200px added, so you can see the parent div does adjust in height: http://jsfiddle.net/gR2wL/3/