I've been looking up on the Internet to find out how min-height and height properties work on body and html elements. I've seen the following code at a lot of places
html {
height: 100%;
}
body {
min-height: 100%;
}
The above can be used in conjunction with some other divs to get a sticky footer. The other statement being that to set percentage height on body we need to set an explicit height of html as well.
Well Ok, but then what is the height of html tag in percentage relative to? Some answers say it is relative to viewport if the height of viewport is 100%. Now what is this 100% height of viewport relative to?
This post over here says that the height of html element is controlled by the viewport HTML vsBody, but that's not what I saw
Height of HTML Element can Increase
But then why is that when the content increases the height of html element also increases as can be seen on Chrome Developer Tools
Code:
html {
}
.wrapper {
padding-bottom: 3000px;
}
.footer {
position: absolute;
bottom: 0;
left: 0;
}
<html>
<head>
<title>Height</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
Content
</div>
<div class="footer">
Footer
</div>
</div>
</body>
</html>
Height of HTML element made fixed
Only when I explicitly set the height of html element to 100% does it get a fixed height:
html {
height: 100%;
}
.wrapper {
padding-bottom: 3000px;
}
.footer {
position: absolute;
bottom: 0;
left: 0;
}
<html>
<head>
<title>Height</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
Content
</div>
<div class="footer">
Footer
</div>
</div>
</body>
</html>
And here's the fixed height:
Sticky Footer
Since the height of HTML Element is taking over the whole content, why can't I achieve a sticky footer by not setting height on html or setting a min-height? Since body is be default position: static
, if I position anything, it should be positioned against the html element right?
But none of the below work :/
html {
min-height: 100%;
}
.wrapper {
padding-bottom: 1000px;
}
.footer {
position: absolute;
bottom: 0;
left: 0;
}
<html>
<head>
<title>Height</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
Content
</div>
<div class="footer">
Footer
</div>
</div>
</body>
</html>
html {
}
.wrapper {
padding-bottom: 3000px;
}
.footer {
position: absolute;
bottom: 0;
left: 0;
}
<html>
<head>
<title>Height</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="wrapper">
<div class="header">
Header
</div>
<div class="content">
Content
</div>
<div class="footer">
Footer
</div>
</div>
</body>
</html>
References:
The concept you are missing is called the "Initial Containing Block".
The html element (by definition) and the body element (by default) are block elements, and behave the same way as all block level elements. So you can set a fixed height, let it be as tall as its content, or give it a percentage height (and/or max and min variants). When a block level element is given a percentage height, that is a percentage height of its "Containing Block". For this to work, the Containing Block's height must not depend (even potentially) on the height of its content, because that would cause a circular dependency.
For most elements, their containing block is the one formed by their parent element, but there are exceptions. In particular, are the two examples of your question, the footer which is position:absolute
and the root element of the document which obviously doesn't have a parent element, in your case, the <html>
element.
As explained by L-X, for absolute positioned elements, their containing block is formed by their nearest non-statically positioned ancestor element. If no such one exists, as in your case, the containing block used is the "Initial Containing Block".
The root (<html>
) element's containing block is also the "Initial Containing Block".
So what is the "Initial Containing Block"? It's a rectangle that has the height and width of the viewport, but is anchored at the origin of the canvas (0, 0). This is different to the viewport, which has the same dimensions, but is not anchored, the scroll bars allow the viewport to move over the canvas.
Now we can answer your questions, with respect to your last snippet
how is the height of html and body elements calculated?
The html element there is the height of its contents - the header and content elements plus the wrapper's padding. (the footer isn't counted - its position:absolute
takes it out of the flow. If it was height:100%
it would be the height of the Initial Containing Block, which is the height of the viewport.
Why doesn't the above sticky footer work?
The footer is positioned relative to the Initial Containing Block - (0, 0) plus the height of the Initial Containing Block, less its own height. But the scrollbars allowing the viewport to range over the canvas, down to the bottom of the html element. It's not locked at (0, 0) so the footer moves relative to it - i.e. it is not sticky to the viewport, and it is not positioned at the bottom of the <html>
element.
When a percentage value is set for a property of the root element and the percentage is defined as referring to the inherited value of some property, the resultant value is the percentage times the initial value of that property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With