Flexbox resize and scrollable overflow
Add min-height: 0
to .flexGrowWrapper
- see demo below:
$("button").click(function() {
$(".resize").toggleClass("small");
});
.resize {
height: 200px;
display: flex;
flex-direction: column;
overflow-y: hidden;
width: 300px;
}
.resize.small {
height: 100px;
}
.heading {
flex: 0 0 auto;
}
.flexGrowWrapper {
border: 2px solid red;
flex-grow: 1;
min-height: 0; /* ADDED */
}
.wrapper {
height: 100%;
overflow-y: auto;
}
.content {
display: flex;
flex-direction: row;
clear: both;
}
<button>
Resize
</button>
<div class="resize">
<div class="heading">
<label>Some heading that wont scroll</label>
</div>
<div class="flexGrowWrapper">
<div class="wrapper">
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
<div class="content">
content
</div>
</div>
</div>
</div>
<div>
Something else here
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scrolling a flexbox with overflowing content
I've spoken to Tab Atkins (author of the flexbox spec) about this, and this is what we came up with:
HTML:
<div class="content">
<div class="box">
<div class="column">Column 1</div>
<div class="column">Column 2</div>
<div class="column">Column 3</div>
</div>
</div>
CSS:
.content {
flex: 1;
display: flex;
overflow: auto;
}
.box {
display: flex;
min-height: min-content; /* needs vendor prefixes */
}
Here are the pens:
- Short columns being stretched.
- Longer columns overflowing and scrolling.
The reason this works is because align-items: stretch
doesn't shrink its items if they have an intrinsic height, which is accomplished here by min-content
.
Horizontal full width with overflow in vertical flexbox
Couple of issues:
- You need to use view-width(
vw
) formin-width
. Changemin-width: 100vh;
tomin-width: 100vw;
. This alone doesn't resolve the issue. - Main issue is because the
.header
is overflowing. You can check this by adding a fat border to it and.container
element. We can fix this using two changes:
.container {
...
width: max-content;
}
.header .col {
...
width: 100px;
}
Demo:
const groups = [];
for (let i = 0; i < 15; i++) {
const rows = [];
for (let j = 0; j < 15; j++) {
rows.push({ cols: ["col 1", "col 2", "col 3", "col 4", "col 5", "col 6", "col 7", "col 8", "col 9" ] });
}
groups.push({ group: 'test' + i, open: false, rows});
}
var app = new Vue({el: '#app', data: { rows: groups } })
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
min-width: 100vw;
width: max-content;
}
.header {
position: sticky;
top: 0;
display: flex;
flex-direction: row;
}
.header .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(250, 189, 189);
padding: 0 2px;
outline: 2px solid black;
width: 100px;
}
.vertical-content {
display: flex;
flex-direction: column;
}
.vertical-content .grouped-row {
flex-grow: 1;
background: rgb(251, 251, 180);
outline: 2px solid black;
display: flex;
flex-direction: column;
}
.vertical-content .row {
display: flex;
flex-direction: row;
width: 100%;
}
.vertical-content .row .col {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
background: rgb(150, 150, 238);
padding: 0 2px;
outline: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<body>
<div class="container" id="app">
<div class="header">
<div class="col">Col 1</div>
<div class="col">Col 2</div>
<div class="col">Col 3</div>
<div class="col">Col 4</div>
<div class="col">Col 5</div>
<div class="col">Col 6</div>
<div class="col">Col 7</div>
<div class="col">Col 8</div>
<div class="col">Col 9</div>
</div>
<div class="vertical-content">
<div class="grouped-row" v-for="row of rows" @click="row.open = !row.open">
<div>
{{ row.group }}
</div>
<div class="row" v-for="actualRow of row.rows" v-if="row.open">
<div class="col" v-for="col of actualRow.cols">{{ col }}</div>
</div>
</div>
</div>
</div>
Can't scroll to top of flex item that is overflowing container
The Problem
Flexbox makes centering very easy.
By simply applying align-items: center
and justify-content: center
to the flex container, your flex item(s) will be vertically and horizontally centered.
However, there is a problem with this method when the flex item is bigger than the flex container.
As noted in the question, when the flex item overflows the container the top becomes inaccessible.
For horizontal overflow, the left section becomes inaccessible (or right section, in RTL languages).
Here's an example with an LTR container having justify-content: center
and three flex items:
See the bottom of this answer for an explanation of this behavior.
Solution #1
To fix this problem use flexbox auto margins, instead of justify-content
.
With auto
margins, an overflowing flex item can be vertically and horizontally centered without losing access to any part of it.
So instead of this code on the flex container:
#flex-container {
align-items: center;
justify-content: center;
}
Use this code on the flex item:
.flex-item {
margin: auto;
}
Revised Demo
Solution #2 (not yet implemented in most browsers)
Add the safe
value to your keyword alignment rule, like this:
justify-content: safe center
or
align-self: safe center
From the CSS Box Alignment Module specification:
4.4. Overflow Alignment: the
safe
andunsafe
keywords and
scroll safety
limitsWhen the [flex item] is larger than the [flex container], it will
overflow. Some alignment modes, if honored in this situation, may
cause data loss: for example, if the contents of a sidebar are
centered, when they overflow they may send part of their boxes past
the viewport’s start edge, which can’t be scrolled to.To control this situation, an overflow alignment mode can be
explicitly specified.Unsafe
alignment honors the specified
alignment mode in overflow situations, even if it causes data loss,
whilesafe
alignment changes the alignment mode in overflow
situations in an attempt to avoid data loss.The default behavior is to contain the alignment subject within the
scrollable area, though at the time of writing this safety feature is
not yet implemented.
safe
If the size of the [flex item] overflows the [flex container], the
[flex item] is instead aligned as if the alignment mode were
[flex-start
].
unsafe
Regardless of the relative sizes of the [flex item] and [flex
container], the given alignment value is honored.
Note: The Box Alignment Module is for use across multiple box layout models, not just flex. So in the spec excerpt above, the terms in brackets actually say "alignment subject", "alignment container" and "start
". I used flex-specific terms to keep the focus on this particular problem.
Explanation for scroll limitation from MDN:
Flex item
considerationsFlexbox's alignment properties do "true" centering, unlike other
centering methods in CSS. This means that the flex items will stay
centered, even if they overflow the flex container.This can sometimes be problematic, however, if they overflow past the
top edge of the page, or the left edge [...], as
you can't scroll to that area, even if there is content there!In a future release, the alignment properties will be extended to have
a "safe" option as well.For now, if this is a concern, you can instead use margins to achieve
centering, as they'll respond in a "safe" way and stop centering if
they overflow.Instead of using the
align-
properties, just putauto
margins on
the flex items you wish to center.Instead of the
justify-
properties, put auto margins on the outside
edges of the first and last flex items in the flex container.The
auto
margins will "flex" and assume the leftover space,
centering the flex items when there is leftover space, and switching
to normal alignment when not.However, if you're trying to replace
justify-content
with
margin-based centering in a multi-line flexbox, you're probably out of
luck, as you need to put the margins on the first and last flex item
on each line. Unless you can predict ahead of time which items will
end up on which line, you can't reliably use margin-based centering in
the main axis to replace thejustify-content
property.
flexbox width inside horizontally scrollable container
Consider the use of inline-flex
instead of flex
and define the width using width
and not flex-basis
.table-wrapper {
width: 500px;
height: 300px;
overflow-x: scroll;
background: rgba(255, 255, 0, 0.2);
}
.table-container {
display: inline-flex; /* UPDATED */
flex-flow: column nowrap;
min-width: 100%; /* UPDATED */
height: 100%;
background: rgba(0, 255, 0, 0.3);
}
.table-header {
display: flex;
flex-flow: row nowrap;
width: 100%;
flex: 0 0 auto;
background: rgba(255, 100, 0, 0.3);
}
.table-cell {
min-width: 100px;
display: flex;
flex: 1 1 auto;
height: 30px;
line-height: 30px;
border: 1px solid blue;
}
.table-body {
display: flex;
flex: 1 1 auto;
border: 1px solid red;
background: rgba(255, 0, 0, 0.3);
}
<div class="table-wrapper">
<div class="table-container">
<div class="table-header">
<div class="table-cell" style="flex: 0 0 180px;width:180px;">header-cell 1</div>
<div class="table-cell">header-cell 2</div>
<div class="table-cell">header-cell 3</div>
<div class="table-cell">header-cell 4</div>
<div class="table-cell" style="flex: 0 0 200px;width:200px;">header-cell 5</div>
<div class="table-cell">header-cell 6</div>
<div class="table-cell">header-cell 7</div>
</div>
<div class="table-body">virtual table here</div>
</div>
</div>
How to make flexbox resize dependant on content size
The problem was that the content had a "hidden" margin. Writing margin:-1vh; fixed the issue :)
Related Topics
Change Checkbox Check Image to Custom Image
Any Way of Using Frames in HTML5
Remove Host Component Tag from HTML in Angular 4
What Does the Clearfix Class Do in CSS
How to Write Backwards Compatible HTML5
What CSS Should I Use to Get a Border Around an Option Tag in Both Firefox and Ie
Rounded Corners on Rectangular Image Using CSS Only
How to Change Side by Side Divs to Stack on Mobile
Changing the Text Selection Color Using CSS
How to Change Content on Hover
Restoring the Value of a Input Type=File After Failed Validation
Google Maps Shows "For Development Purposes Only"
Css: Why Background-Color Breaks/Removes the Box-Shadow
Why Does Firefox Not Honor CSS Font-Size for Code Tags Wrapped in Pre
Internet Explorer Doesn't Recognise the 'Html' CSS Background Image Tag