You can see in the code below that the h1
pushes down the body and the absolutely-positioned block .absolute
does not stick to the top. But you also can see that the same block is stuck to the top of its parent .wrapper
. Why?
I'm not asking how to do that trick; I know how, e.g. padding instead margin to h1, or clearfix to parent and so on.
I'm interested in only one thing: why h1
's margin pushes down the body
, but is not pushing down .wrapper
?
body {
position: relative;
margin: 0;
padding: 0;
overflow: hidden;
background-color: silver;
}
.absolute {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: darkblue;
}
.wrapper {
position: relative;
overflow:hidden;
width: 50%;
height: 200px;
overflow: hidden;
background-color: yellow;
}
.wrapper > .absolute {
background-color: darkcyan;
}
<div class="absolute"></div>
<h1>Some title</h1>
<div class="wrapper">
<div class="absolute"></div>
<h1>Some title</h1>
</div>
OK, I'll try to be more clear. If you click on the link below, you can see my JSFiddle. There is background-color: silver
in the body
tag. When I look in the code inspector, I see that the body tag begins slightly lower due to the h1 margin. But background-color
begins at the top. This means that the code inspector is lying to me, and body begins from top. But why, then, does an absolutely-positioned element that's a direct child of body
not start at the top?
This is caused by
h1
having a default margin, which is keeping thebody
apart fromh1
and its sibling.absolute
.So all you have to do is reset the margin in
h1
, like you did forbody
:snippet with every margin resetted
snippet with every no margin resetted
It's because collapsing margins. How to disable it, you could read in some articles/answers, for example, this.
You are using
overflow: hidden
for.wrapper
, and it disables collapsing margins for this block. From the specification:But it seems like
overflow: hidden
doesn't work for<body>
, because if I setheight: 0
/max-height: 0
it doesn't work too:I think it's because (from the specification):
That's why margins between
<body>
and first<h1>
collapse (from MDN):That's why margins between
<html>
and<body>
don't collapse (from the specification):I also noticed that if
<html>
has defaultbackground-color
and<body>
has specifiedbackground-color
+margin
, the background color fills the entire space of<html>
, for example:But if you set
background-color
to<html>
, it works like a normal block, for example:I summary, I recommend you to use other approaches to disable collapsing margins, or add another wrapper for
<body>
, for example:This is interesting behavior with little documentation to be found online (at least on a basic search).
I'll start by saying I don't know the reason why the absolutely positioned box doesn't align to the corner of
body
, as it would be expected to do. But here are a few observations:The expected positioning works on IE11. The gap exists in Chrome and FF.
If you remove
position: relative
frombody
, the expected positioning works (as tested in Chrome, FF & IE11). demoIf you apply just 1px
padding
tobody
, it also works cross-browser. demoIf you add a border to
body
, it also works. demoUPDATE
As a quick addendum to @BoltClock's accepted answer, this problem could have been easily illustrated and understood by just adding a background color to the root element in the original code...
demo
... and by removing the default margin on the
h1
:demo
This is another instance of the phenomenon known as
margin-collapsing
.I'll try to explain what is happening:
When you move
div.absolute
with position absolute, it pulls it out of the flow of the content. This causes the firsth1
to act as the first-child of its parent, which isbody
in this case.The
h1
's margin then gets collapsed outside the body, due to margin-collapsing. That is whytop: 0;
is not in the upper-left of the viewport. It is in the upper left of thebody
.If you need to get this to work, then add a
html {position: relative; overflow: hidden:}
.As mentioned, the containing block of the top-level absolutely positioned element is
body
, asbody
is relatively positioned. When the margin of theh1
collapses with that ofbody
, this causes the margin to affectbody
, and in turn the absolutely positioned element that it contains. Conversely, ifbody
wasn't relatively positioned, the absolutely positioned element would be anchored to the initial containing block, and stick to the top of the viewport unaffected by any effective margins onbody
(becausebody
is no longer its containing block).As to why the silver background bleeds beyond the
body
element, that's by design:The root element's default background color is always
transparent
, so setting a background color on thehtml
element prevents the silver background from bleeding out of thebody
element (and you'll see that the inspector is in fact not lying to you):