Why do HTML and BODY elements overlap? - html

With this simple HTML/CSS template below, I expected BODY to be contained within HTML element. Why is it not? I separated the css for HTML and BODY to give different colors.
https://jsfiddle.net/jwinnd/w95ngLqc/3/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>demo</title>
<style>
html {
width: 100%;
height: 100%;
border: solid 30px red;
}
body {
width: 100%;
height: 100%;
border: solid 30px blue;
}
</style>
</head>
<body>
<script>
</script>
</body>
</html>

This is what you want. Don't overthink it. The box-sizing property is the most important in this scenario. The box-sizing will measure the element's width and height with the border included.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>demo</title>
<style>
html {
border: solid 30px red;
box-sizing: border-box;
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
body {
border: solid 30px blue;
box-sizing: border-box;
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
</style>
</head>
<body>
<script>
</script>
</body>
</html>

Your Question:
In short; you're asking why the body element is not directly on top of the html parent as you would expect.
Explanation:
The fact is, IT IS, but the way that the CSS is set out, is that some CSS rules and some default styling factors offset this direct layering.
In this case, the HTML and the body 'boxes' are only by default measured by the system in terms of it's "content area" rather than it's whole "margin" + "border" + "content" area.
Read about CSS box-sizing.
You have a border on both, so the child element is offset against the border, but the child element has also been told to be 100% width, so it must overflow the parent because the true total size of the child element is "border" (30px x 2) + "padding" (0px) + "content" (100%)
As well as this, the <body> element has a default margin value of 8px (0.5rem standard font size) on all edges so this as well is not accounted for by the sizing system because the margin (like the border) is not in the "content area" and so causes a further offset.
However, the child element is forced to being 100% of its parent so it has to "overflow" at the far end of the parent (<html>) box; causing your borders to overlap.
From the above you can see your body element actually has a TOTAL width of:
margin: 16px
border: 60px
content: 100%
So the body is 100% + 76px of the parent element's size.
CSS can't not show any part of the display, so it is forced to overflow the parent to keep everything viewable (You can change this with: overflow:hidden;)
Further to the above, the <body> element overflows the parent <html> element because the parent has been set to a width of 100% as well, so it will be the maximum width of the child (body) "content area" rather than the area it actually effects on the screen. This is why the border on the bottom right of your example has blue outside the red; because the system thinks:
This container [the screen size] has a width of X so I need to be X wide for my contents and then I can add my border and my margin
the child element meanwhile processes:
I must take up all the width of my parent, plus my border and plus my margin that I have.
Be default <body> has a natural margin on it, and the border itself set on <html> will force its child elements to be within the border rather than on top of the border.
My fixes to remove default settings and browser inherited styles, and force the box model to respect all areas of the box not just the contents.
Tweaked Version of your HTML:
html {
width: 100%;
height: 100%;
border: solid 30px red;
box-sizing: border-box;
}
body {
margin: 0; /* Added to body */
width: 100%;
height: 100%;
border: solid 30px blue;
box-sizing:border-box;
/* often added to the *{ .. } element to apply to all elements on a page */
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>demo 2</title>
<style>
</style>
</head>
<body>
Hello 2
</body>
</html>
CSS Changes made:
Removed default margin on the body element.
Changed box-sizing to border box whereby the DOM Box model is set to the border rather than simply the box contents.

Yeah! If sometimes you see a web developer pulling his hair or gnashing his teeth, he is probably messing up with this problem. You may think that when you determine the height of a block-level element it includes the content box to the outer side of the border. But it is not! When you set the height of an element you only set its content's size, and not the borders and paddings. It is really common for developers to set all element to have box-sizing of border-box. You can do this by adding this peace of code to the top of your css style. :
*{
box-sizing: border-box;
}
So, here is your code result after adding this property. Also, note that the body element has a default margin. Be sure to disable that too:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>demo</title>
<style>
*{
box-sizing: border-box;
}
html {
width: 100%;
height: 100%;
border: solid 30px red;
}
body {
width: 100%;
height: 100%;
margin:0;
border: solid 30px blue;
}
</style>
</head>
<body>
<script>
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>demo</title>
<style>
html {
box-sizing:border-box;
width: 100%;
height: 100%;
border: solid 30px red;
}
body {
margin:0;
box-sizing:border-box;
width: 100%;
height: 100%;
border: solid 30px blue;
}
</style>
</head>
<body>
<script>
</script>
</body>
</html>

Related

Scroll in the body and the space after the block [duplicate]

This question already has answers here:
Why does this CSS margin-top style not work?
(14 answers)
CSS margin terror; Margin adds space outside parent element [duplicate]
(7 answers)
Closed 1 year ago.
I don't understand why there is a scroll in the body and a space after the block .example. According to my logic, I make the margin-bottom 100px and then subtract these 100px from the block height max-height: calc(100% - 100px);
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
.example {
padding: 20px;
width: 60%;
margin: 100px auto 0;
max-height: calc(100% - 100px);
border: 1px solid black;
overflow-y: scroll;
}
p{
padding: 100vh 0;
}
</style>
</head>
<body>
<div class="example">
<div class="text">
<p>Lorem</p>
<p>Lorem</p>
</div>
</div>
</body>
</html>
You're running into wildly inherited margins problem derived from the popular collapsed margins - issue (which is better known for when two elements with vertical margins, the two colliding margins collapse into one) - not your exact case but same in nature.
Read more on w3.org Collapsing Margins
Since you used html, body {height: 100%} and the tall .example element has margin-top 100% - the body element moved, collapsed 100px down! It basically "wildly" inherited (at least visually) those 100px margin.
An element with vertical margin can cause unwanted results with ancestors flow. One common way to fix this is to smartly avoid vertical margin, or to add overflow: auto to the ancestor that's being affected by that problem html, body in your specific case.
html, body {
height: 100%; /* Why would you want this? */
overflow: auto; /* FIX for wild margins */
}
The other solution (I'm sure there are many others) is to not use html, body {height: 100%}
Rather min-height (if really needed) on html and body and vh (viewport height) unit on the .example element
html, body {
/* min-height: 100%; /* use min-height, but not needed */
}
.example {
/* .... other styles */
margin: 100px auto 0;
height: calc(100vh - 100px); /* 100vh minus 100px margin-top */
}
Long story short - Be careful when using margin. I personally use it only when working with flexbox, or in the horizontal space (often when using inline-block elements) otherwise I always use wrappers with padding to create desired spacings which are perfectly controlled thanks to box-sizing: border-box (no need to calculate anything) - or when really necessary- I treat them with special care.
Get rid of the padding on the p elements:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
.example {
padding: 20px;
width: 60%;
margin: 100px auto 0;
max-height: calc(100% - 100px);
border: 1px solid black;
overflow-y: scroll;
}
</style>
</head>
<body>
<div class="example">
<div class="text">
<p>Lorem</p>
<p>Lorem</p>
</div>
</div>
</body>
</html>
Right answer its a Collapsing margins xD. To solve the problem, you can add one of the following to the body:
border
padding
overflow

Flexbox limits child items height when child item height is set to auto

I have three divs: outer, inner, deeper, where each one is the parent of the next.
"Deeper" has its height set to a fixed value, whereas "inner" is set to auto.
I'd expect that "inner" height is the same as "deeper" height, but turns out that it is limited by "outer" height whenever "outer" display is set to flex.
However when "outer" display is set to "block" it works as expected.
Why does this happen?
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.outer {
height: 400px;
overflow-y: auto;
border: 1px solid gray;
display: flex;
}
.inner {
margin: 50px 0;
background-clip: content-box;
height: auto;
}
.deeper {
height: 600px;
width: 200px;
background-color: red;
}
<div class="outer">
<div class="inner">
<div class="deeper"></div>
</div>
</div>
here I posted another code to show my previous conclusion better. in this code you can change the "display:flex" to "display:block" to see the effect in inspect window.
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.outer {
height: 400px;
border: 1px solid gray;
display: flex;
/* the above "display:flex" makes the children of this tag to have the fixed height. */
}
.inner {
height: auto; /* the height defined here does not affect, you can inspect the tag to see that the height is "400px". */
background-color: #242;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-box</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>
I think what you would expect is wrong. see the code below:
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
.outer {
height: 400px;
/* overflow-y: auto;*/
border: 1px solid gray;
display: block;
}
.inner {
/* margin: 50px 0;*/
/* background-clip: content-box;*/
height: 500px;
background-color: #242;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex-box</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="outer">
<div class="inner">
<!-- <div class="deeper"></div>-->
</div>
</div>
</body>
</html>
this is a very simple example. in this case I commented the "deeper" div. and also I commented the "overflow" and "background-clip" properties, because I think that they are not related to the question about "height".
what I want to say is that in this case we have the ".outer" div with "display:block" and a fixed "height". in that div we have another div with "height:500px" that is taller from his parent. you may see only this 500px div. but if you "inspect" you will notice that the height of ".outer" div is 400px. so we can conclude that
if we have a tag with "display:block" and a "fixed height", the height of this tag is not changed according to its child.
so in the case of "your question", we have the ".inner" div and its child is the ".deeper" div. ".inner" div has "display:block" and has a fixed height because:
"align-items" property, which has an initial value of "stretch" makes the children of a div with "display:flex" (that is the ".inner" div) to have the height of their parent (means the ".inner" has "400px" height)
so according to our conclusion height of ".inner" is not changed with the height of ".deeper".

How do I fit everything inside html and body

I have a project and I am having trouble fitting everything inside the body. Child elements always go outside of the body, when I looked at my code it looks like okay, so I made an experiment; I trace each HTML element by giving them a border, so that I can see them visually how they will behave. This is what I have so far.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="index.css">
<title>A nice example</title>
</head>
<body>
<div class="box">
<div class="childbox"></div>
</div>
</body>
</html>
CSS Example 1, setting 100% height for everything
html{height: 100%; border: 5px solid black; padding: 5px;} /*black*/
body{height: 100%; border: 5px solid red; padding: 10px;} /*red*/
.box{height: 100%; border: 5px solid green; padding: 5px;} /*green*/
.childbox{height: 100%; border: 5px solid pink} /*pink*/
Output : everything overflows outside html.
CSS Example 2, setting 100% height for the body and its child's, except html
html{border: 5px solid black; padding: 5px;} /*black*/
body{height: 100%; border: 5px solid red; padding: 10px;} /*red*/
.box{height: 100%; border: 5px solid green; padding: 5px;} /*green*/
.childbox{height: 100%; border: 5px solid pink} /*pink*/
Output : Everything fits inside html, but doesn't occupy the full height of the screen. I know I can do this by making the body min-height: 100vh.. but it will stop expanding when the 100vh is full..
My goal is,
to make the body and html 100% in height / not using vh.
and not overflow outside the body, or html
when adding child elements I want everything from html to body expands in height dynamically and not go outside and overflow, or overlaps each other..
the body should be inside html, and the div's should be inside the body.
Please help.
This is what is happening, the CSS is calculating 100% width and height and then it adds a 10px / 5px padding after which causes the elements to overflow by 10 / 5px.
You can change this by adding the following css at the beginning of your code:
* {
box-sizing: border-box;
//Edit:
margin: 0;
padding: 0;
}
This will make sure that the padding is accounted for in the 100% width and height.
Hope this works!
Edit:
Also, what you are looking for in the html and body style is height: auto; not 100%.
If its happening it means that you are not following CSS box model during styling your sheet. you can also use box-sizing property of CSS.
Consider an example
<div id="frame">This is the frame
</div>
Then use box-sizing property and set its value to border-box.
<style>
#frame{ width: xx% height:yy%; box-sizing:border-box; }
</style>

How to get a border around body tag without it cutting off?

I'm a beginner who wants to visualize the html and css changes that I make while learning and so I would like to put a border around all the elements that I add.
Problem: The blue border around the html/body element cuts off and isn't fully displayed on the bottom and right sides of the border when overflow is set to hidden.
Why is it that the border is overflowing the html page even when its width and height are set to 100%?
HTML
<!DOCTYPE html>
<html>
<head>
<title> Practice Webpage </title>
<link href="stylesrevised.css" rel="stylesheet" type="text/css" >
</head>
<body></body>
</html>
CSS
html,body{
width: 100%;
height: 100%;
margin: 0; /* Space from this element (entire page) and others*/
padding: 0; /*space from content and border*/
border: solid blue;
border-width: thin;
overflow:hidden;
display:block;
}
Here is the resulting webpage
Welcome to the coding journey!!! In your css, add the following: box-sizing: border-box;
This will make your elements fit within the prescribed width and height.
html,body{
width: 100%;
height: 100%;
margin: 0; /* Space from this element (entire page) and others*/
padding: 0; /*space from content and border*/
border: solid blue;
border-width: thin;
overflow:hidden;
display:block;
box-sizing: border-box;
}
<!DOCTYPE html>
<html>
<head>
<title> Practice Webpage </title>
<link href="stylesrevised.css" rel="stylesheet" type="text/css" >
</head>
<body></body>
</html>
your overflow: hidden; is whats messing things up for you, the default setting for borders is content-box which adds pixels to the width and height of your elements, eg if you have a div 100px wide and add a 1px border to it is actual size will be 102px.
you can solve this by using box-sizing: border-box; which causes the border to be added to the inside of the element instead.
html,body{
width: 100%;
height: 100%;
margin: 0; /* Space from this element (entire page) and others*/
padding: 0; /*space from content and border*/
border: solid blue;
border-width: thin;
display:block;
box-sizing: border-box;
}
If you want to make this effect all borders used through out your site you can use this, saves having to set it each time you add a border.
*, *:before, *:after {
box-sizing: border-box;
}

Border of outer element affects how margin of inner element is displayed, why?

I think I got it just partly, now I have another problem I don't understand. I've got a div with id="signin" that is inside other 2 divs. Those 2 divs don't have any padding or border, and when I apply margin-top to the div with id="signin" now it doesn't create any white space above. Why is it? Can the div next to the div with id="signin" be affecting it in any way?
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Test</title>
<style type="text/css">
body {margin: 0px;}
#top-bar {
background-color: #690203;
height: 40px;
}
.fixed-width {
width: 950px;
margin: auto;
}
#logo {
float: left;
}
#logo img {
border-right: 2px solid #752124;
padding: 9px;
}
#signin {
float: left;
width: 200px;
margin-left: 15px;
margin-top: 10px;
border: 1px solid deepskyblue;
}
</style>
</head>
<body>
<div id="top-bar">
<div class="fixed-width">
<div id="logo">
<img src="images/logo.png" width="20">
</div>
<div id="signin">
<!--<img src="images/signin.png" width="13">-->
<span>test test</span>
</div>
</div>
</div>
</body>
</html>
I've started learning css recently and came across a problem I can't understand. I've got one div nested inside another, and when the outer div has a border, then using margin with inner div results in moving the inner div within the outer div, which is how I thought it should work. However, when the outer div doesn't have any border, then using margin with the inner div results in moving the outer div as well and it creates some space above it. Please, have a look and try to explain why it's like that. Thank you.
with border in #bigger
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#bigger {
width: 100px;
height: 100px;
background-color: deepskyblue;
border: 1px dashed black; /* border I use or don't use with the outer div */
}
#smaller {
margin-top: 10px;
width: 50px;
height: 50px;
background-color: deeppink;
padding-top: 10px;
}
</style>
</head>
<body>
<div id="bigger">
<div id="smaller"></div>
</div>
</body>
</html>
without border in #bigger
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#bigger {
width: 100px;
height: 100px;
background-color: deepskyblue;
}
#smaller {
margin-top: 10px;
width: 50px;
height: 50px;
background-color: deeppink;
padding-top: 10px;
}
</style>
</head>
<body>
<div id="bigger">
<div id="smaller"></div>
</div>
</body>
</html>
This is caused by the fact that CSS uses collapsing margins.
That link will explain it far better than I will, so I'd recommend giving that a read, but to give you a short summary:
Margin in CSS is designed to be displayed outside of an element. This behaviour gets a bit murky when dealing with elements within other elements, as the margin can be considered outside of the child in both cases of whether it is within the parent or outside of the parent. It was determined that margin's would always seek to be outside of all parent elements as well, unless that parent had a style which prevented this logic from being true. For example, if the parent has a border, it now has something above it which separates the child from the outside world, meaning that the child's margin must belong inside of the parent. If not, there is no separation, so the child's margin ventures outward.
If you wanted to always have the margin inside of the parent, a better option might be to apply padding to the parent element, instead of margin to the child.