I'm building a modal with flexbox, that has a two row design:
|-------------------|
| A |
|-------------------|
| |
| B |
| |
| |
|-------------------|
Since both A and B are part of a modal with height express in percentage and not in px I use flexbox in order to give to A an height and then to make B fill the rest of the space with an optional scrollbar if needed.
In order to achieve this I use the following html + css :
<div class="wrapper">
<div class="A"></div>
<div class="B"></div>
</div>
.wrapper {
display: flex;
flex-direction: colum;
height: 100%;
}
.A {
height: 70px;
width: 100%;
}
.B {
margin: 10px 20px 10px 20px;
flex: 1;
overflow-y: auto;
overflow-x: hidden;
}
The problem is that depending on the content of B, the height of A changes. With some content is fixed to 70px, with some other content is maybe 24px and if I inspect the css rules I can see that the height is 24px and when I click on the rule it highlights me the "height: 70px" line of code.
If I remove the "display: flex" in the wrapper the height remains correct with any kind of content but the div B overflow the modal and ignores completely the rule "overflow-y: auto".
How can I solve this?
If you use flex: 0 0 70px; combined with either min-height: 0; or overflow: hidden, it should make sure the A always stays 70px high.
The first 0 is flex-grow which prevent it from grow, the second 0 is flex-shrink which prevent it from shrink, and the min-height/overflow will allow it to also be smaller than its content, which by default it is not (min-height defaults to auto, which prevent a flex item be smaller than its content).
The last 70px is flex-basis which is the Flexbox version for height, and I recommend you use that instead.
Note, you are missing an n in colum for the flex-direction value.
.wrapper {
display: flex;
flex-direction: column;
height: 90vh;
background: lightgray;
}
.A {
flex: 0 0 70px;
width: 100%;
min-height: 0;
background: lightblue;
}
.B {
margin: 10px 20px 10px 20px;
flex-grow: 1;
overflow-y: auto;
overflow-x: hidden;
background: lightgreen;
}
<div class="wrapper">
<div class="A">A</div>
<div class="B">B</div>
</div>
If the contents of B is "taller" than the height of B, B grows in height to somehow accommodate the contents. This causes the height of A to decrease to adjust. In order to disallow A from shrinking, add flex-shrink: 0 to its styles.
Related
I have a "boxHeader" which height is fixed to 64px and a "boxcontent" which I want height to be fixed to the remaining space.
My problem: if the height of the children in the "boxContent" exceed the height of the remaining space, it will also increase the height of "boxContent". And I don't want that, I want the children of "boxContent" to respect the max size (and add scroll)
Edit: The children inside "boxContent" are React Components, I have a "Sider" of Ant Design containing multiple Panel's Collapse AND I have a Content side by side. I want to add a scroll bar on the Sider AND on the Content so both Sider and Content have overflow-y: auto
Can you help me ?
Here the code
<div id="container">
<div id="boxHeader">
<HeaderArea />
</div>
<div id="boxContent">
{...}
</div>
</div>
#container {
display: flex;
flex-flow: column;
height: 100% !important;
min-height: 100% !important;
#boxContent {
/* height: calc(100vh - 64px); this works, but i don't want to calcule the size*/
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
background: white;
}
#boxHeader {
flex: 0 0 64px;
}
body{
height: 100vh; /*100% is also tested*/
}
You can give #boxContent max-height and overflow-y: scroll with these two I think it is going to work. But If it is not can you add your HTML so that I can look and fix it. I hope this line of code fixes your problem.
#boxContent {
max-height:300px; //(for example)
overflow-y: auto;
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
background: white;
}
This question already has answers here:
Can't scroll to top of flex item that is overflowing container
(12 answers)
Closed 4 years ago.
I've been on this for a while now and tried a lot of the solutions I've seen across different Stackoverflow questions / blogposts / ... But I honestly can't figure out what's going wrong.
I've got a flexed div with two divs in there. The top div A has a fixed height, the other div B fills the rest using flex: 1;. If the screen is resized and it's smaller than the height of A + B together, then B will start overflowing. I want it to scroll, but I also want the content to be fully visible when scrolling. For some reason which I can't figure out, the content renders out of the top of div B as you can see in this screenshot of my fiddle:
Some of the previously asked questions got me somewhere. For example setting the body to height: auto;, but then when my screen is bigger than A + B it can't be center aligned anymore. min-height: 0; also doesn't seem to help in this case.
How can I make sure my container overflows but will fully show the content of it?
You can solve the issue by giving .second:
flex-basis: auto;
flex-shrink: 0;
Or, with shorthand: flex: 1 0 auto;
Working example:
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
body {
display: flex;
flex-direction: column;
}
.second {
flex: 1 0 auto;
background: blue;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
min-height: 0;
overflow: auto;
}
.container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 500px;
min-height: 0;
/* added this to make it obvious. Obviously, not needed */
padding: 2rem 0;
}
.container-child {
height: 110px;
background: green;
width: 100%;
}
.container-child:not(:last-child) {
margin-bottom: 30px;
}
<div class="second">
<div class="container">
<div class="container-child"></div>
<div class="container-child"></div>
<div class="container-child"></div>
</div>
</div>
I added some top and bottom padding to .container to make it obvious that it's working - but it's not needed.
Now let's look at why this is happening. When you apply .second { flex:1; } it means:
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
... which allows it to have a smaller size than its contents.
Whenever you have a bigger child centered in a smaller parent, the browser won't provide a scrollbar to top (or to left, when horizontal), because then , if the top of the parent and the top of the child coincide and the child is bigger than the parent, the child is no longer centered, is it?
The same happens when using other centering techniques and you center a bigger child in a smaller parent.
To fix the problem, you need to prevent the child from outgrowing the parent.
In this case, it meant sizing .second based from its content (flex-basis: auto) and not allowing it to shrink: (flex-shrink: 0;).
To better visualize the issue, consider this example:
.left, .right {
position: relative;
border: 1px solid red;
padding: 1rem 5rem;
}
.left {
left: -5rem;
}
.right {
right: -5rem;
}
<div class="left">
I'm taken left
</div>
<div class="right">
I'm taken right
</div>
If the browser provided scrollbars to allow you to scroll to beginning of .left, it would mean that left: -5rem did not apply. I hope that makes sense, I can't explain it better.
I need to put 3 columns inside a container. They are supposed to have the same width and evenly distributed. I use flex for that and it works fine.
In the end I need to insert a collection of "cards" in each column ... Because the number of cards can cause the columns to have a greater height than what can be displayed in the browser, the container (the parent of the columns) has overflow set to scroll. So when that happens you can still scroll down to look at the cards that are at the bottom of the column.
I have two problems that I'd like to fix:
1) As soon as I insert a card in the left column, that columns becomes larger than the other two. If I set the column to flex and set flex-grow to 0 on the card, it makes no difference. I am not sure why?
EDIT:
I fixed #1 by setting width: 33%; on .column.
===========================================================================
2) The left column is not drawn passed the bottom boundary of the browser, even though it contains cards causing the container to potentially overflow. What I want to do is be sure that the column "contains" the cards. How could I achieve that (using flex or not)?
I created a fidle and illustrated this problem with the figure below.
JSFIDDLE is here
1) As soon as I insert a card in the left column, that columns becomes
larger than the other two. If I set the column to flex and set
flex-grow to 0 on the card, it makes no difference. I am not sure why?
flex-grow does not define the width, it define how the available space should be distributed.
You could use flex-basis: 33.333%
2) The left column is not drawn passed the bottom boundary of the
browser, even though it contains cards causing the container to
potentially overflow. What I want to do is be sure that the column
"contains" the cards. How could I achieve that (using flex or not)?
Change the height: 100% on container to min-height: 100%
Stack snippet
html, body
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container
{
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100%; /* changed to 'min-height' */
width: 100%;
box-sizing: border-box;
}
.column
{
display: flex;
flex-direction: column;
flex: 1 1 auto;
background: grey;
margin: 5px;
}
.article
{
margin: 5px;
background: white;
height: 100px;
border: 1px solid orange;
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
To make the columns equal width, instead of flex: 1 1 auto, use flex: 1 1 0 (which is the same as flex: 1).
With flex-basis: auto the width of each column is based on its content, so equal width columns aren't guaranteed.
With flex-basis: 0, the width of all columns is an equal distribution of space in the container.
Here's a more complete explanation of flex-basis and the difference between auto and 0.
Make flex-grow expand items based on their original size
To make the divs respect their height: 100px, add flex-shrink: 0. Flex items have flex-shrink: 1, by default.
Here's a more complete explanation:
What are the differences between flex-basis and width?
To get the container to follow along, see the other answer to this question.
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100vh;
box-sizing: border-box;
}
.column {
display: flex;
flex-direction: column;
background: grey;
margin: 5px;
flex: 1; /* adjustment */
}
.article {
margin: 5px;
background: white;
border: 1px solid orange;
flex: 0 0 100px; /* adjustment */
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
I'm facing a strange issue that might have link with flexbox misbehaving with max-height, but so far I didn't find any pure css solution.
I made a plunker to summarize the problem. If you resize your window to reduce its height, at some point you should have a scrollbar in the first block, but if you get back to a higher height, even if there is enough space, the scrollbar won't disappear unless you put your mouse over it (which feels very bugy) : https://plnkr.co/edit/VsJ7Aw8qZdSM1iJeL7Bj?p=preview
I have a main container (in flex) containing 2 blocks (also in flex).
The main container has its height set to 100%, allowing it to resize itself following the window size.
Both children have a fixed content and an overflow-y set to auto.
The first child has a max-height in % to let more height to the second child.
The issue seems to come from this max-height rule. If you remove it, then there's no problem, but I need this max-height...
I don't want to use something like:
.max { flex: 1 1 auto; }
.all { flex: 3 1 auto; }
because it would make my first block higher than its content depending on the window size. I want the first block to have at most its content height.
So my question is: Is it an implementation issue in many browsers (maybe all, but I only tested it in Chrome, IE10 and IE11), or is something wrong in my logic ?
Thank you.
UPDATE: I used a fixed height for my content in this example, but in my project it's a list of n elements in it. So I can't really set my max-height with px value.
UPDATE2: I can't use vh in .max max-height property because it takes 100vh as 100% of viewport height (basically your browser window height). But in my context, .main is already in other containers. Those containers have already their heights defined and are smaller than my window height.
/* Styles go here */
html {
height: 100%;
}
body {
height: calc(100% - 16px);
}
.main {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
.max,
.all {
display: flex;
flex-direction: column;
width: 100%;
overflow-y: auto;
}
.max {
flex: 0 1 auto;
min-height: 103px;
max-height: 40%;
background-color: green;
}
.all {
flex: 2 1 auto;
min-height: 235px;
background-color: blue;
}
.content {
flex: 0 0 auto;
box-sizing: border-box;
height: 200px;
margin: 5px;
border: 1px dashed black;
background-color: white;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<div class="max">
<div class="content"></div>
</div>
<div class="all">
<div class="content"></div>
</div>
</div>
</body>
</html>
It is a bug, in Chrome, a test in FF and Edge, it works fine.
Since you use full viewport height, change the max-height: 40%; to max-height: 40vh;.
Another way, as in below sample, is to change the 100% in height: 100% to 100vh.
I guess this works better because viewport units like vh is a fixed unit, which percent is not.
Plnkr demo: https://plnkr.co/edit/66W4a2lOI58XLudCmkw9?p=preview
html {
height: 100vh;
}
body {
height: calc(100vh - 16px);
}
.main {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
}
.max,
.all {
display: flex;
flex-direction: column;
width: 100%;
overflow-y: auto;
}
.max {
flex: 0 1 auto;
min-height: 103px;
max-height: 40%;
background-color: green;
}
.all {
flex: 1 1 auto;
min-height: 235px;
background-color: blue;
}
.content {
flex: 0 0 auto;
box-sizing: border-box;
height: 200px;
margin: 5px;
border: 1px dashed black;
background-color: white;
}
<div class="main">
<div class="max">
<div class="content"></div>
</div>
<div class="all">
<div class="content"></div>
</div>
</div>
Yes it feels buggy. If you increase the height of the window the height of the first box does not get updated unless:
you decrease the height again
"put your mouse over it" (did not quite get your meaning here)
IMHO this is a browser bug.
If you set flex-grow to anything greater 0 for the first box, the height gets updated correctly, if you increase the height of the window (as you would expect) But using flex-grow isn't an option as the box could potentially grow bigger than its content.
Rather than using max-height:40% you should use the exact same height as you use for .content and use flex-grow: 1 as well to circumvent the "browser bug"
I have 2 divs that are placed on top of each other. For purposes of alignment, I am using display: flex and flex: column on the div containing these two divs. However, the first div uses the "height 0 padding" trick for videos. The problem I'm having, is that when using flex: column and change the width of the screen, the height doesn't change (and I want the height to change so that it matches the ratio for the video). What ends up happening is that the div stays the same, and the video shrinks within it and it looks ugly because there is extra background.
Plunker: https://plnkr.co/edit/TaeF5f8VufJWPU3GRZPr?p=preview
(in short, I want it such that when I change the width of the browser, the red div's height gets smaller)
CSS
/* Styles go here */
body {
height: 100%;
}
.container {
height: 80vh;
display: flex;
flex-flow: column;
}
.video {
flex: none;
height: 0;
padding-bottom: 30%;
background-color: red;
width: 80%;
}
.next-content {
flex: 1 0 auto;
width: 80%;
background-color: blue;
}
HTML:
<body>
<h1>Hello Plunker!</h1>
<div class="container">
<div class="video"></div>
<div class="next-content"></div>
</div>