<html> , <body> , padding, margin, 100vh and calc() - html

Consider the following code snippet:
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
background-color: green;
min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink;"></section>
As expected, the body element fills the entire viewport in green and on top there is a section element in pink.
Now, suppose you want to do something else very simple like set a margin in the section element: style="min-height: 50px; background-color: pink; margin-bottom: 10px;". Unexpectedly, a blue strip from the html element appears in the bottom of the viewport.
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
background-color: green;
min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink; margin-bottom: 10px;"></section>
Question 1) Why this behaviour? It doesn't make sense to me.
One way to correct this behavior is including padding and min-height calc() adjustments in the body element:
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
padding-bottom: 1px;
background-color: green;
min-height: calc(100vh - 1px);
}
<section style="min-height: 50px; background-color: pink; margin-bottom: 10px;"></section>
However, this solution requires such a gimmick that I'm not comfortable with.
Question 2 Is there a better solution? (ie: more intuitive and more readable)

You are facing a margin-collapsing issue. The bottom margin you applied to your section is collpasing with the bottom margin of the body and thus its applied to the body instead of the section.
As you can read here:
The top and bottom margins of blocks are sometimes combined
(collapsed) into a single margin whose size is the largest of the
individual margins (or just one of them, if they are equal), a
behavior known as margin collapsing.
Margin collapsing occurs in three basic cases:
Adjacent siblings
Parent and first/last child
Empty blocks
That's why in your case you have 10px of margin bottom that adds the scroll to your page since body has a min-height:100vh
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
background-color: green;
min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>
To avoid such behavior you need to simply avoid margin to collpase. So you can include a small padding like you did or a border then don't forget to also add box-sizing:border-box to avoid changing the height and use calc.
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
background-color: green;
min-height: 100vh;
border-bottom:1px solid transparent;
/* OR padding-bottom:1px */
box-sizing:border-box;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>
You can also use flex as there is no margin collpasing with flex (check links below for more method):
html {
margin: 0;
padding: 0;
background-color: blue;
}
body {
margin: 0;
padding: 0;
background-color: green;
min-height: 100vh;
display:flex;
flex-direction:column;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>
Some links that may help you to get more information:
https://css-tricks.com/what-you-should-know-about-collapsing-margins/
How do I uncollapse a margin?
CSS margin terror; Margin adds space outside parent element
Margin on child element moves parent element
Margin collapsing in flexbox

I also don't know why such behavior but you can try with following CSS to overcome this situation:
body {margin: 0; padding: 0; background-color: green; position:absolute; left:0; top:0; right:0; bottom:0; overflow:auto;}

Related

Is there a way to prevent anything overflowing out of an html element through automatically resizing children?

In the example below, is there a way to override the size of the h1 tags so they do not overflow (I do not want to just hide the overflow).
We really want the 'strictContainer' to be 100px of height and not bigger. I searched for an analoguous to size:auto but found nothing.
h1 {
height: 80px; border:solid black
}
.strictContainer {
height: 150px; border:solid gold
}
<div class="strictContainer">
<h1>Hello
</h1>
<h1>Hello
</h1>
</div>
Assuming you cannot modify the original CSS. You can override the size of h1 using a new rule make it have more precedence.
One way to fit both the h1 tags in the container is to make them have equal heights:
/* original rules */
h1 {
height: 80px;
border: 2px solid black
}
.strictContainer {
height: 150px;
border: 2px solid gold;
}
/* overrides */
.strictContainer>h1 {
/* need to override default margins */
margin: auto 0;
/* make them have equal heights*/
height: 50%;
box-sizing: border-box;
/* uncomment following to have auto height */
/*height: auto;*/
}
<div class="strictContainer">
<h1>Hello</h1>
<h1>Hello</h1>
</div>
User agents(browsers) put default styles on some html elements. For example, Chrome has following style on h1 tags by default:
h1 {
display: block;
font-size: 2em;
margin-block-start: 0.67em;
margin-block-end: 0.67em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
In order to fit both the tags we need to override margins. I used margin: auto 0;. This means vertical margin is auto and horizontal margin is 0.
We've used box-sizing: border-box; to make borders part of the dimensions. Otherwise we would have to calculate height using height: calc(50% - 4px);
solution 2 You can make the container a flexbox:
/* original rules */
h1 {
height: 80px;
border: 2px solid black
}
.strictContainer {
height: 150px;
border: 2px solid gold;
}
/* overrides */
.strictContainer {
display: flex;
flex-direction: column;
justify-content: space-around; /* play with this */
}
.strictContainer>h1 {
/* need to override default margins */
margin: 0;
height: auto;
flex: 0 0 auto;
/* for 50% height use this */
/*flex: 1 0 auto;*/
}
<div class="strictContainer">
<h1>Hello</h1>
<h1>Hello</h1>
</div>
Note: In your code snippet you've used 150px height for the container so I've used the same. If your issue is with margins then you can use
You can use overflow: hidden to hide any content that may overflow, but I think you are asking for height: min-content.
.container {
width: 10em;
padding: 0.5em;
height: min-content;
background: peachpuff;
}
.content {
height: 5em;
border: 1px solid red;
}
<div class="container">
<div class="content">Hello this is some content la la la la la</div>
</div>
Overflow hidden is used to hide element that overflows
overflow:hidden
/**
other values are visible(default),scroll and auto
ww3schools.com/css/css_overflow.asp
**/
/*
you can remove the default setting
for box-sizing you can check out the following link
https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
*/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/*
I highly recommend you to use % or vh/vw instead of px
It makes your website responsive
*/
h1 {
height: 50%;
border: 2px solid black;
}
.strictContainer {
height: 150px;
border: 2px solid gold;
}
<div class="strictContainer">
<h1>Hello</h1>
<h1>Hello</h1>
</div>

How do I remove default spacing around my header strip

Really simple code, the strip I created has a margin or spacing around it and I want it to fill the whole top side of the page.
.header {
background: #555;
color: #f1f1f1;
height: 100px;
/* width: 100%; */
margin: 0;
padding: 0;
border: none;
}
<div class="header" id="myHeader"></div>
These are the margins that come from body.
In CSS you can set the margins of body to 0.
body {
margin: 0;
}
Also note that your <html></html> tags should be surrounding your entire html and your <body></body> tags should be holding all representational elements.
To fill the whole top side of the page, you should set the body's margin to 0px.
.header {
background: #555;
color: #f1f1f1;
height: 100px;
/* width: 100%; */
margin: 0;
padding: 0;
border: none;
}
body {
margin: 0px;
}
<div class="header" id="myHeader"></div>

100% Height Div with Margin or Padding Scrollbar Issue

I'm having trouble eliminating the vertical scrollbar when applying a 50px padding (black) to the .background style.
html, body {height:100%; margin: 0; padding:0;}
div.background
{
width: 500px;
height: 100%;
background-color: black;
padding: 50px;
}
div.transbox
{
width: 100%;
height: 100%;
background-color: #ffffff;
position: relative;
background-color: rgba(255,255,255,0.3);
}
div.transbox p
{
margin: 50px;
position: absolute;
bottom: 0;
color: white;
}
This is what it looks like
http://jsfiddle.net/sm6LLgp4/2/
If I remove the top and bottom padding (black), the scrollbars are gone, but I've also lost my padding:
http://jsfiddle.net/sm6LLgp4/3/
How can I maintain the 50px padding all around without the vertical scrollbar?
Insert box-sizing:border:box, than it works.
*{
box-sizing:border-box;
}

100% Not Working

I'm having an issue with the age-old problem of 100% height. I know this problem is asked a lot, and I have reviewed this, this, this and countless more. I want to create a basic fixed header, side navigation and main article area, that looks like this:
But, for some reason it's looking like the following (I put 200px padding in the blue bar just to have it appear).
My HTML looks like the following:
<!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<section>
<nav></nav>
<article></article>
</section>
</body>
</html>
And my CSS looks like this:
* { -moz-box-sizing: border-box; background-color: transparent; border: 0 none; color: #000000; list-style: none outside none; margin: 0; outline: medium none; padding: 0; text-decoration: none; }
body, html { height: 100%; }
header {
background: #6c6363;
top: 0;
z-index: 100;
height: 100px;
left: 0;
position: fixed;
right: 0;
}
section {
min-height: 100%;
overflow: auto;
position: relative;
padding-top: 100px;
}
nav {
background-color: #747feb;
float: left;
min-height: 100%;
padding-bottom: 200px;
width: 150px;
}
article {
background: #74eb8a;
margin: 20px 20px 20px 170px;
min-height: 100%;
padding: 20px;
position: relative;
}
As you can see, nothing too special. I know that section needs 100% height, and so does body and html. I can position the nav and acticle absolutely, and make something like this:
But, in my actual site (I simplified it for this), the side navigation has drop-downs, which will change the navigation height dynamically. This causes the following to happen:
Absolutely positioned elements won't change the height of the relative wrapper, so I need to float them. However, floating them doesn't make the height become 100%.
I have even made a JSFiddle to show the problem: http://jsfiddle.net/g8VjP/
If anybody can help me out, I'll really appreciate it.
Thank you!
PS: I'm all for using calc() if it works!
SOLUTION
I modified Mayank's answer and managed to come up with a solution. I had to add a couple wrappers, but it worked. My HTML now looks like the following:
<!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<section>
<nav></nav>
<div class="cell-wrap">
<div class="table-wrap">
<article></article>
</div>
</div>
</section>
</body>
</html>
With the key being the cell-wrap and table-wrap. I have the nav is one table-cell and the .cell-wrap is another. With the nav having a fixed with, the .cell-wrap fills in the rest. However, I want spacing around the article, so I added .table-cell and made that into a table. That then expands and fills the height and width of the .cell-wrap. I then add 30px padding to give a space around the article (because margins don't work on table-cells) and made the article a table cell.
A bit confusing, but it works!
My CSS is as follows:
* { -moz-box-sizing: border-box; background-color: transparent; border: 0 none; color: #000000; list-style: none outside none; margin: 0; outline: medium none; padding: 0; text-decoration: none; }
body, html { height: 100%; }
header {
background: #6c6363;
top: 0;
z-index: 100;
height: 100px;
left: 0;
position: fixed;
right: 0;
}
section {
display: table;
height: 100%;
min-height: 100%;
padding-top: 100px;
position: relative;
width: 100%;
}
nav {
background-color: #657182;
display: table-cell;
min-height: 100%;
width: 150px;
}
.cell-wrap {
display: table-cell;
height: 100%;
min-height: 100%;
}
.table-wrap {
display: table;
height: 100%;
padding: 30px;
width: 100%;
}
article {
background: none repeat scroll 0 0 #FFFFFF;
display: table-cell;
min-height: 100%;
padding: 20px 20px 120px;
z-index: 1;
}
Here's the fiddle. Not sure why there's a scroll bar at the bottom though, but it seems fine if you show it just normally in your browser.
height: 100% means 100% of the containing block's height. Your containing block, section, does not have a defined height (but a min-height instead). You can either:
Change min-height: 100% on section to height: 100%. or...
Keep min-height: 100% and add a height: 1px (or anything less than 100%) which will be overridden by min-height.
The key here is to have a height property set on the parent.
display:table and display:tabel-cell are you friends here mate!!
Updated your fiddle to slight workarounds and here you go : DEMO
CSS to modify :
section {
min-height: 100%;
overflow: auto;
position: relative;
padding-top: 100px;
display:table;/* addition */
}
article {
background: #74eb8a;
margin: 0px 20px 0px 170px;
min-height: 100%;
width:100%;
height: 100%;
position: relative;
display:table-cell; /* addition */
}
Additionally i took the liberty to remove the extra padding that you have placed inside article , insert a div or section inside article and assign padding to it if it works!!
try this :
nav {
background-color: #747feb;
width: 150px;
position : absolute;
top : 100px;
left : 0;
bottom : 0;
}
article {
background: #74eb8a;
position: absolute;
top : 100px;
left : 150px ; /* nav width*/
bottom : 0;
right : 0;
}

How do I use the Sticky Footer CSS?

I've taken a look at the sticky footer CSS and have tried to make changes to my CSS so I could get this concept but no luck as I can't change html & body to 100% height.
Here's the sticky footer CSS that I'd like
And here's the link to my web page that I'd like it on
& Here's my CSS
/* Main content styles */
body {
font-family: Helvetica Neue: Regular;
}
html, body, div, h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 0;
border: 0;
}
/* Container */
#container {
margin: 0 auto;
width: 960px;
}
/* Content */
#content {
width: 642px;
float: right;
padding: 20px 0 0 0;
}
#content h1 {
padding: 0 0 20px 0;
margin: 0 0 20px 20px;
border-bottom: 1px solid #94b9c4;
}
.article {
padding: 5px 20px;
}
.articleimg {
float: left;
padding: 0 25px 0 0;
}
/* Footer */
#footer {
text-align: left;
position: relative;
width: 642px;
float: right;
clear: both;
}
#footer p {
font-family: Helvetica Neue: Regular;
font-size: 12px;
color: #94b9c4;
padding: 10px 0 0 0;
margin: 0 0 20px 20px;
border-top: 1px solid #94b9c4;
}
The only code that is important when using a sticky footer with CSS is the position attribute for the footer. In the HTML, make sure that the footer div is a child of the body:
HTML
<body>
<div class="content">...</div>
<div class="footer">...</div>
</body>
The reason it needs to be a child of the body is because position in CSS is based on the positioning of its closest ancestor. If you position the footer absolutely within another <div> than you always have to be cognizant about that containers position. Anyway, the CSS should be like so:
CSS
.footer {
position: fixed;
bottom: 0;
left: 0; // remove this if you have a specified width for the footer
right: 0; // remove this too
height: 100px; // you can change this
}
The previous code should create a footer that spans the whole bottom of the page with 100px height. This will stick the footer to the bottom of the page no matter what. However, you must also keep in mind that this footer will need to be accounted for so that it does not cover your content. I typically will add a padding on the bottom of my content area roughly the same as the height of my footer. Hope this helps!
Even though this footer you use in your question will work, let me show you another way, that uses less code in both CSS and HTML. This will create a footer, that is sticky to the bottom of the viewport or the content, depending which is longer. So this one is not fixed.
HTML
<body>
<h1>Any content without the need of a wrapper</h1>
<footer></footer>
</body>
CSS
html {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
}
body {
/* the margin compensates the footer's height plus and margin if you want one */
margin: 0 0 100px 0;
}
footer {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
}
Demo
Try before buy
on your page, keep as the child of the body. for example:
<body>
<div class="main">
<p>"paragraph"</p>
</div>
<footer>
<p>Created by </p>
</footer>
</body>
in css file
body {
.
.
.
display: flex;
flex-direction: column;
min-height: 100vh;
}
.main {
flex-grow: 1;
}