How to prevent a flex item height to overflow due to it's content
You need to add min-height: 0
to your .main-content
CSS rule. That prevents that element from stretching to contain its children and pushing the footer offscreen (which is the bad behavior that you're trying to avoid).
This happens because flex items (children of a flex container) establish a default minimum main-size, based on their contents, and will refuse to be smaller than that minimum. In your case (with the outer flex container being vertically-oriented), "main-size" is height
, and the flex item in question (.main-content
) is establishing a content-based min-height
.
(If you want the list items to be scrollable, then you may want to also add overflow-y:auto
to .main-content
)
Prevent flex items from overflowing a container
Your flex items have
flex: 0 0 200px; /* <aside> */
flex: 1 0 auto; /* <article> */
That means:
The
<aside>
will start at200px
wide.Then it won't grow nor shrink.
The
<article>
will start at the width given by the content.Then, if there is available space, it will grow to cover it.
Otherwise it won't shrink.
To prevent horizontal overflow, you can:
- Use
flex-basis: 0
and then let them grow with a positiveflex-grow
. - Use a positive
flex-shrink
to let them shrink if there isn't enough space.
To prevent vertical overflow, you can
- Use
min-height
instead ofheight
to allow the flex items grow more if necessary - Use
overflow
different than visible on the flex items - Use
overflow
different than visible on the flex container
For example,
main, aside, article {
margin: 10px;
border: solid 1px #000;
border-bottom: 0;
min-height: 50px; /* min-height instead of height */
}
main {
display: flex;
}
aside {
flex: 0 1 200px; /* Positive flex-shrink */
}
article {
flex: 1 1 auto; /* Positive flex-shrink */
}
<main>
<aside>x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x </aside>
<article>don't let flex item overflow container.... y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y </article>
</main>
html/css flex: How to prevent item in container exceed parent container height?
To solve this with flexbox you need to wrap the box you want to scroll and add overflow-x: hidden;
to the wrapping container. To fix some extra space use the calc()
method. This happens, when is used height: 100vh;
on a scrollable element.
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--header-height: 60px;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #f1f1f1;
}
header {
min-height: var(--header-height);
display: flex;
justify-content: center;
align-items: center;
}
main {
display: flex;
}
.box1,
.box2 {
display: flex;
flex: 1 0 50%;
border: 1px solid red;
}
.box2 {
height: calc(100vh - var(--header-height));
background-color: antiquewhite;
overflow-x: hidden;
}
.scrollable {
width: 100%;
display: flex;
overflow-y: auto;
}
<div class="container">
<header>Hello Flex!</header>
<main>
<div class="box1">1</div>
<div class="box2">
<div class="scrollable">
2<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> 2
<br />2<br />2<br /> very long content, should be scrollable and NOT stretch parent.
</div>
</div>
</main>
</div>
Prevent a flex items height from expanding to match other flex items
This is an old solution.
My answer is superseded by this new answer by Aaron usingalign-self
. That is a better solution that does not rely on a CSS quirk.
As long as the flex container has no height itself, you can set height: 0%
on the first flex item. Because it has no height to inherit from its parent, any percentage height will cause it to collapse. It will then grow with its contents.
Example
In this example I have removed the -webkit
prefix. It's only really required for Safari and the prefix can be added above the non-prefixed version. I also removed flex-direction: row
as it is the default value.
.container {
display: flex;
}
.flexbox-1 {
flex: 1;
height: 0%;
border: solid 3px red;
}
.flexbox-2 {
flex: 2;
border: solid 3px blue;
height: 200px;
margin-left: 10px;
}
<div class="container">
<div class="flexbox-1">.flexbox-1</div>
<div class="flexbox-2">.flexbox-2</div>
</div>
Prevent flex item from exceeding parent height and make scroll bar work
Short Answer
Instead of flex: 1
, use flex: 1 1 1px
.
Make these two adjustments in your code:
#messagelist {
/* flex:1; */
flex: 1 1 1px; /* new */
}
#messagecontents {
/* flex:1; */
flex: 1 1 1px; /* new */
}
revised codepen
Explanation
In most cases, as you have noted, adding min-height: 0
to flex items in a column-direction container is enough to correct the problem.
In this case, however, there's an additional obstacle: flex-basis
.
You're applying the following rule to flex items #messagelist
and #messagecontents
: flex: 1
.
This is a shorthand rule that breaks down to:
flex-grow: 1
flex-shrink: 1
flex-basis: 0
(source: https://www.w3.org/TR/css-flexbox-1/#flex-common)
2019 UPDATE: Since the posting of this answer in 2018, it appears that Chrome's behavior has changed and is now uniform with Firefox and Edge. Please keep that in mind as you read the rest of this answer.
In Chrome, flex-basis: 0
is enough to trigger an overflow, which generates the scrollbars. (2019 update: This may no longer be the case.)
In Firefox and Edge, however, a zero flex-basis
is insufficient. This is probably the more correct behavior in terms of standards compliance as MDN states:
In order for
overflow
to have an effect, the block-level container must have either a set height (height
ormax-height
) orwhite-space
set tonowrap
.
Well, flex-basis: 0
meets none of those conditions, so an overflow condition should not occur. Chrome has probably engaged in an intervention (as they often do).
An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.
To meet the "standardized behavior", which would enable an overflow to occur in Firefox and Edge, give flex-basis
a fixed height (even if it's just 1px).
Prevent flex items from stretching
You don't want to stretch the span in height?
You have the possiblity to affect one or more flex-items to don't stretch the full height of the container.
To affect all flex-items of the container, choose this:
You have to set align-items: flex-start;
to div
and all flex-items of this container get the height of their content.
div { align-items: flex-start; background: tan; display: flex; height: 200px;}span { background: red;}
<div> <span>This is some text.</span></div>
How to prevent flex-items from overflowing flex parent with no wrap?
Set display: inline-flex
on the .parent
class to change it to an inline element. This will also force the .parent
to expand to contain its children. Then by setting min-width: 100%
on the .parent
class, it will force it to expand to 100% of the containing element.
.parent {
display: inline-flex;
flex-direction: row;
background-color: red;
min-width: 100%;
}
.child {
min-width: 100px;
flex-basis: 0px;
flex-grow: 1;
margin: 5px;
height: 100px;
background-color: blue;
}
How to make a flex item not fill the height of the flex container?
The align-items
, or respectively align-content
attribute controls this behaviour.
align-items
defines the items' positioning perpendicularly to flex-direction
.
The default flex-direction
is row
, therfore vertical placement can be controlled with align-items
.
There is also the align-self
attribute to control the alignment on a per item basis.
#a { display:flex;
align-items:flex-start; align-content:flex-start; }
#a > div { background-color:red; padding:5px; margin:2px; } #a > #c { align-self:stretch; }
<div id="a"> <div id="b">left</div> <div id="c">middle</div> <div>right<br>right<br>right<br>right<br>right<br></div> </div>
Related Topics
Are CSS3 Properties Like Animate Too CPU Intensive
Font Color in HTML Email - Gmail
Font Size. What How to Be Sure Of
Fixed Button Over a Scrollview
iPhone Viewport Height Too Large in Landscape Mode
What Is The Biggest Usable Number for Use in Calc() in CSS
Adding Background Image to Shiny Navbarpage
CSS Grid: Grid-Row Not Working in Chrome Browser
Remove White Space Under Footer
Nested Mixins or Functions in Sass
How to Reverse-Engineer a Webkit Matrix3D Transform
Sass Importing Without Compiling
How to Always Center a Flexible Square in Viewport with Pure CSS