Flex element not filling up 100% height in flex container [duplicate] - css

This question already has answers here:
How to stretch flex child to fill height of the container?
(5 answers)
Closed 5 years ago.
I have the following markup:
.container {
display: flex;
width: 500px;
}
.col1 {
background: red;
height: 100%;
width: 50px;
}
.col2 {
background: blue;
flex: 1;
height: 200px;
}
<div class="container">
<div class="col1"></div>
<div class="col2"></div>
</div>
And I'm expecting it to look like this:
But instead when rendered in the browser and inspected, the height of .col1 is 0px. I'd expect it to be 200px since .col2 stretches the height of the container to that size. What am I doing wrong?

Remove height: 100% from .col1, like:
.col1 {
background: red;
width: 50px;
}
Have a look at the snippet below:
.container {
display: flex;
width: 500px;
}
.col1 {
background: red;
width: 50px;
}
.col2 {
background: blue;
flex: 1;
height: 200px;
}
body {
margin: 0;
}
<div class="container">
<div class="col1"></div>
<div class="col2"></div>
</div>
Hope this helps!

Related

How to fit 2 elements to page height?

I'm developing an app with the interface that is supposed to fit the page (only some internal elements may have scrolling). The basic layout consists of a header and the main section:
<div class="page">
<Navigation/> <!-- a Vue component -->
<main class="page__main">
...
</main>
</div>
currently, CSS has hardcoded height of the header (Navigation):
.page {
height: 100vh;
}
.page__main {
height: calc(100vh - 80px); /* 80px is the height of the header */
}
I'd like to get rid of this hardcoded bit but make sure .page__main's height gets no larger than 100vh - height of Navigation. Is there a way to do this without JS? I suspect that there are some options that can be used with
.page {
height: 100vh;
display: flex;
flex-direction: column;
}
but just using that with
.page__main {
flex-shrink: 1;
}
doesn't work: .page__main has children which use height in percents and once I set flex-shrink: 1; instead of height: calc(100vh - 80px); those grow and the interface is broken.
To illustrate the problem better, here's the current state:
body { padding: 0; margin: 0; }
.page {
height: 100vh;
background: blue;
}
.page__navigation {
height: 80px;
background: gray;
}
.page__main {
height: calc(100vh - 80px);
}
.part1 {
height: 50%;
background: #eeeeee;
overflow-y: scroll;
}
.part2 {
height: 50%;
background: #cccccc;
}
<div class="page">
<div class="page__navigation">nav stuff</div>
<main class="page__main">
<div class="part1">
this one usually has more elements than it could contain and those are shown with scrolling
<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line
</div>
<div class="part2">
some
</div>
</main>
</div>
and here's what happen when I try to "set height" via flex:
body { padding: 0; margin: 0; }
.page {
height: 100vh;
display: flex;
flex-direction: column;
background: blue;
}
.page__navigation {
height: 80px;
background: gray;
}
.page__main {
flex-shrink: 1;
}
.part1 {
height: 50%;
background: #eeeeee;
overflow-y: scroll;
}
.part2 {
height: 50%;
background: #cccccc;
}
<div class="page">
<div class="page__navigation">nav stuff</div>
<main class="page__main">
<div class="part1">
this one usually has more elements than it could contain and those are shown with scrolling
<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line
</div>
<div class="part2">
some
</div>
</main>
</div>
You can consider a nested flexbox container and don't forget the use of min-height:0; to allow the elements to shrink.
body { padding: 0; margin: 0; }
.page {
height: 100vh;
display: flex;
flex-direction: column;
background: blue;
}
.page__navigation {
height: 80px;
background: gray;
}
.page__main {
flex-grow: 1; /* Fill the remaining space*/
display:flex; /* Nested Container*/
flex-direction:column;
min-height:0; /* Allow the element to shrink */
}
.part1 {
flex-basis: 50%;
background: #eeeeee;
overflow-y: scroll; /* Allow the element to shrink */
}
.part2 {
flex-basis: 50%;
min-height:0; /* Allow the element to shrink */
background: #cccccc;
}
<div class="page">
<div class="page__navigation">nav stuff</div>
<main class="page__main">
<div class="part1">
this one usually has more elements than it could contain and those are shown with scrolling
<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line
</div>
<div class="part2">
some
</div>
</main>
</div>
Use flex-grow. Keep everything as the second one (flex one) and change:
Edit
.page {
height: 100vh;
display: flex;
flex-direction: column;
background: blue;
}
.page__main {
height: 100%;
min-height: 0;
flex: 1 1 auto;
}
Three value flex means flex: flex-grow | flex-shrink | flex-basis.
Flex-grow tells our element whether or not it can take up additional space.
Flex-shrink works very similarly to flex-grow, only instead of dealing with extra space, it deals with space not needed by an elements content.
Flex basis is best used when in conjunction with either flex-shrink or flex-grow.
You can check this article to understand better.
I would suggest css-grid approach : -
.page {
background: gray;
display: grid;
grid-template-rows: 100px auto;
height: 100vh;
color: white;
}
.nav {
grid-row: 1/2;
background: brown;
}
.main {
grid-row: 2/3;
background: green;
display: grid;
grid-template-rows: 30% 70%;
}
.part1 {
overflow: auto
}
.part2 {
background: blue
}
<div class="page">
<div class="nav">Nav</div>
<div class="main">
<div class="part1">
this one usually has more elements than it could contain and those are shown with scrolling
<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line
</div>
<div class="part2">
some
</div>
</div>
</div>
</div>

How to get a div to fill the remainder of the screen height [duplicate]

This question already has answers here:
Make a div fill the height of the remaining screen space
(41 answers)
Closed 4 years ago.
I've got a div, I need the bottom div to fill the remainder of the screen and show a scroll bar. The bottom div is not showing a scroll bar.
JSFiddle
.page {
position: fixed;
top: 0;
width: 100%;
height: 100%;
margin: 0;
padding: $menu-height 0 0 0;
box-sizing: border-box;
}
.sidebar {
width: 500px;
float: left;
height: 100%;
box-sizing: border-box;
background: #ddd;
border-right: 1px solid red;
}
.top {
height: 200px;
background: #eee;
}
.bottom {
background: #ccc;
overflow-y: auto;
}
.filler-content {
height: 2000px;
}
<div class="page">
<div class="sidebar">
<div class="top">
top
</div>
<div class="bottom">
<div class="filler-content">
bottom
</div>
</div>
</div>
</div>
If I understood your problem correctly, display: flex is your friend.
Add display: flex; flex-direction: column; to your .sidebar and flex: 1; to your .bottom and that should do it. If I misunderstood, just let me know in a comment and I'll try to help otherwise
Demo: http://jsfiddle.net/qy5fL29t/23/
I would use a flexbox solution as it will make it a lot simpler and get rid of the need for using floats (we shouldn't be abusing them in the day of css3)
html,
body {
height: 100%;
margin: 0;
}
.page {
height: 100%;
display: flex; /* this one is so that you don't need to float the sidebar and can insert a main area that will take up the rest of the width */
flex-direction: column;
flex-wrap: wrap;
}
.sidebar {
width: 500px;
height: 100%;
display: flex; /* this is so we can get bottom to take any height top doesn't need */
flex-direction: column;
background: #ddd;
border-right: 1px solid red;
}
.top {
flex-basis:200px;
min-height: 200px; /* these two are to force top to be 200px otherwise flex may recalculate based on available space */
max-height: 200px;
background: #eee;
}
.bottom {
flex-grow: 1; /* this forces bottom to grow to fill the space top doesn't take */
overflow-y: auto;
}
/* test and example below */
.filler-content {
height:1000px;
}
.main {
flex-grow: 1;
background: white;
}
<div class="page">
<div class="sidebar">
<div class="top">
top
</div>
<div class="bottom">
<div class="filler-content">
bottom
</div>
</div>
</div>
<div class="main">
</div>
</div>
Replace your css with this
.sidebar {
width: 500px;
float: left;
height: 100%;
box-sizing: border-box;
background: #ddd;
border-right: 1px solid red;
}
.top {
height: 200px;
background: #eee;
}
.bottom {
background: #ccc;
overflow-y: scroll;
height:200px
}
.filler-content {
height:2000px;
}
<html>
<body>
<div class="page">
<div class="sidebar">
<div class="top">
top
</div>
<div class="bottom">
<div class="filler-content">
bottom
</div>
</div>
</div>
</body>
</div>
</html>
You can use this code for bottom div srollbar.
.bottom {
background: #ccc;
overflow-y: auto;
height:200px;
}

IE11 - Flex child takes full height [duplicate]

This question already has answers here:
How to make a sticky footer using flexbox in IE11?
(5 answers)
flex container min-height ignored in IE
(3 answers)
Closed 5 years ago.
I have a problem with Flexbox on IE11.
What I'm trying to do is to have one parent with 3 children. One header with a fixed size, a footer with a fixed size and in between a content area which should take the remaining space.
Here's the code - it works with Chrome but not with IE11:
.parent {
display: flex;
flex-direction: column;
max-height: 500px;
}
.header {
flex: 0 0 auto;
background: red;
height: 50px;
}
.content {
background: yellow;
flex: 1 1 auto;
position: relative;
overflow-y: scroll;
}
.footer {
flex: 0 0 auto;
background: blue;
height: 50px;
}
.long-item {
height: 2000px;
}
<div class="parent">
<div class="header">Header</div>
<div class="content">
<div class="long-item">Content</div>
</div>
<div class="footer">Footer</div>
</div>
I already went throught the open issues but couldn't really find a solution.
That is one of IE's flex bugs, the min-height when using flex direction column "bug".
In your case, add display: flex to the body and flex-grow: 1; to the parent (flex-basis: 100% or width: 100% will work as well).
body {
display: flex;
}
.parent {
flex-grow: 1; /* fill horizontal space */
display: flex;
flex-direction: column;
max-height: 500px;
}
.header {
flex: 0 0 auto;
background: red;
height: 50px;
}
.content {
background: yellow;
flex: 1 1 auto;
position: relative;
overflow-y: scroll;
}
.footer {
flex: 0 0 auto;
background: blue;
height: 50px;
}
.long-item {
height: 2000px;
}
<div class="parent">
<div class="header">Header</div>
<div class="content">
<div class="long-item">Content</div>
</div>
<div class="footer">Footer</div>
</div>

Make full-width without setting `width` [duplicate]

This question already has answers here:
Setting div width to 100% minus certain amount of px
(5 answers)
Expand a div to fill the remaining width
(21 answers)
Closed 6 years ago.
I will simulate what i need to achieve.
for example, i want that #2 took the whole space, remaining of 100% - 180px.. how to achieve that?
p.s. seems flexbox is more supported over devices than calc - http://css3clickchart.com/#flexbox
You can use flexbox model as shown below. Adding flex: auto; will allow the right content to use remaining width.
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#parent {
display: flex;
height: 100%;
}
#left {
width: 180px;
background-color: hotpink;
}
#right {
flex: auto;
background-color: dodgerblue;
}
<div id="parent">
<div id="left"></div>
<div id="right"></div>
</div>
Use css calc
Here with a example.. This might help:
.class {
width: -moz-calc(100% - 100px);
width: -webkit-calc(100% - 100px);
width: calc(100% - 100px);
}​
You can use float: left and overflow: hidden.
aside {
float: left;
width: 30%;
background: beige;
}
article {
overflow: hidden;
background: brown;
color: white;
}
<aside>
sidebar
</aside>
<article>
content
</article>
There are many ways to do this. One simple way is below.
1st way: Simple inline-block
.container {
width: 100%;
height: 600px;
background-color: #f2f2f2;
}
.sidebar {
background-color: red;
width: 180px;
height: 600px;
float: left;
}
.main-content {
display: inline-block;
background-color: green;
}
<div class="container">
<div class="main-content">Main Content</div>
<div class="sidebar">Sidebar</div>
</div>
Fair warning though: In this case the .main-content will only take the space it needs, and will not actually be full width. So If you want to set background to it, you should actually set the backround to .container.
2nd way: Use calc for width
.container {
width: 100%;
height: 600px;
background-color: #f2f2f2;
position: relative;
}
.sidebar {
background-color: red;
width: 180px;
height: 600px;
float: left;
}
.main-content {
float: right;
background-color: green;
width: calc(100% - 180px);
height: 600px;
}
<div class="container">
<div class="main-content">Main Content</div>
<div class="sidebar">Sidebar</div>
</div>
3rd way: use Flex
.container {
width: 100%;
height: 600px;
background-color: #f2f2f2;
display: flex;
}
.sidebar {
background-color: red;
width: 180px;
height: 600px;
}
.main-content {
background-color: green;
flex: auto;
}
<div class="container">
<div class="sidebar">Sidebar</div>
<div class="main-content">Main Content</div>
</div>
Flexbox is probably the nicest solution, but saidly old browsers don't support it.
4th way of doing this is the oldfasioned way with faking tables:
.container {
width: 100%;
height: 600px;
background-color: #f2f2f2;
display: table;
}
.sidebar {
background-color: red;
width: 180px;
display: table-cell;
}
.main-content {
display: table-cell;
background-color: green;
}
<div class="container">
<div class="sidebar">Sidebar</div>
<div class="main-content">Main Content</div>
</div>

Fix width of a flex column based on another

I have a wrapper of 500px and 2 columns. The second column is 200px width (flex: 0 0 200px).
If in the first there is an element > 300px the first column will expand according to this element.
How can I stop the first column from growing, basing only the width of the wrapper and the second column?
Fiddle here: https://jsfiddle.net/b58aatdr/3/
#hello {
display: flex;
width: 500px;
}
#hello > div {
height: 50px;
}
#hello > div:first-child {
background-color: yellow;
}
#hello > div:last-child {
background-color: red;
flex: 0 0 200px;
}
#baddiv {
width: 400px;
height: 20px;
background-color: purple;
}
<div id="hello">
<div>
<div id="baddiv"></div>
</div>
<div></div>
</div>
Set max-width: 300px to your first div if you want it to adjust itself up to 300px and use width: 300px; if you want it to always be 300px even if content is less wide.
Update based on comment
The 2:nd div group uses another trick, position: absolute, where one doesn't need to set any width, it uses the parent and the right div to restrict the left div from growing beyond the 300px.
Note also, this is a normal behavior how element works, if they don't have a fixed/max width set, they grow (or in some cases wrap) to fit their content.
Update 2 based on comment
The 3:rd div group uses display: table instead of flex, where one doesn't need to set any width.
.hello {
display: flex;
width: 500px;
}
.hello > div {
height: 50px;
}
.hello > div:last-child {
background-color: red;
flex: 0 0 200px;
}
.baddiv {
width: 400px;
height: 20px;
background-color: purple;
}
/* alt. 1 */
.hello.nr1 > div:first-child {
background-color: yellow;
max-width: 300px;
}
/* alt. 2 */
.hello.nr2 > div:first-child {
flex: 1;
position: relative;
background-color: lime;
}
.inner {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
/* alt. 3 */
.hello.nr3 {
display: table;
table-layout: fixed;
width: 500px;
}
.hello.nr3 > div {
height: 50px;
display: table-cell;
}
.hello.nr3 > div:first-child {
background-color: cyan;
}
.hello.nr3 > div:last-child {
background-color: red;
width: 200px;
}
<div class="hello nr1">
<div>
<div class="baddiv"></div>
</div>
<div></div>
</div>
<br>
<div class="hello nr2">
<div>
<div class="inner">
<div class="baddiv">
</div>
</div>
</div>
<div></div>
</div>
<br>
<div class="hello nr3">
<div>
<div class="baddiv"></div>
</div>
<div></div>
</div>

Resources