I have a simple page with 3 div on top of each other but I cannot get the middle content div to use all the vertical space available on screen. Note that top and bottom height cannot be fixed and that it has to be compatible with IE9.
HTML
<div class="container">
<div>Top</div>
<div class="content">Middle</div>
<div>Bottom</div>
</div>
CSS
.container {
background-color: #dddddd;
}
.content {
height: 100%;
min-height: 100%;
}
I also put that on Fiddle to demonstrate the issue: http://jsfiddle.net/quaxkq40/
Thanks.
If flexible box layout is an option, it can be done simply by displaying the container as a flex box and the nested <div>s as flex items:
html, body {
height: 100%;
margin: 0;
}
.container {
background-color: #dddddd;
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
}
<div class="container">
<div>Top</div>
<div class="content">Middle</div>
<div>Bottom</div>
</div>
Note: Vendor prefixes omitted due to brevity.
Otherwise, you'll probably end up with CSS tables:
html, body {
height: 100%;
margin: 0;
}
.container {
background-color: #dddddd;
display: table;
height: 100%;
}
.container > div {
display: table-row;
}
.content {
height: 100%;
}
<div class="container">
<div>Top</div>
<div class="content">Middle</div>
<div>Bottom</div>
</div>
Each of the above methods has its own pros/cons, choose one that meets the requirements with care.
You could display the div's inside .container as table rows.
body, html {
height: 100%;
}
.container {
background-color: #dddddd;
display: table;
height: 100%;
width: 100%;
}
.container>div {
display: table-row;
}
.content {
height: 100%;
min-height: 100%;
background: lightblue;
}
UPDATED FIDDLE
Related
I have a pretty simple page setup in the following manner using flexboxes:
The blue div is supposed to make up 25% in height and the violet div 75%. In case there are too many lines in the blue div, it should stay the same size an show a scrollbar. This works for a few lines, but breaks at some point and the blue div overflows and grows into the violet one. I'm new to flexboxes, so I don't really understand why this is happening. Would I be better off not using flexboxes? Thankful for any hints or pointer at this point.
This is the code I use (run in full page):
function lines(noLines) {
var text = "line</br>".repeat(noLines);
document.getElementById("lower").innerHTML = text;
}
* {
box-sizing: border-box;
}
.body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#static1 {
height: 30px;
width: 100%;
background-color: red;
}
#static2 {
height: 40px;
width: 100%;
background-color: orange;
}
#content {
display: flex;
flex: 1;
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
}
#upper {
flex: 3 0;
background-color: violet;
}
#lower {
flex: 1;
background-color: blue;
overflow: auto;
}
<div class="body">
<div id="static1">Some static div</div>
<div id="static2">Another static div. Flexbox below fills rest of remaining screen.</div>
<div id="content">
<div id="left">
Left part, fixed width in percentage.</br>
Click to enter lines into the bottom right:</br>
<button onclick=lines(20)>Few Lines</button>
<button onclick=lines(200)>Many Lines</button>
</div>
<div id="right">
<div id="upper">Flexbox with flex=3.</div>
<div id="lower">Flexbox with flex=1.</div>
</div>
</div>
</div>
For the overflow property to work properly, the container needs an actual height or max-height. Flex heights (you have flex: 1 on .content) won't cut it.
In order for overflow to have an effect, the block-level container
must have either a set height (height or max-height) or
white-space set to nowrap. ~ MDN
Since you already know the height of the primary container (100vh) and the first two rows (30px and 40px), the rest is simple using the calc() function.
function lines(noLines) {
var text = "line</br>".repeat(noLines);
document.getElementById("lower").innerHTML = text;
}
.body {
display: flex;
flex-direction: column;
height: 100vh; /* adjustment */
}
#static1 {
flex-shrink: 0; /* disable shrinking */
height: 30px;
/* width: 100%; */
background-color: red;
}
#static2 {
flex-shrink: 0; /* disable shrinking */
height: 40px;
/* width: 100%; */
background-color: orange;
}
#content {
height: calc(100vh - 70px); /* new */
display: flex;
/* flex: 1; */ /* may work in some browsers, but not reliable */
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
}
#upper {
flex: 3 0;
background-color: violet;
}
#lower {
flex: 1;
background-color: aqua; /* adjusted for illustration */
overflow: auto;
}
body {
margin: 0; /* new; override browser default */
}
* {
box-sizing: border-box;
}
<div class="body">
<div id="static1">Some static div</div>
<div id="static2">Another static div. Flexbox below fills rest of remaining screen.</div>
<div id="content">
<div id="left">
Left part, fixed width in percentage.<br> Click to enter lines into the bottom right:<br>
<button onclick=lines(20)>Few Lines</button>
<button onclick=lines(200)>Many Lines</button>
</div>
<div id="right">
<div id="upper">Flexbox with flex=3.</div>
<div id="lower">Flexbox with flex=1.</div>
</div>
</div>
</div>
jsFiddle demo
I hope this is what you mean, but If I'm wrong, apologies. The problem I can see lies in the way you are using flex: 1 & flex: 3 to define the proportions of the right column, without specifying to what height their parent container has, i.e. #right has no height, so the box can always expand as it gets more filled with content.
Please try this, I hope this works and if I can answer anything else, just ask please.
The only thing I changed was your CSS and added max-height: calc(100vh - 70px); to the #right div. And changed overflow: auto; to overflow-y: scroll;
* {
box-sizing: border-box;
}
.body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#static1 {
height: 30px;
width: 100%;
background-color: red;
}
#static2 {
height: 40px;
width: 100%;
background-color: orange;
}
#content {
display: flex;
flex: 1;
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
max-height: calc(100vh - 70px);
}
#upper {
flex: 3;
height: 75%;
background-color: violet;
}
#lower {
flex: 1;
height: 25%;
background-color: blue;
overflow-y: scroll;
}
Change the top part of CSS to this:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
I'm trying to display an app bar and three images in a column, that uses 100% of the height of the screen. The images are supposed to use the whole width of the column with the rest being cut off. I can get it working with just divs, but I'm having trouble when using images.
Here is a version to illustrate how it should look like. This has an app bar of height 50 and three "images" that fill the rest of the space:
https://codepen.io/Meerpohl/pen/zYxRKRV
And here is what I get with images. The images stretch the heights of my divs and ultimately of everything else, resulting in that scrollbar. Instead I need thin slices of the images.
html, body {
height: 100%;
margin: 0;
}
.root {
height: 100%;
display: flex;
flex-direction: column;
}
.appbar {
height: 50px;
text-align: center;
background-color: coral;
}
.container {
flex: 1;
}
.item {
height:33.33%;
overflow:hidden;
}
img {
width: 100%;
object-fit: cover;
}
<div class="root">
<div class="appbar">
This is a nice app bar
</div>
<div class="container">
<div class="item">
<img src="http://www.kleines-meerwasseraquarium.de/wp-content/uploads/2016/02/Zitronengrundel.jpg">
</div>
<div class="item">
<img src="http://www.kleines-meerwasseraquarium.de/wp-content/uploads/2016/02/Zitronengrundel.jpg">
</div>
<div class="item">
<img src="http://www.kleines-meerwasseraquarium.de/wp-content/uploads/2016/02/Zitronengrundel.jpg">
</div>
</div>
</div>
https://codepen.io/Meerpohl/pen/eYmVdro
The code is the same in both cases. One just uses text instead images.
.item {
position: relative;
height:33%;
overflow:hidden;
}
img {
position: absolute;
transform: translateY(-50%);
width: 100%;
object-fit: cover;
}
this should work i think!
i'm on the train right now, so I can't give you a pen.
You can position the image absolute in the parent div (this should be relative) and translateY so it is centered.
Hope this is what you want to do ;)
use this!
img {width: 100%; object-fit: cover; max-height: 33.33vh; }
Try this:
html, body {
height: 100%;
margin: 0;
}
.root {
height: 100%;
display: flex;
flex-direction: column;
}
.appbar {
height: 50px;
background-color: coral;
display: flex;
justify-content: center;
align-items: center;
}
.container {
height: calc(100vh - 50px);
display: flex;
flex-direction: column;
}
.item {
overflow: hidden;
display: flex;
flex: 1;
}
img {
width: 100%;
object-fit: cover;
}
added calc to .container and display:flex on .item, removed some unused properties.
Codepen: https://codepen.io/Liveindream/pen/NWPygpx
I have the following html and css:
HTML:
<body style="height:100%;">
<div class="fb-container">
<div class"somedatadiv">
Some data
</div>
<div class="anotherdiv">
data
</div>
</div>
</body>
CSS:
.fb-container {
display: flex;
flex-wrap: no-wrap;
align-items: stretch;
// min-height: 100%;
}
.somedatadiv {
width: 75%;
max-width: 345px;
backround: grey;
padding: 30px;
}
for some reason the flex container div is not stretching 100% of the body height.
(the browser I am using is chrome for this "demo/application/site")
You need to add display:flex to the parent tag for and then flex:1 to the child to enable the child to expand to 100% of parent.
.fb-container {
background-color:green;
flex: 1;
}
.somedatadiv {
width: 75%;
max-width: 345px;
background-color: grey;
padding: 30px;
}
<body style="height:100vh;display:flex;">
<div class="fb-container">
<div class="somedatadiv">
Some data
</div>
<div class="anotherdiv">
data
</div>
</div>
</body>
add this and it should work. Demo: https://jsfiddle.net/jacobgoh101/svtewj9j/
html,
body {
height: 100%;
}
body {
display: flex;
}
update: if you want the fb-container to stay full width
add flex: 1 1 100%; to it
.fb-container {
flex: 1 1 100%;
}
update: complete solution https://jsfiddle.net/jacobgoh101/svtewj9j/2/
html,
body {
height: 100%;
}
body {
display: flex;
}
.fb-container {
display: flex;
flex-wrap: no-wrap;
align-items: stretch;
flex: 1 1 100%;
}
.somedatadiv {
flex: 1 1 75%;
max-width: 345px;
backround: grey;
padding: 30px;
box-sizing: border-box;
}
There was some code missplaced in the MCV template.
that was messing up the style/layout.
this post is not relevant for other users so it will be removed/deleted
update: Can not delete this post:
I have two divs streched to the size of the parent(body), but on application of inline-block attribute the divs are placed one below the other instead of beside each other.
I want them to be placed beside each other, such that i need to scroll horizontally instead of vertically.
jsFiddle - http://jsfiddle.net/wJ73v/364/
html
<div class="red"></div>
<div class="red-blue"></div>
css
html {
height: 100%;
width: 100%;
}
body {
margin:0;
padding: 0;
height: 100%
}
.red {
background-color: red;
height: 100%;
width: 100%;
display: inline-block;
}
.red-blue {
background: linear-gradient(red, blue);
height: 100%;
width: 100%;
display: inline-block;
}
Do like this, add white-space: nowrap to the body
html,
body {
height: 100%;
margin: 0;
white-space: nowrap;
}
.red {
background-color: red;
height: 100%;
width: 100%;
display: inline-block;
}
.red-blue {
background: linear-gradient(red, blue);
height: 100%;
width: 100%;
display: inline-block;
}
<div class="red"></div>
<div class="red-blue"></div>
If you want to get rid of that vertical scroll, you can set overflow-y: hidden; on the body.
If you need the scroll, you can use flexbox.
html, body {
height: 100%;
margin: 0;
display: flex;
}
.red {
background-color: red;
height: 100%;
width: 100vw;
}
.red-blue {
background: linear-gradient(red, blue);
height: 100%;
width: 100vw;
}
<div class="red"></div>
<div class="red-blue"></div>
If I make a flexbox with 2 children and column flow and set the second child to flex-grow 1 the second child expands to fill the flexbox. This works
(ps: Didn't want to clutter the example with safari support so use Chrome or Firefox)
* {
box-sizing: border-box;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
color: white;
}
#outer {
display: flex;
flex-flow: column;
height: 100%;
}
#top {
background-color: red;
}
#bottom {
background-color: blue;
flex: 1 0 auto;
}
<div id="outer">
<div id="top">top</div>
<div id="bottom">bottom (blue)</div>
</div>
But, if I then put a child #inside inside #bottom and set its height to 100% it doesn't increase its height to match even though the flexbox has stretched #bottom.
added css
#inside {
background-color: green;
height: 100%;
}
html
<div id="outer">
<div id="top">top</div>
<div id="bottom">
<div id="inside">inside</div> <!- added ->
</div>
</div>
* {
box-sizing: border-box;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
color: white;
}
#outer {
display: flex;
flex-flow: column;
height: 100%;
}
#top {
background-color: red;
}
#bottom {
background-color: blue;
flex: 1 0 auto;
}
#inside {
background-color: green;
height: 100%;
}
<div id="outer">
<div id="top">top</div>
<div id="bottom">
<div id="inside">inside (green)</div>
</div>
</div>
So I add a height: 100% to #bottom but now bottom is as big as #outer instead of the flex stretched size.
#bottom {
background-color: blue;
flex: 1 0 auto;
height: 100%; /* added */
}
* {
box-sizing: border-box;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
color: white;
}
#outer {
display: flex;
flex-flow: column;
height: 100%;
}
#top {
background-color: red;
}
#bottom {
background-color: blue;
flex: 1 0 auto;
height: 100%;
}
#inside {
background-color: green;
height: 100%;
}
<div id="outer">
<div id="top">top</div>
<div id="bottom">
<div id="inside">inside (green) (would not scroll if working)</div>
</div>
</div>
How do I get #bottom to stretch to fit the flexbox and also get a the child #inside to be 100% height of its container #bottom?
Flex has a quirk where you need to set the height to 0.
Change the #bottom rule's height property to this height: 0;
For the inside to work I changed it to "position: absolute" and as well added a position:relative to the bottom
Update
If you don't want to use absolute position, you can set these 2 css rules like this:
(Note though, that this propagates the original issue if a new inner div is used like the first one)
#bottom {
position: relative;
background-color: blue;
flex: 1 0 auto;
height: 0;
display: flex;
}
#inside {
background-color: green;
flex: 1 0 auto;
}
Sample using "position: absolute"
* {
box-sizing: border-box;
}
html, body {
margin: 0;
width: 100%;
height: 100%;
color: white;
}
#outer {
display: flex;
flex-flow: column;
height: 100%;
}
#top {
background-color: red;
}
#bottom {
position: relative;
background-color: blue;
flex: 1 0 auto;
height: 0;
}
#inside {
background-color: green;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
<div id="outer">
<div id="top">top</div>
<div id="bottom">
<div id="inside">inside (would not scroll if working)</div>
</div>
</div>
How do I get #bottom to stretch to fit the flexbox and also get a the child #inside to be 100% height of its container #bottom?
Just add two lines of code to the CSS.
CSS
#bottom {
background-color: blue;
flex: 1 0 auto;
display: flex; /* NEW */
}
#inside {
flex: 1; /* NEW */
background-color: green;
}
DEMO: http://jsfiddle.net/wf2L8dse/
Here's what's happening:
You have a flex container (#outer) with two flex items (#top and #bottom).
#outer is in column alignment.
#bottom has flex: 1 (i.e., flex-grow: 1), so it occupies all available height in the container.
A new element (#inside) is made a child of #bottom and must occupy the same height as parent.
Solution:
Make #bottom a (nested) flexbox. This activates default flex rules.
One such rule is align-items: stretch, which tells flex items (#inside) to stretch the full height of their container. (Height, in this case, because the flex-direction is row, by default.)
Then apply flex: 1 (or flex-grow: 1) to #inside, so it expands the full width of the container.
Addressing the height: 100% issue
I'm not sure there's anything wrong with your code. You have applied height: 100% to #inside and, as required by the spec when using percentage heights, specified a height for all parent elements including body and the root element (html).
The only thing you may want to consider (to remove the vertical scrollbar on the browser window), is applying overflow: hidden to body.
DEMO: http://jsfiddle.net/wf2L8dse/1/