I'm trying to create a flexbox layout of fixed height which scrolls the inner content when the inner content is too large.
Additionally if the content doesn't cause scrolling I want to fix a div with buttons to the bottom of the container.
I have a layout which works perfectly in Firefox but in Chrome it causes the bottom button div to clip on top of the content when it's large enough to cause scrolling.
This is the layout rendering properly in Firefox:
This is how it renders improperly in Chrome:
Additionally, this is how it should behave if there's not enough inner content to cause scrolling:
.container {
height: 150px;
width: 300px;
display: flex;
flex-direction: column;
overflow-y: auto;
border: 1px solid #000;
padding: 4px;
}
.options {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.spacer {
flex: 1 1 auto;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: space-between;
}
<div class="container">
<div class="options">
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
</div>
<div class="spacer"></div>
<div class="buttons">
<input type="button" value="Cancel">
<input type="button" value="Save">
</div>
</div>
https://jsfiddle.net/tdghqyuu/1/
Add this to your code:
.container > * {
flex-shrink: 0;
}
An initial setting on flex items, according to the flexbox specification, should be flex-shrink: 1. This means that flex items are permitted to shrink in order to avoid overflowing the container.
Chrome and IE11 appear to be adhering to this guideline.
Other browsers, such as Firefox, Edge and Safari, seem to have flex-shrink
set to 0
by default.
On the other hand, this may have little or nothing to do with flex-shrink
. The problem may relate to the default min-height
and min-width
settings on flex items. (See here: Why don't flex items shrink past content size?)
Or maybe it's a combination of both. It really depends on the browser.
The fact is, browser implementations vary. That's why you have to test.
Spec initial settings are not entirely reliable because
Interventions
An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.
In other words, a browser takes it upon itself to provide settings that it feels are best for its users, regardless of spec guidelines.
Chrome seems to do this a lot. Here are some examples:
One thing appears certain: If you disable flex-shrink
, your layout then works across all browsers. Add this to your code:
.container > * {
flex-shrink: 0;
}
.container>* {
flex-shrink: 0;
}
.container {
height: 150px;
width: 300px;
display: flex;
flex-direction: column;
overflow-y: auto;
border: 1px solid #000;
padding: 4px;
}
.options {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10px;
/* new; for demo only */
}
<div class="container">
<div class="options">
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
</div>
<div class="buttons">
<input type="button" value="Cancel">
<input type="button" value="Save">
</div>
</div>
You may also want to consider moving the scrollbar to the options box only, then you've truly fixed the buttons to the bottom of the screen. Make this adjustment to your code:
.container {
height: 150px;
width: 300px;
display: flex;
flex-direction: column;
/* overflow-y: auto; */
border: 1px solid #000;
padding: 4px;
}
.options {
display: flex;
flex-direction: row;
flex-wrap: wrap;
overflow-y: auto; /* NEW */
flex: 1; /* NEW; may be necessary for overflow to work in some browsers */
}
.container > * {
flex-shrink: 0;
}
.container {
height: 150px;
width: 300px;
display: flex;
flex-direction: column;
/* overflow-y: auto; */
border: 1px solid #000;
padding: 4px;
}
.options {
display: flex;
flex-direction: row;
flex-wrap: wrap;
overflow-y: auto; /* NEW */
flex: 1; /* NEW; may be necessary for overflow to work in some browsers */
}
.buttons {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10px; /* new; for demo only */
}
<div class="container">
<div class="options">
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
</div>
<div class="buttons">
<input type="button" value="Cancel">
<input type="button" value="Save">
</div>
</div>
Also, I removed the spacer element you had. It doesn't seem necessary when there are a multitude of clean ways to create space between items in a flex container.
.container
doesn't need to be "flex", a min-height
property for .options
may be enough:
.container {
height: 150px;
width: 300px;
/*display: flex;*/
flex-direction: column;
overflow-y: auto;
border: 1px solid #000;
padding: 4px;
}
.options {
display: flex;
flex-direction: row;
flex-wrap: wrap;
min-height: 125px;
}
.options > div
{
display: inline-block;
}
.spacer {
flex: 1 1 auto;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: space-between;
}
<div class="container">
<div class="options">
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
<div class="option">
<input type="checkbox"> Option
</div>
</div>
<div class="spacer"></div>
<div class="buttons">
<input type="button" value="Cancel">
<input type="button" value="Save">
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With