How to make flex container not force scroll on body - html

In the code sample I did:
reset all margins/paddings to 0
set body height to 100%
set flex container height to 96%
set flex container margin-top to 2%
Now this gives me a scroll on the body even if the flex containers height + margin-top only sums up to 98%, so my question is, can't I use margin-top is this way and where does the extra space come from forcing the body to scroll?
Setting the body to overflow:hidden removes the scroll, but that feels more like a band-aid and not considered as a solution (unless this is a "behavior-by design" which needs that in this case).
Edit
Ways like remove the margin-top on the flex container and then set a padding-top: 2%; on the body or use position: relative; top: 2%; on the container or with absolute: position; I can make it work as expected though, but the case here is why margin-top: 2% doesn't do it.
* {
box-sizing: border-box;
padding: 0;
margin: 0
}
html, body {
background-color: gray;
height: 100%;
}
.outer {
display: flex;
flex-flow: column;
margin: 0 auto;
height: 96%;
width: 50%;
margin-top: 2%;
}
.top {
background-color: lightgray;
}
.middle {
background-color: darkgray;
}
.the-rest {
flex: 1 0 auto;
background-color: lightgray;
}
<div class="outer">
<div class="top">
top
</div>
<div class="middle">
middle
</div>
<div class="the-rest">
content
</div>
</div>

This is because percentage margins are based on the width of the containing block / element...in this case, the body.
W3C Spec
MDN
A <percentage> relative to the width of the containing block. Negative values are allowed.

I usually use vh and vw on html and body. In this demo I applied vh only since it looked like a vertically oriented demo. I also make the body and html position: relative. With vw and vh there's a real measured length that other elements (children of ::root) can actually set their relative measurements of 100%. I use position: relative because it makes the html, body sit rigidly inside the view port and the viewport units keep the body, html on the edge at 100vh and 100vw.
UPDATE
I think this behavior is due to collapsing-margins So if there's an illogical margin-top behavior, keep that in mind. There are several very specific circumstances that result in this odd behavior and there are a few solutions as well. The solution for these circumstances are as follows:
body, html { height: 100vh; } /* no relative or absolute positioning */
.outer { min-height: 100%; margin-top: -2%; } /* It's explained that the positive numbered margin-top is not effective and yet the negative value works but not like a normal negative value!? o_0
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
position: relative;
background-color: gray;
height: 100vh;
}
.outer {
display: flex;
flex-flow: column;
margin: 0 auto;
min-height: 100%;
width: 50%;
margin-top: - 2%;
border-top: 0;
}
.top- {
background-color: lightgray;
}
.middle {
background-color: darkgray;
}
.the-rest {
flex: 1 0 auto;
background-color: lightgray;
}
.marker {
position: absolute;
outline: 1px solid red;
}
<span class="marker" style="top: 0; left: 0;">top:0|left:0</span>
<span class="marker" style="top: 0; right: 0;">top:0|right:0</span>
<div class="outer">
<div class="top">
top
</div>
<div class="middle">
middle
</div>
<div class="the-rest">
content
</div>
</div>
<span class="marker" style="bottom: 0; left: 0;">bottom:0|left:0</span>
<span class="marker" style="bottom: 0; right: 0;">bottom:0|right:0</span>

Related

CSS: Make inner div 100% body width without using position:absolute - is it possible?

Lets assume for some reason I can not change the HTML, neither use JavasScript. Lets assume the position of #content_actual depends on the height of #element. #element has a flexible height.
Is there a solution for this problem?
HTML:
<div id="content">
<div id="element">ABCDE</div>
<div id="content_actual">FGHIJ</div>
</div>
CSS:
#content {
width:960px;
margin: 0 auto;
}
#element {
// width: 100% of body width
// position: everything but position absolute or fixed
}
Similar to Paulie_D's (apparently we were sharing brainwaves) but this uses percentage to counter the container width. No idea how well supported this would be:
https://jsfiddle.net/7w2cwqfq/4/
<div id="content">
<div id="element">ABCDE</div>
<div id="content_actual">FGHIJ</div>
</div>
#content {
width:200px;
margin: 0 auto;
background: yellow;
}
#element {
position: relative;
left: calc(-50vw + 50%);
width: 100vw;
background: red
}
A combination of relative positioning, viewport units and calc.
Codepen Demo
NOTE: this breaks as soon as the viewport is less than the container width. Media queries would be required at that point.
#content {
width: 480px; /* numbers changed for this Snippet */
margin: 0 auto;
background: green;
padding: 50px;
}
#element {
height: 50px;
line-height: 50px;
width: 100vw;
position: relative;
right: calc(50vw - 240px); /* second value 50% of container width */
background: lightblue;
}
<div id="content">
<div id="element">ABCDE</div>
<div id="content_actual">FGHIJ</div>
</div>
It should also be noted that the container cannot have overflow:hidden for this technique to work.

CSS container height issue

My container is not touching my footer for the majority of cases and I'm not sure what's going on.
So here is my CSS code:
html {
min-height: 100%;
position: relative;
}
body {
margin: 0;
width: 100%;
height: 100%;
}
section {
height: 100%;
}
#container {
overflow: auto;
width: 80%;
margin: 0 auto;
background: red;
height: 100%;
}
.footer {
width: 100%;
position: absolute;
left: 0;
bottom: 0;
}
Here's my HTML:
<body>
<div id="container">
<section>
<p>Content goes here</p>
</section>
</div>
<div class="footer">Content</div>
</body>
So I have all of the heights set for parent elements,but there's still a big gap between the container and the footer. In cases where the content takes up the whole page, the footer and container ends up touching, but the content for some reason gets lost in the footer. How can I solve this issue?
Height based on percentage are tricky. vh is much better for such purposes.
Here is the solution: JSfiddle
#container {
overflow: hidden;
width: 80%;
margin: 0 auto;
background: red;
height: 100vh;
}
Make one adjustment to your CSS:
Add height: 100% to the html element.
html {
height: 100%; /* NEW */
min-height: 100%;
position: relative;
}
This will clear the way for all child elements to recognize their percentage heights, and the container will expand. Your min-height: 100% will still work because min-height overrides height.
DEMO: http://jsfiddle.net/au6tcodc/
(You'll notice a vertical scrollbar on the container in the demo. This is caused by the overflow: auto declaration in #container. If you want to remove the scrollbar switch to overflow: hidden (see all overflow values).

How can I make this 100% height + column overflow layout work in Firefox and IE?

I have a three-column layout that takes up 100% width and height of the browser (with padding). This layout contains two columns which also take up 100% height and should scroll independently.
Here is a jsfiddle: http://jsfiddle.net/KdZ9A/2/. Here is how it looks in Chrome (desirable -- individual columns scroll):
and Firefox and IE (undesirable -- body is scrolling):
This works perfectly in Chrome; however, the in Firefox and IE (10), the entire page scrolls instead of individual columns scrolling. I only want the columns to overflow and scroll -- not the body. Any idea how to make this work in Firefox and IE?
I've also tried a bit different approach using absolute positioning of the columns' contents: http://jsfiddle.net/KdZ9A/3/.
Here is the HTML I am using:
<div id="container">
<div id="inner">
<div id="palette">palette</div>
<div id="list">
<div class="content"></div>
</div>
<div id="editor">
<div class="content"></div>
</div>
</div>
</div>
I'm using absolute positioning to achieve 100% height and then display of table and table-cell inside that to achieve 100% height of the columnns:
* {
padding: 0;
margin: 0;
}
html, body {
width: 100%;
height: 100%;
}
body {
position: relative;
}
#container {
background-color: #f1f1f1;
position: absolute;
left: 20px;
right: 20px;
top: 20px;
bottom: 20px;
}
#inner {
display: table;
height: 100%;
}
#inner > div {
display: table-cell;
}
#palette {
min-width: 180px;
max-width: 180px;
width: 180px !important;
background-color: pink;
}
#list {
width: 55%;
min-width: 350px;
background-color: cyan;
}
#editor {
width: 45%;
min-width: 400px;
background-color: magenta;
}
.content {
overflow: auto;
height: 100%;
}
I was 5 minutes from giving up and HOLY CRAP...I GOT IT WORKING
http://jsfiddle.net/gFX5E/15/
This is based on the different approach I mentioned. I needed to wrap .content divs and make the wrappers position relative. I also added some headers to the columns.
HTML:
<div class="content-wrap">
<div class="content">
...
</div>
</div>
CSS:
.content-wrap {
position: relative;
height: 100%;
}
.content {
overflow: auto;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
Seems to work in Chrome, Safari, Firefox, and IE8+.
And here is a more semantic HTML5 version which also adds a header to the top: http://jsfiddle.net/gFX5E/20/. I believe this will require use of html5shiv to work in IE8.
If you are willing to settle for a fixed total width, here is how:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box; /* makes filling up easier */
}
html, body {
height: 100%;
}
#container {
position: relative;
width: 980px;
height: 100%;
margin: auto;
background: grey;
}
#palette {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 800px;
background: pink;
}
#list {
position: absolute;
left: 180px;
top: 0;
bottom: 0;
right: 450px;
background: cyan;
overflow-y: auto;
}
#editor {
position: absolute;
left: 530px;
top: 0;
bottom: 0;
right: 0;
background: magenta;
overflow-y: auto;
}
</style>
</head>
<body>
<div id="container">
<div id="palette">Palette</div>
<div id="list" class="content"></div>
<div id="editor" class="content"></div>
</div>
<script>
$(function() {
for (var i=0; i<20; i++) {
$('.content').append('<p>Lorem ipsum [truncated for SO]</p>');
}
});
</script>
</body>
</html>
Demo on this Codepen: http://codepen.io/anon/pen/aqgCm?editors=100.
This is a pretty old post, but I thought I'd comment.
If you display: flex instead of display: table in your 1st example that should fix the issue.
Also setting your scroll container height to 100vh will also do the trick.
You have to understand that the browsers apply scroll only when they understand the size( i.e. height and width) of the content is greater than the size specified for it. In your case, the height you have specified for the div is 100%. This effectively tells the browser to keep increasing the size of the div till all the content fits in completely. Hence, this creates the situation where scroll isn't needed as the browser would 'fit' the entire content within this div.
So if you want the div (or the paragraphs contained in it) to be scrollable, then you would have to specify the height and then tell the browser to provide a scroll for the content that won't fit in the specified size.
I am not sure if you want the individual 'paragraphs' to be scrollable or the entire div( which contains these paragraphs) to be scrollable. In either case, you would need to provide a fixed height for the scroll to be useful. Your paragraph tag would need to have the following CSS applied to it :
p {
height: 200px; /*Some fixed height*/
overflow-y: scroll;
}
Here's an example of this: http://jsfiddle.net/y49C3/
In case you want your div called 'content' to be scrollable (as opposed to the paragraphs), then you would have to apply the aforementioned CSS to the div instead.
.content {
overflow-y: scroll;
height: 500px;
}
You can see that here: http://jsfiddle.net/qF7Mt/1/
I have tested this in Firefox (29) and IE 10 and it works fine!!!
Hope this helps!!!

Setting height 100% to div causes vertical scrollbar

There are only 3 lines of text in a div in body. The background color was filling only up to those 3 lines of text.
As I wanted the color to fill up 100% vertical of the browser, I just set the CSS height properties of html & body to 100%. But the vertical scrollbar shows up now. How can I hide/remove it?
I tried overflow:hidden for html as well as div properties but no luck. Using Firefox.
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
}
.logodiv {
width: 100%;
background-color: #243640;
height: 40px;
color: #FF1442;
}
.content {
/* Firefox 3.6+ */
background: -moz-radial-gradient(circle, #1a82f7, #2F2727);
width: 100%;
height: 100%;
overflow: hidden;
}
<div class="logodiv">
ITEMS LIST
</div>
<div class="content">
line1<br> line2
<br> line3
<br>
</div>
Use min-height: 100% instead and add a negative margin to .content to shift it up:
.logodiv {
position: relative;
z-index: 10;
}
.content {
background-color: gold;
min-height:100%;
margin-top: -40px;
}
.content:before {
content: ' ';
display: block;
height: 40px;
}
JSBin Demo #1
Note: In order to push down the content of .content element, I used ::before pseudo-element selector, another option could be:
Using box-sizing: border-box and padding-top: 40px CSS declarations:
.content {
background-color: gold;
min-height:100%;
margin-top: -40px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding-top: 40px;
}
JSBin Demo #2
PS: Nowadays, All major modern browsers support ::before pseudo-element and/or box-sizing property. But if you're looking for the traditional way which all browsers support, you can create a .spacer division, as the first child of .content element and set height: 40px; to .spacer.
JSBin Demo #3
Make logodiv absolutely positioned:
http://jsfiddle.net/Gcduf/
.logodiv
{
width:100%;
background-color:#243640;
height:40px;
color:#FF1442;
position: absolute;
top: 0;
}
Use the calc() function.
Make this adjustment to your code:
.content { height: calc(100% - 40px); }
.logodiv {
height: 40px;
background-color: #243640;
color: #FF1442;
}
.content {
height: calc(100% - 40px);
}
body {
height: 100vh;
}
* {
margin: 0;
padding: 0;
}
<div class="logodiv">
ITEMS LIST
</div>
<div class="content">
line1<br> line2
<br> line3
<br>
</div>
You've got .logodiv with height: 40px.
And its sibling .content with height: 100%.
Add these two together and they overflow the height of their container (body). That's the reason for the vertical scrollbar.
With the calc() function you can set up mathematical expressions using addition (+), subtraction (-), multiplication (*), and division (/) as component values.

Centering a child inside it's parent

I'm working to center #child within #parent at 100% height and width. Why does setting the #child top position to 10% work, but using 10% as a margin-top does not?
http://jsfiddle.net/rbtstudio/SCmfG/
<style>
html {
height: 100%;
}
body {
height: 100%;
overflow: hidden;
}
#parent {
width: 100%;
height: 100%;
background-color: #323232;
}
#child {
width: 80%;
height: 80%;
background-color: #eaeaea;
margin: 0 auto;
position: relative;
top: 10%;
}
/*
#child {
width: 80%;
height: 80%;
margin-top: 10%;
margin-right: auto;
margin-bottom: 0;
margin-left: auto;
}
*/
</style>
<div id="parent">
<div id="child"></div>
</div>
The issue here is called "collapsing margins". You can read more about them in the css spec.
http://www.w3.org/TR/CSS21/box.html#collapsing-margins
It's not that the margin isn't working, it's that the margin is collapsing, causing the margin to apply to the top of the parent box.
You'll notice that when the margin is applied to the child, the parent is moved down.
http://jsfiddle.net/SCmfG/4
One workaround (of many) to avoid the collapsing of margins is to add overflow: hidden to the parent element:
http://jsfiddle.net/SCmfG/5/
EDIT: Another important point to keep in mind (which was in another answer which has since been deleted) is that all percentage margins are based on a percentage of the width of the element, even top and bottom.