I am using CSS FlexBox to design my website. (See example below)
In FlexBox, "Flex:1" attribute will make sure all the items in the container are re-sized according to the widest item.
However, in Internet Explorer 10/11 this does not work unless you specify the width of the item. (Using flex-basis). The problem is that once you specify a flex-basis value, it becomes static and no longer shrinks or grows according to the content.
Is there some solution in IE without making the width static?
Thanks!
Example (IE - Bug, Chrome - Correct Behaviour): https://codepen.io/dsomekh/pen/BRoreL
<html>
<style>
.parent{
display: flex;
justify-content:center;
}
.table{
display:flex;
flex-direction:row;
}
.element{
flex:1;
border: 5px solid skyblue;
display:flex;
}
</style>
<div class="parent">
<div class="table">
<div class="element">First element - small.</div>
<div class="element">Second element - contains more text and first element will resize accordingly. How do we acheive this in IE?</div>
</div>
</div>
</div>
</html>
Updated
In this case IE need a width set, combined with flex: 1 1 0
.parent {
display: flex;
justify-content: center;
}
.table {
display: flex;
/* flex-direction: row; row is default so this is not needed */
}
.element {
flex: 1 1 0; /* changed */
width: 100%; /* added */
border: 5px solid skyblue;
display: flex;
}
<div class="parent">
<div class="table">
<div class="element">First element - small.</div>
<div class="element">Second element - contains more text and first element will resize accordingly. How do we acheive this in IE?</div>
</div>
</div>
Related
This question already has an answer here:
Why is a flex item limited to parent size?
(1 answer)
Closed 4 months ago.
I have prepared the following simple sample
This code does not apply max-height to .b when flex-direction is row, and .b overflows.
However, when the flex-direction is column, the max-height is applied and the .b does not overhang due to the max-height. Why is this?
I tried changing align-items:stretch to a value such as flex-start, but I did not see any change.
https://jsfiddle.net/o2fsL9y8/
https://jsfiddle.net/o2fsL9y8/1/
<div class="a">
<div class="b">
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
}
.b {
overflow: auto;
background: blue;
flex: 1 1 auto;
height: 500px;
}
edit
When a large child element is created in .b as shown below, it scrolls without overflowing, regardless of whether flex-direction is specified for row or column.
The difference in behavior looks more and more unnatural, even though it should be doing almost the same thing as the code shown above. Why does it behave this way?
https://jsfiddle.net/o2fsL9y8/3/
<div class="a">
<div class="b">
<div style="height: 500px; background-color: yellow"></div>
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
}
.b {
overflow: auto;
background: blue;
flex: 1 1 auto;
}
overflow is applied to container not child. So that when the child overflows the container maintains its state and apply the overflow property that you have specified in the container.
<div class="a">
<div class="b">
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
overflow: auto;
}
.b {
background: blue;
flex: 1 1 auto;
}
This is hiding the overflow when column and not in row because in column layout the elements have to position with respect to how much height is available. But in row layout they only cares about how much width available and if something overflows you have to deal it within .a.
I have a parent with overflow-y and a fixed height. I wish to center align its child. The content of the child can vary in size, and sometimes it overflows the parent and triggers a scrollbar. In those cases, the top and bottom content of the child is cut out.
I wish the child to be center aligned, but only if it's smaller than the parent. Or it could always be center aligned, but then the content shouldn't be cut out.
Check out the problem here: https://jsfiddle.net/gumy023z/
.parent {
background-color: red;
height: 40px;
overflow-y: scroll;
/* Comment out the flex, and all the content will be available */
display: flex;
justify-content: center;
align-items: center;
}
<div class="parent">
<div class="child">
This is a test <br> This is a test <br> This is a test
</div>
</div>
The alignment will work in the flex axis of a flexbox. So you can switch to a column flexbox and give min-height: 0 (which overrides the default min-width: auto setting for a flex item) for the child element - see demo below:
.parent {
background-color: red;
height: 40px;
overflow-y: auto;
display: flex;
flex-direction: column; /* ADDED */
justify-content: center;
align-items: center;
}
.child {
min-height: 0; /* ADDED */
}
<div class="parent">
<div class="child">
1. This is a test <br> 2. This is a test <br> 3. This is a test
</div>
</div>
Currently, I'm trying to make a list. On the left side images which fit into my "display flex layout" and resize on all browsers. My "flex-grow layout" list 1 for the image and 3 for the description. Without images, everything is fine, but with my image (100% width) it does not fit into the 1/3 of the row ...
Does anybody know a solution?
#main {
height: 100px;
border: 1px solid #c3c3c3;
display: -webkit-flex; /* Safari */
display: flex;
}
#main div:nth-of-type(1) {-webkit-flex-grow: 1;}
#main div:nth-of-type(2) {-webkit-flex-grow: 3;}
#main div:nth-of-type(1) {flex-grow: 1;}
#main div:nth-of-type(2) {flex-grow: 3;}
#main img { width: 100% }
<div id="main">
<div style="background-color:coral;"><img src="http://www.der-eyecatcher.de/wp-content/uploads/2016/02/Lampe-silber-Schirm_1.jpg"></div>
<div style="background-color:lightblue;">Description</div>
</div>
<hr>flex-grow without Image<hr>
<div id="main">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;">Description</div>
</div>
Thank you
Simon
You have the image container – the flex item div – set to flex-grow: 1. That's fine.
Except the default value of flex-basis is auto (spec).
So, you're telling the item that it's initial main size (i.e., flex-basis) should be the size of its content (the image). That's exactly what's happening. The item takes the natural size of the image.
Add this to your code:
flex-basis: 0
OR, better yet, this:
flex: 1
which is short for:
flex: 1 1 0
which is short for:
flex-grow: 1
flex-shrink: 1
flex-basis: 0
From the spec:
7.2. Components of
Flexibility
Authors are encouraged to control flexibility using the flex shorthand
rather than with its longhand properties directly, as the shorthand
correctly resets any unspecified components to accommodate common
uses.
For an explanation of the difference between flex-basis: auto and flex-basis: 0, see this post:
Make flex-grow expand items based on their original size
#main {
height: 100px;
border: 1px solid #c3c3c3;
display: flex;
}
/* adjustment here */
#main div:nth-of-type(1) {
flex: 1;
}
#main div:nth-of-type(2) {
flex-grow: 3;
}
#main img {
width: 100%;
height: auto;
}
<div id="main">
<div style="background-color:coral;"><img src="http://www.der-eyecatcher.de/wp-content/uploads/2016/02/Lampe-silber-Schirm_1.jpg"></div>
<div style="background-color:lightblue;">Description</div>
</div>
<hr>flex-grow without Image
<hr>
<div id="main">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;">Description</div>
</div>
If I set up a nested flexbox container like so:
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2"></div>
</div>
</div>
</div>
...and then set the width of grow2 such that it is wider than container1 then grow2 overflows container1.
I believe this should not happen since flex elements are supposed to shrink when they are larger than the flex container.
If I set the flex-basis of grow2 then this works as expected.
Please see the following example for a demo:
https://jsfiddle.net/chris00/ot1gjjtk/20/
Please use Chrome or Firefox for this
Furthermore, I read that the flexbox spec says that width and flex-basis should have the same effect (when using horizontal layouts) which they clearly don't.
Now I could just use flex-basis instead of width, but... Edge does the same thing for both flex-basis and width, and it does it in the "wrong" way. IE11 does it wrong also (although that appears to have multiple flexbox bugs).
Please check out the demo with Edge.
So how is this supposed to work?
Are there bugs in all browsers?
Is flex-basis actually supposed to be different from width (in simple horizontal layouts)?
Or is Edge correct and both width and flex-basis are supposed to overflow the parent container?
Finally, is there a workaround that can fix the overflow for Edge (and even IE11)?
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
The Problem
As far as the spec is concerned, this isn't an issue pertaining to flex-basis, width, flex-grow or flex. It's something entirely different.
4.5. Implied Minimum Size of Flex
Items
To provide a more reasonable default minimum size for flex items, this
specification introduces a new auto value as the initial value of
the min-width and min-height properties defined in CSS 2.1.
In other words, a flex item, by default, cannot be smaller than the length of its content (essentially, the longest word or fixed-size element).
The item cannot stay within its container (or even render a scroll bar or ellipsis), because its content is not permitted to overflow. The content simply expands the item. This behavior applies to fixed-sizing, as well (such as the flex-basis: 400px in your code).
Again, the initial settings are:
min-width: auto, in row-direction
min-height: auto, in column-direction
For a more complete explanation see this post:
Why doesn't flex item shrink past content size?
Solution for Chrome, Safari, Firefox and Edge
The standard solution to this problem is simple: override the default.
In your code, add min-width: 0 to .grow1.
That solves the problem in Chrome, Safari, FF and Edge.
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
min-width: 0; /* NEW */
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
revised fiddle 1
Solution for IE11
In IE11, contrary to spec guidance, the flex min-width / min-height default values are already 0, yet the flex item still breaks out.
The defaults are 0 because when the flexbox spec was first released, the min-* properties did not deviate from the CSS 2.1 initial values, which are 0.
Later, after browsers had completed their implementations, the flex min-* values were updated to auto. Chrome, Safari, FF and Edge made the update. IE11 did not.
The reason the flex items break out in IE11 relates to another issue: the browser wants an explicit width on the container
In your code, add flex-basis: 100% to .grow1.
More details here:
Why IE11 doesn't wrap the text in flexbox?
flexbox flex-basis: 0px in Chrome
.container1 {
margin-top: 10px;
display: flex;
width: 200px;
height: 50px;
background-color: red;
}
.grow1 {
flex-grow: 1;
height: 40px;
background-color: green;
flex-basis: 100%; /* NEW */
}
.container2 {
display: flex;
height: 30px;
background-color: yellow;
}
.grow2a {
flex-grow: 1;
flex-basis: 400px;
height: 20px;
background-color: turquoise;
}
.grow2b {
flex-grow: 1;
width: 400px;
height: 20px;
background-color: turquoise;
}
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2a">Working (flex-basis)</div>
</div>
</div>
</div>
<div class="container1">
<div class="grow1">
<div class="container2">
<div class="grow2b">Not working (width)</div>
</div>
</div>
</div>
revised fiddle 2 (IE11)
More Browser Discrepancies
Evidence appears to exist (in this question and other examples I've seen) that Webkit-based browsers are no longer honoring the auto default defined in the spec.
Moreover, the adherence to the auto standard may vary based on which property is used for sizing: flex-basis vs. width / height
As discussed in the following post, these properties should render the same way.
What are the differences between flex-basis and width?
I am trying to stretch the size of an iframe to fill the remaining space within my web app. I know the maximum space is being allocated for the div (by adding a border), but the iframe height itself is not expanding to fill the entire vertical height.
The problem is the row content iframe is not filling the entire vertical space, even though the flexbox is allocating that space appropriately.
Any ideas?
.box {
display: flex;
flex-flow: column;
height: 100vh;
}
.box .row.header {
flex: 0 1 auto;
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
.row.content iframe {
width: 100%;
border: 0;
}
<div class="box">
<div class="row header">
<h1>Event Details</h1>
<div id="container">
<h5>Test</h5>
</div>
<div data-role="navbar">
<ul>
<li>Players
</li>
<li>Games
</li>
<li>Chat
</li>
</ul>
</div>
</div>
<div class="row content">
<iframe src="players.html"></iframe>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
Here are two things to consider:
When you create a flex container only the child elements become flex items. Any descendants beyond the children are not flex items and flex properties don't apply to them.
Your iframe is not a flex item because it is a child of div class="row content" which is a flex item, but not a flex container. Therefore, no flex properties apply and there is no reason for the iframe to stretch.
To apply flex properties to the children of flex items, you need to make the flex item also a flex container. Try this:
.box .row.content {
flex: 1 1 auto;
display: flex; /* new */
}
With the adjustment above the iframe's parent becomes a (nested) flex container, the iframe becomes a flex item, and default flex settings (including align-items: stretch) go into effect. The iframe should now occupy the full height of the container.
You can fix it with just flexbox, Make sure the container (wrapper) of the iframe has a height set or its parent has, this can be a in pixels percent or VH. and flex-direction:column. The iframe itself needs a flex:1 1 auto; nothing else is needed so no height or width set on it.
Internet explorer can have some problem with the width of the iframe. But it should work vertically. For IE11 make sure you set a min-height:0 on the wrapper.
body{
padding:1em;
display:flex;
flex-direction:column;
align-items:center;
justify-content: center;
height:100vh;
}
.wrap {
display: flex;
flex-direction: column;
width: 80vw;
height: 80vh;
border: 2px solid blue;
min-height: 0;
}
.frame {
flex: 1 1 auto;
border: 0;
}
Simplified jsfidle demo
Complex jsfidle demo