What would be the best analogy for fr(fraction) unit in a flexbox layout? I was thinking of flex: 1 but not sure if it is the best match in terms of its growing/shrinking behavior.
What I'm trying to do is to make a fallback for grid layout so that it works in IE11. I have a grid statement grid-template-columns: 11.25rem 1fr; that I can't make work in IE (even with Auto-prefixer that adds -ms-grid-columns columns still stack on top of each other).
So I was thinking to maybe just implement it in flexbox for IE using something like this:
.container {
max-width: 46rem;
.parent {
display: flex;
& :first-child {
inline-size: 11.25rem;
}
& :last-child {
flex: 1;
}
}
}
Turned out flex: 1 works for my needs.
It's a shorthand for flex: 1 1 0px; so
flex-grow: 1 lets it grow when there is extra space.
flex-shrink: 1 lets it shrink when there is not enough space.
flex-basis: 0px allows it to have width defined by its content with respect to its container's width.
Related
I have been unable to determine why flexbox is not working in IE 11.
For testing, I sourced a very simple flexbox layout from CodePen and have pasted the information below.
Chrome works as intended; IE11 fails.
Image of layout-success running on Chrome:
Image of layout-failure on IE11
body {
background: #333;
font-family: helvetica;
font-weight: bold;
font-size: 1.7rem;
}
ul {
list-style: none;
}
li {
background: hotpink;
height: 200px;
text-align: center;
border: 2px solid seashell;
color: seashell;
margin: 10px;
flex: auto;
min-width: 120px;
max-width: 180px;
}
.flex {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
<ul class="flex">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
http://codepen.io/hankthewhale/pen/IdKkB?editors=110
IE has a problem parsing the flex property.
Here are a few workarounds that have worked for me:
Use the long-hand properties instead of the shorthand.
Instead of something like this: flex: 0 0 35%.
Try this:
flex-grow: 0
flex-shrink: 0
flex-basis: 35%
Make sure flex-shrink is enabled.
So instead of this: flex: 0 0 35%
Try this: flex: 0 1 35%
(In other cases flex-shrink needs to be disabled: Flex item overlaps another item in IE11)
Careful with percentage and unitless values with flex-basis
This may depend on your version of IE11. Behavior appears to vary.
Try these variations:
flex: 1 1 0
flex: 1 1 0px
flex: 1 1 0%
Beware! Certain css minifiers will replace 0px with 0, which can be a really annoying thing to debug (however, they won't change 0% for some reason).
More details here:
Image behavior within flexbox (rows embedded in columns)
Why does shorthand flex property behave differently than long hand properties in IE?
Instead of flex: 1 use flex: auto (or add in flex-basis: auto)
If you're using flex: 1 in flex-direction: row (such as on larger screens), and you switch to flex-direction: column in a media query (let's say for mobile devices), you may find that your flex items collapse.
In your media query, add flex-basis: auto. This will override the flex-basis value in the flex: 1 rule (which is usually 0, 0px or 0%, depending on the browser).
Using flex: auto should also work, which is short for:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
Use old-fashion width / height properties instead of flex.
Use block layout instead of flex layout.
You don't need to completely abandon flex layout. But for a particular container you may be able to get the job done with display: block instead of display: flex; flex-direction: column.
For example, in needing to use the padding trick to responsively embed a video in a flex item, the obstacle I faced was that some browsers don't work well with percentage padding (or margin) in a flex container.
To make it work I switched the display value on the flex item from this:
/* a flex item, also a nested flex container */
#footer-container > article {
display: flex;
flex-direction: column;
}
to this:
#footer-container > article {
display: block;
}
For me, using
flex: 1 1 auto;
instead of
flex: 1;
solved the flex issue on IE 11.
Just use flex:1 0 auto;. It will work.
As in #Michael_B answer, limit the growth with Flexbox flex property: flex: 0 1 (1/n - b) taken in % value, where n is the number of flex items in a row and b is the gap that you want to see between flex items in IE.
On the flex items along with flex property above use the max-width property with percentage value of 1/n - b.
In your case the generalized CSS for the flex item would be:
li {
// ... the remaining code from your snippet
// Calculate the following manually and insert or use CSS preprocessor that does math for you.
// See the formula explanation above.
max-width: (your flex container max-width / 2) * 100% - b;
flex: 0 1 (your flex container max-width / 2) * 100% - b;
}
In actual case with 5 items / row there will be (1/5) * 100% - 1% = 19% => max-width: 19% and flex: 0 1 19%;.
Play with b parameter to make flex items short enough to allow flex: wrap; work.
In my case, the CSS minifier rejects the px unit of the last argument in -ms-flex shorthand rule, I tried using % unit and it works fine.
In mdn
flex:1
means the same as
flex-grow:1.
However, in fact it has different show in browser.
You can try it in this jsFiddle by changing the comment in css.
When I use flex: 1 the element who's classname is test-container will be height:100% but it won't happen when you use flex-grow: 1.
I don't understand why. Looking for some help. Thanks very much.
.flex-1 {
display: flex;
flex-direction: column;
height: 500px;
background: red;
}
.child-1 {
height: 50px;
background: blue;
}
.child-2 {
flex-grow: 1;
/* flex:1; */
background: green;
}
.test-container {
display: flex;
flex-direction: row;
background: white;
height: 100%;
}
<div class="flex-1">
<div class="child-1"></div>
<div class="child-2">
<div class="test-container"></div>
</div>
</div>
flex
The flex property is a shorthand for setting:
flex-grow
flex-shrink
flex-basis
The flex: 1 rule is supposed to compute to this:
flex-grow: 1
flex-shrink: 1
flex-basis: 0
These values are defined in the spec. See section 7.1.1. Basic Values of flex
I say "supposed to compute" because, in IE11 and possibly other browsers, a unit of measure, such as px or %, is appended to the 0 value in flex-basis. This can make a difference (example).
flex-grow
The flex-grow property (which distributes free space in the container among flex items), when declared by itself, leaves flex-shrink and flex-basis at their initial values.
So when you set flex-grow: 1, the browser renders this:
flex-grow: 1 (overrides the default value, which is 0)
flex-shrink: 1 (this is the default value)
flex-basis: auto (this is the default value)
The difference between flex: 1 and flex-grow: 1
Ultimately, the difference between flex: 1 and flex-grow: 1 is that the former sets flex-basis: 0, and the latter keeps the default flex-basis: auto.
For a complete explanation of the difference between flex-basis: 0 and flex-basis: auto see this post:
Make flex-grow expand items based on their original size
Your code example
The reason you're seeing a difference in your code is that flex-basis controls height in a column-direction container.
In Chrome, with flex-basis: auto, the height of the element is 450px (500px parent - 50px header). In other words, flex-grow is free to distribute the free space.
With flex-basis: 0, the height of the element is 0, and flex-grow has no free space to distribute.
The height: 100% on the child of the flex item is simply ignored because it isn't being applied properly, as explained in these posts:
Working with the CSS height property and percentage values
Chrome / Safari not filling 100% height of flex parent
In reading the posts above you'll also understand why your code renders differently in Firefox, Safari, Edge and IE.
l get the reason why that happen. In fact
flex:1 === flex-grow:1;flex-shrink:1;flex-basis:0%
the key is the flex-basis:0%. If you use flex-grow:1,the flex-basis will be auto. In this sutation, you can't let the height:100% work .
However I don't sure when the
flex:1 === flex-grow:1;flex-shrink:1;flex-basis:0%
will happen. In the doc
flex:1 !== flex-grow:1;flex-shrink:1;flex-basis:0%
I have been unable to determine why flexbox is not working in IE 11.
For testing, I sourced a very simple flexbox layout from CodePen and have pasted the information below.
Chrome works as intended; IE11 fails.
Image of layout-success running on Chrome:
Image of layout-failure on IE11
body {
background: #333;
font-family: helvetica;
font-weight: bold;
font-size: 1.7rem;
}
ul {
list-style: none;
}
li {
background: hotpink;
height: 200px;
text-align: center;
border: 2px solid seashell;
color: seashell;
margin: 10px;
flex: auto;
min-width: 120px;
max-width: 180px;
}
.flex {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
<ul class="flex">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
http://codepen.io/hankthewhale/pen/IdKkB?editors=110
IE has a problem parsing the flex property.
Here are a few workarounds that have worked for me:
Use the long-hand properties instead of the shorthand.
Instead of something like this: flex: 0 0 35%.
Try this:
flex-grow: 0
flex-shrink: 0
flex-basis: 35%
Make sure flex-shrink is enabled.
So instead of this: flex: 0 0 35%
Try this: flex: 0 1 35%
(In other cases flex-shrink needs to be disabled: Flex item overlaps another item in IE11)
Careful with percentage and unitless values with flex-basis
This may depend on your version of IE11. Behavior appears to vary.
Try these variations:
flex: 1 1 0
flex: 1 1 0px
flex: 1 1 0%
Beware! Certain css minifiers will replace 0px with 0, which can be a really annoying thing to debug (however, they won't change 0% for some reason).
More details here:
Image behavior within flexbox (rows embedded in columns)
Why does shorthand flex property behave differently than long hand properties in IE?
Instead of flex: 1 use flex: auto (or add in flex-basis: auto)
If you're using flex: 1 in flex-direction: row (such as on larger screens), and you switch to flex-direction: column in a media query (let's say for mobile devices), you may find that your flex items collapse.
In your media query, add flex-basis: auto. This will override the flex-basis value in the flex: 1 rule (which is usually 0, 0px or 0%, depending on the browser).
Using flex: auto should also work, which is short for:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
Use old-fashion width / height properties instead of flex.
Use block layout instead of flex layout.
You don't need to completely abandon flex layout. But for a particular container you may be able to get the job done with display: block instead of display: flex; flex-direction: column.
For example, in needing to use the padding trick to responsively embed a video in a flex item, the obstacle I faced was that some browsers don't work well with percentage padding (or margin) in a flex container.
To make it work I switched the display value on the flex item from this:
/* a flex item, also a nested flex container */
#footer-container > article {
display: flex;
flex-direction: column;
}
to this:
#footer-container > article {
display: block;
}
For me, using
flex: 1 1 auto;
instead of
flex: 1;
solved the flex issue on IE 11.
Just use flex:1 0 auto;. It will work.
As in #Michael_B answer, limit the growth with Flexbox flex property: flex: 0 1 (1/n - b) taken in % value, where n is the number of flex items in a row and b is the gap that you want to see between flex items in IE.
On the flex items along with flex property above use the max-width property with percentage value of 1/n - b.
In your case the generalized CSS for the flex item would be:
li {
// ... the remaining code from your snippet
// Calculate the following manually and insert or use CSS preprocessor that does math for you.
// See the formula explanation above.
max-width: (your flex container max-width / 2) * 100% - b;
flex: 0 1 (your flex container max-width / 2) * 100% - b;
}
In actual case with 5 items / row there will be (1/5) * 100% - 1% = 19% => max-width: 19% and flex: 0 1 19%;.
Play with b parameter to make flex items short enough to allow flex: wrap; work.
In my case, the CSS minifier rejects the px unit of the last argument in -ms-flex shorthand rule, I tried using % unit and it works fine.
I have been unable to determine why flexbox is not working in IE 11.
For testing, I sourced a very simple flexbox layout from CodePen and have pasted the information below.
Chrome works as intended; IE11 fails.
Image of layout-success running on Chrome:
Image of layout-failure on IE11
body {
background: #333;
font-family: helvetica;
font-weight: bold;
font-size: 1.7rem;
}
ul {
list-style: none;
}
li {
background: hotpink;
height: 200px;
text-align: center;
border: 2px solid seashell;
color: seashell;
margin: 10px;
flex: auto;
min-width: 120px;
max-width: 180px;
}
.flex {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
<ul class="flex">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
http://codepen.io/hankthewhale/pen/IdKkB?editors=110
IE has a problem parsing the flex property.
Here are a few workarounds that have worked for me:
Use the long-hand properties instead of the shorthand.
Instead of something like this: flex: 0 0 35%.
Try this:
flex-grow: 0
flex-shrink: 0
flex-basis: 35%
Make sure flex-shrink is enabled.
So instead of this: flex: 0 0 35%
Try this: flex: 0 1 35%
(In other cases flex-shrink needs to be disabled: Flex item overlaps another item in IE11)
Careful with percentage and unitless values with flex-basis
This may depend on your version of IE11. Behavior appears to vary.
Try these variations:
flex: 1 1 0
flex: 1 1 0px
flex: 1 1 0%
Beware! Certain css minifiers will replace 0px with 0, which can be a really annoying thing to debug (however, they won't change 0% for some reason).
More details here:
Image behavior within flexbox (rows embedded in columns)
Why does shorthand flex property behave differently than long hand properties in IE?
Instead of flex: 1 use flex: auto (or add in flex-basis: auto)
If you're using flex: 1 in flex-direction: row (such as on larger screens), and you switch to flex-direction: column in a media query (let's say for mobile devices), you may find that your flex items collapse.
In your media query, add flex-basis: auto. This will override the flex-basis value in the flex: 1 rule (which is usually 0, 0px or 0%, depending on the browser).
Using flex: auto should also work, which is short for:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
Use old-fashion width / height properties instead of flex.
Use block layout instead of flex layout.
You don't need to completely abandon flex layout. But for a particular container you may be able to get the job done with display: block instead of display: flex; flex-direction: column.
For example, in needing to use the padding trick to responsively embed a video in a flex item, the obstacle I faced was that some browsers don't work well with percentage padding (or margin) in a flex container.
To make it work I switched the display value on the flex item from this:
/* a flex item, also a nested flex container */
#footer-container > article {
display: flex;
flex-direction: column;
}
to this:
#footer-container > article {
display: block;
}
For me, using
flex: 1 1 auto;
instead of
flex: 1;
solved the flex issue on IE 11.
Just use flex:1 0 auto;. It will work.
As in #Michael_B answer, limit the growth with Flexbox flex property: flex: 0 1 (1/n - b) taken in % value, where n is the number of flex items in a row and b is the gap that you want to see between flex items in IE.
On the flex items along with flex property above use the max-width property with percentage value of 1/n - b.
In your case the generalized CSS for the flex item would be:
li {
// ... the remaining code from your snippet
// Calculate the following manually and insert or use CSS preprocessor that does math for you.
// See the formula explanation above.
max-width: (your flex container max-width / 2) * 100% - b;
flex: 0 1 (your flex container max-width / 2) * 100% - b;
}
In actual case with 5 items / row there will be (1/5) * 100% - 1% = 19% => max-width: 19% and flex: 0 1 19%;.
Play with b parameter to make flex items short enough to allow flex: wrap; work.
In my case, the CSS minifier rejects the px unit of the last argument in -ms-flex shorthand rule, I tried using % unit and it works fine.
I wanted to use flex box property to my layout where we create boxes dynamically.
So I want to adjust themselves(box) as per the count. Like if only 1 box is there, it should take complete 100% space and max 3 boxes will come in one row.
If 4th box comes in the screen then go to the next row automatically.
I have searched a lot about flex-flow but did not get the right solution.
Please help.
Regards
Using new syntax, Chrome (requires prefix) and Opera only at present:
#container {
display: flex;
flex-flow: row wrap;
}
#container > * {
flex: 1 1 33%;
}
Here is a demo: http://jsfiddle.net/lpd_/qwwT8/. If you don't want items on subsequent rows to stretch once the first row is filled, you can add:
#container > *:nth-child(n+4) {
max-width: 33.33%;
max-width: calc(100% / 3); /* To override and be more precise, if you wish */
}