Why does 100% not mean 100% height? - html

I am trying to get some divss to expand to fill the screen, but I am struggling. I have broken down the issue on this jsfiddle.
What I really want to know is why does the div, with its 100% min-height, not expand to that height (or at all) when its parent has the same attribute and does expand?
<body>
<div>
stuff
</div>
</body>
body {
min-height: 100%;
background: red;
}
div {
min-height: 100%;
background: grey;
}

The issue is covered in the CSS 2.1 spec:
<percentage>
Specifies a percentage height. The percentage is
calculated with respect to the height of the generated box's
containing block. If the height of the containing block is not
specified explicitly (i.e., it depends on content height), and this
element is not absolutely positioned, the value computes to 'auto'. A
percentage height on the root element is relative to the initial
containing block. Note: For absolutely positioned elements whose
containing block is based on a block-level element, the percentage is
calculated with respect to the height of the padding box of that
element. This is a change from CSS1, where the percentage was always
calculated with respect to the content box of the parent element.
So, to clarify, a percentage height will reference the height of its containing block (unless it is position: absolute or position: fixed). If that containing block does not have a specified height, then the percentage will refer to auto, and it won't really do much.
position: absolute changes the referenced containing block to the nearest positioned (absolute, relative, or fixed) element.
position: fixed changes the referenced containing block to the viewport.
So, if you specify a height on your containing block, specify a position other than static on your containing block, or don't mind using the viewport as your containing block, then you can use percentage heights effectively.
Please see my demonstration at jsFiddle

You need to also set the height of the html so that 100% refers to the viewport height instead of the document height (demo):
html,body {
height: 100%;
background: red;
padding: 0;
}
div {
height: 100%;
background: grey;
}

because you can't really use 100% height on a static element. Changing the position attribute from static to absolute will give you 100% height. demo
posted as answer per the request of the the PO.

Percentage heights in CSS don't make a lot of sense to me. I would argue that it doesn't work the way it should, but CSS enthusiasts would insist that it does.
This article discusses both the issue and solution in detail:
http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks
This might help too:
<style>
#outer {position:absolute; height:auto; width:200px; border: 1px solid red; }
#inner {position:absolute; height:100%; width:20px; border:1px solid black; }
</style>
<div id="outer">
<div id="inner"></div>
text
</div>
See here for more details on the above:
How to make a floated div 100% height of its parent?

There are two issues, you'll want to specify the height of the html as well, as in:
html, body {
min-height: 100%;
}
Also there appears to be an issue in IE where min-height doesn't do the trick for the div but specifying height on the div does the trick. As such:
html, body {
min-height: 100%;
background: red;
}
div {
height: 100%;
background: grey;
}

This will work
body, html {
height: 100vh;
}
aside {
background: green;
width: 200px;
height: 100vh;
}

Related

Why my background-color only appear when I put the "body" and "html" in my CSS code? [duplicate]

I am trying to set a <div> to a certain percentage height in CSS, but it just remains the same size as the content inside it. When I remove the HTML 5 <!DOCTYTPE html> however, it works, the <div> taking up the whole page as desired. I want the page to validate, so what should I do?
I have this CSS on the <div>, which has an ID of page:
#page {
padding: 10px;
background-color: white;
height: 90% !important;
}
I am trying to set a div to a certain percentage height in CSS
Percentage of what?
To set a percentage height, its parent element(*) must have an explicit height. This is fairly self-evident, in that if you leave height as auto, the block will take the height of its content... but if the content itself has a height expressed in terms of percentage of the parent you've made yourself a little Catch 22. The browser gives up and just uses the content height.
So the parent of the div must have an explicit height property. Whilst that height can also be a percentage if you want, that just moves the problem up to the next level.
If you want to make the div height a percentage of the viewport height, every ancestor of the div, including <html> and <body>, have to have height: 100%, so there is a chain of explicit percentage heights down to the div.
(*: or, if the div is positioned, the ‘containing block’, which is the nearest ancestor to also be positioned.)
Alternatively, all modern browsers and IE>=9 support new CSS units relative to viewport height (vh) and viewport width (vw):
div {
height:100vh;
}
See here for more info.
You need to set the height on the <html> and <body> elements as well; otherwise, they will only be large enough to fit the content. For example:
<!DOCTYPE html>
<title>Example of 100% width and height</title>
<style>
html, body { height: 100%; margin: 0; }
div { height: 100%; width: 100%; background: red; }
</style>
<div></div>
bobince's answer will let you know in which cases "height: XX%;" will or won't work.
If you want to create an element with a set ratio (height: % of it's own width), use the aspect-ratio property. Make sure height is not explicitly set on the element for it to work. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio
.square {
width: 100%;
height: unset;
aspect-ratio: 1 / 1;
}
Historically, the best way to do this was to set the height using padding-bottom. Example for square:
<div class="square-container">
<div class="square-content">
<!-- put your content in here -->
</div>
</div>
.square-container { /* any display: block; element */
position: relative;
height: 0;
padding-bottom: 100%; /* of parent width */
}
.square-content {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
}
The square container will just be made of padding, and the content will expand to fill the container. Long article from 2009 on this subject: http://alistapart.com/article/creating-intrinsic-ratios-for-video
In order to use percentage(%), you must define the % of its parent element. If you use body{height: 100%} it will not work because its parent have no percentage in height. In that case in order to work that body height you must add this in html{height:100%}
In other cases to get rid of that defining parent percentage you can use
body{height:100vh}
vh stands for viewport height
You can use 100vw / 100vh. CSS3 gives us viewport-relative units. 100vw means 100% of the viewport width. 100vh; 100% of the height.
<div style="display:flex; justify-content: space-between;background-color: lightyellow; width:100%; height:85vh">
<div style="width:70%; height: 100%; border: 2px dashed red"></div>
<div style="width:30%; height: 100%; border: 2px dashed red"></div>
</div>
Sometimes, you may want to conditionally set the height of a div, such as when the entire content is less than the height of the screen. Setting all parent elements to 100% will cut off content when it is longer than the screen size.
So, the way to get around this is to set the min-height:
Continue to let the parent elements automatically adjust their height
Then in your main div, subtract the pixel sizes of the header and footer div from 100vh (viewport units). In css, something like:
min-height: calc(100vh - 246px);
100vh is full length of the screen, minus the surrounding divs.
By setting min-height and not height, content longer than screen will continue to flow, instead of getting cut off.
With new CSS sizing properties you can get away with not setting exact height on parent. The new block-size and inline-size properties can be used like this:
<!DOCTYPE html>
<style>
#parent {
border: 1px dotted gray;
height: auto; /* auto values */
width: auto;
}
#wrapper {
background-color: violet;
writing-mode: vertical-lr;
block-size: 30%;
inline-size: 70%;
}
#child {
background-color: wheat;
writing-mode: horizontal-tb;
width: 30%; /* set to 100% if you don't want to expose wrapper */
height: 70%; /* none of the parent has exact height set */
}
</style>
<body>
<div id=parent>
<div id=wrapper>
<div id=child>Lorem ipsum dollar...</div>
Resize the browser window in full page mode. I think the values are relative to viewport height and width.
For more info refer: https://www.w3.org/TR/css-sizing-3/
Almost all browsers support it: https://caniuse.com/?search=inline-size

HTML and BODY are static, which is my DIV's closest positioned ancestor?

I’ve got this simple HTML5 document:
<!doctype html>
<html>
<head>
<style type="text/css">
body { margin: 0; padding: 0; }
.parent1 { height: 50px; background: #00ff00; }
.parent1 > .child1 { height: 50%; width: 100%; background: #ffcc00; }
.parent2 { position: absolute; width: 100%; height: 25%; background: #ff0000; }
</style>
</head>
<body>
<div class="parent1">
<div class="child1">I'm 25px height (50% of 50px)</div>
</div>
<div class="parent2">I'm absolute positioned. My ancestors, body and html, are static... Where I'm getting the 25% from?</div>
</body>
</html>
There’s no height defined for html and body, so they use the default value auto (which means that their height is their content’s height). They aren’t positioned, so they are static.
div.parent1 is 50px height.
div.parent1 has a child element with a 50% height.
div.parent2 is positioned absolute with a height of 25%.
If I’m not mistaken, a height set with percentage only works if it’s parent has a height defined (that’s the case of div.child1).
Because div.parent2 is absolute, it’s height is not computed, so body and html height is 50px. That’s clear, but I don’t understand why div.parent2 25%’s height is working… Where does it take from? Its ancestors body and html are static… Window? Viewport?
JSFiddle
Let's see what w3 says about absolutely positioned elements:
They define a new rectangular plane into which their contents are
flowed, just as the HTML inside the <BODY> element flows into the
default container.
So it sounds like the body element itself represents a default container, no matter it is static.
Taken from w3.org.
Or even better explanation from w3 wiki.
If an absolutely positioned element has no positioned ancestor, then
the containing block is something called the “initial containing
block,” which in practice equates to the html element. If you are
looking at the web page on screen, this means the browser window; if
you are printing the page, it means the page boundary.
html is a block-level element and it lives in the initial containing block.
The initial containing block is a rectangular box which takes the width of the viewport. Hence the width of html element would be equal to the width of the viewport.
On the other hand, the containing block of body element is generated by html. Therefore they would have equal widths as well.
body itself establishes a containing block for its block-level children. And that's why a div element in normal flow will take the width of the viewport.
see https://stackoverflow.com/a/28354270/2543240
The html 'element' in the absence of an positioned ancestor.
For an absolutely positioned element, percentage values for the left, right and width properties are relative to the width of the containing block. Percentage values for the top, bottom and height properties are relative to the height of the containing block.
In this case, the containing block is the html element,
The body had no height as the element is out of the flow.
html {
background: green;
}
body {
margin: 0;
padding: 0;
background: lightblue;
}
.parent2 {
position: absolute;
width: 100%;
height: 25%;
background: #ff0000;
}
<div class="parent2">I'm absolute positioned. My ancestors, body and html, are static... Where I'm getting the 25% from?</div>
Your HTML is static using px.
The percentage is calculated on browser page height - width

Why isn't parent div width stretching to width of child

Look at this jsfiddle:
http://jsfiddle.net/w9k2sz52/
#content {
background: #ff0000;
min-height: 200px;
}
.container-fluid {
min-width: 2000px;
}
<div id="content">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<h1>Some title here</h1>
</div>
</div>
</div>
</div>
Why is the width of #content not stretching to be 2000px instead of being the width of the viewport? What do I need to do to make content stretch so that no matter what min-width is set on container-fluid #content will always stretch to fit it
Set #content to inline-block, and then set min-width to 100%. Note that setting width to 100% won't have the desired affect.
#content {
background: #ff0000;
min-height: 200px;
min-width: 100%;
display:inline-block;
}
Adding a float will make the parent element the same width as the child:
#content {
background: #ff0000;
min-height: 200px;
float: left;
}
#content {
background: #ff0000;
min-height: 200px;
display: inline-block;
}
You could use
width:auto;
This should mean it stretches to the width of its contents.
EDIT:
The min-width property in CSS is used to set the minimum width of a specified element. The min-width property always overrides the width property whether followed before or after width in your declaration. Authors may use any of the length values as long as they are a positive value.
You need to set a max-width or width with it. Say you had a width of 80% and a min width of 400px, it will be no smaller then 400px even if 80% of the page is 200px.
You could give the content a min width forcing the div to be auto and be no smaller then the content.
Could #content determine the width, while .container-fluid expands to fill it? Instead of the other way around.
#content {
background: #ff0000;
min-height: 200px;
width:2000px;
}
.container-fluid {
width: 100%;
}
By adding
position:absolute
to your CSS declaration for #content, you force the CSS interpreter to check what elements are inside #content, therefore achieving desired effect.
The problem with absolute positionning is that it remove the element from the natural workflow of the document. Therefore, you are better wrapping the element unto which you want to apply absolute positionning inside another element. This one will stay in the natural workflow of the DOM.
See this jsfiddle: https://jsfiddle.net/7Ls47d83/4/
Google "CSS box model" for more interesting articles and post about this, or this article.

How do I stretch a div to be the height of the document body, not the viewport? (included code)

All the examples I've seen say to do the below code, but this does not work (see jsfiddle below).
html { height: 100%; min-height: 100%; }
body { height: 100%; min-height: 100%; }
.stretchable { position: absolute; width: 100px; height: 100%; min-height: 100%; }
Showing it not working: http://jsfiddle.net/yVDXQ/481/
How do I use CSS only to force a div to be the height of the document body, not the window?
Look closer... your body element is not the full height of the content. Remove the height: 100% and instead add position: relative to the body element. Here is a fork of the fiddle:
http://jsfiddle.net/7j8vrnr8/
Remember that absolute positioned elements have their height/width based on the first relative positioned element as you move up the hierarchy.
position: relative
First of all, you need to remove height:100% for body – otherwise the body will only be as high as the viewport (with the rest of the content overflowing it).
And then, since your .stretchable element is positioned absolutely, you simply remove any height and min-height from that completely (so that effectively height:auto is in place) – and position it from the top and bottom, so that those two values determine its height. (position:relative added for body, so that this element gets taken as point of reference for the absolute positioning).
http://jsfiddle.net/yVDXQ/484/

Why body height is not 100% while using min-height property with 100% value

I have a page at
http://uberhealth.co/register.php
I have set the property to set the min-height to 100% but still as you can see the footer is not at bottom and thus the height is not getting set to 100%. how can i fix this?
Update
I have already given there
html, body{
height:100%;
}
and a container class for body
.cbody-full { min-height:100%; }
Though you've set a min-height (percentage) value for the <html> element, it doesn't have a explicit height value. Hence, the min-height property is not working for the <body> element properly.
From the MDN:
min-height
The percentage is calculated with respect to the height of the
generated box's containing block. If the height of the containing
block is not specified explicitly (i.e., it depends on content
height), and this element is not absolutely positioned, the percentage
value is treated as 0.
You could set a height of 100% for the <html> element, and min-height: 100%; for the <body>.
html { height: 100%; }
body { min-height: 100%; }
Update #1
Here's my attempt to fix your layout issue.
First note that you have to specify the height of the parent element, if want to use min-height for the child element.
You have multiple wrappers inside each other, changed all the min-height: 100% declarations to height: 100% (including the html, body, ...); and use min-height: 100% for the .cbody-full > container element.
Then, you may face the vertical scrollbar. That's because the computed height of the header and the footer is added to 100% of the height of the screen (In fact the .cbody-full > container element has the height of 100%).
You could fix that, by adding a negative top/bottom margin to the .cbody-full > container element:
.cbody-full > container {
min-height: 100%;
margin-bottom: -50px;
margin-top: -55px;
}
But, this cause the container goes over the header and/or the footer. In order to fix that, you could set a top/bottom padding to the container and use box-sizing: border-box to calculate the width and height of the box including the paddings and borders:
.cbody-full > container {
min-height: 100%;
margin-bottom: -50px;
box-sizing: border-box;
padding-bottom: 50px;
margin-top: -55px;
padding-top: 55px;
}
Just one more thing, you probably need to set z-index property for the header and footer elements, as follows:
#navbar, /* The header (navigation in this case) */
.footer {
position: relative;
z-index: 100;
}
Update #2
If you consider using Ryan fait's sticky footer, note that the footer shouldn't be inside of the .cbody-full element, it should be beside that. That's why it doesn't stay at the bottom of the page.
Hence, you could change your markup as follows:
<body>
<nav id="navbar"></nav>
<div class="cbody-full"></div>
<div class="footer"></div>
</body>
Then, follow the above approach for height and min-height properties, as well as position and z-index for the navigation and footer. Finally use the following for the .cbody-full element:
.cbody-full {
min-height: 100%;
margin-bottom: -50px;
box-sizing: border-box;
padding-bottom: 50px;
margin-top: -55px;
padding-top: 55px;
}
even if you dont put min-height:100% its always at 100%. The height is always relative to the content always given that the height is not staticcaly defined