The difference between flex:1 and flex-grow:1 - css

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%

Related

Flex column collapsing with textarea [duplicate]

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.

How does the flex shorthand handle a single value that is represented as a percentage?

The Mozilla Developer Network flex article says of its syntax:
One-value syntax: the value must be one of:
a unitless <number>: then it is interpreted as <flex-grow>.
a valid value for width: then it is interpreted as <flex-basis>.
one of the keyword values none, auto, or initial.
The second bullet implies that flex: 20%; is equivalent to flex-basis: 20%;, as 20% is a valid value for width.
However, that is not the case in practice:
flex shorthand
.container {
display: flex;
}
.container>div {
padding: 6px;
}
.one {
background: #fcc9e5;
flex: 20%;
}
.two {
background: #ecaef9;
flex: 1;
}
<div class="container">
<div class="one">one</div>
<div class="two">two</div>
</div>
flex-basis
.container {
display: flex;
}
.container>div {
padding: 6px;
}
.one {
background: #fcc9e5;
flex-basis: 20%;
}
.two {
background: #ecaef9;
flex: 1;
}
<div class="container">
<div class="one">one</div>
<div class="two">two</div>
</div>
So, what is happening here?
The spec says that, in a flex shorthand declaration, when <flex-grow> and <flex-shrink> are omitted, they both default to 1. (MDN incorrectly states that <flex-grow> defaults to 0.)
This means that the shorthand declaration flex: 20% is equivalent to flex: 1 1 20%.
Specifying only flex-basis: 20% leaves flex-grow and flex-shrink at their initial values of 0 and 1 respectively, making that longhand declaration by itself equivalent to the shorthand flex: 0 1 20%.
How does the flex shorthand handle a single value that is represented as a percentage?
Very simple. Like this:
flex: 20%
Is equivalent to:
flex-grow: 1
flex-shrink: 1
flex-basis: 20%
The people at MDN have apparently misinterpreted the flex definition in the spec, which is actually a bit confusing.
On the one hand, the spec says the Initial Value for flex is flex: 0 1 auto.
But if you read the text right below, it says (as pointed out by #BoltClock in his answer), that the value for flex-grow is 1 when omitted.
So, bottom line, in your first example, flex: 20% is equivalent to:
flex-grow: 1
flex-shrink: 1
flex-basis: 20%
While in your second example, flex-basis: 20% is equivalent to:
flex-grow: 0 (the initial value)
flex-shrink: 1 (the initial value)
flex-basis: 20%
By the way, this is exactly why the flexbox specification makes this recommendation:
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.
https://drafts.csswg.org/css-flexbox-1/#flex-components

Flex-box alignment not working in IE [duplicate]

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.

Flex layout broken in IE11 [duplicate]

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.

Flexible box layout model: How should auto margins in the cross-axis direction behave?

Please help me to understand one issue with the flexible box layout model for which I get different results in Firefox and Chrome.
Consider the following HTML fragment:
<body>
<header>Header</header>
<footer>Footer</footer>
</body>
styled via
body {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
header {
max-width: 400px;
height: 20px;
background-color: yellow;
margin: 0 auto;
}
footer {
width: 400px;
height: 20px;
background-color: green;
margin: 0 auto;
}
The header box has a maximum width constraint of 400px while the footer has a fixed width of 400px. When I try this code in Gecko-based browsers (Firefox 21 and 24 in my case) both header and footer are horizontally centered (as I hoped for by giving them left and right auto margins) but only the footer has a width of 400px while the header's width is just the width of the content even if enough horizontal space was available.
In WebKit/Blink-based browsers (Chrome 25 and 28 in my case) the header and footers are both centered and are both 400px wide (in case there is enough horizontal space), and this is exactly what I want to achieve.
Obviously, either Firefox or Chrome must be wrong. How do you understand the spec: http://www.w3.org/TR/css3-flexbox/? What is the desired behaviour?
If you want to play around, here is a JSFiddle: http://jsfiddle.net/4Rv7K/.
Note that one has to enable the flexible box layout model in the release version of Firefox. It is the setting layout.css.flexbox.enabled. (Without it, one is actually not testing anything about flexboxes.)
P.S.: The bug was in Chromium's engine and has apparently been fixed by now: https://code.google.com/p/chromium/issues/detail?id=242654
The Firefox/Gecko behavior is correct.
WebKit is stretching up to 400px (the max-width) due to the header element's default "align-self: stretch" value. However, the spec is clear that "align-self: stretch" is only supposed to stretch if you have no auto margins in the cross axis. Quoting the spec:
If a flex item has ‘align-self: stretch’, [...] and neither of its
cross-axis margins are ‘auto’, the used outer cross size is the used
cross size of its flex line, clamped according to the item's min and
max cross size properties
http://www.w3.org/TR/css3-flexbox/#cross-sizing
The exception for "neither of its cross-axis margins are auto" is what Firefox is honoring here and WebKit/Blink appear to be ignoring.
Now, to achieve your desired layout: It looks like you want both stretchiness and centering, and I don't think you can get both of those things simultaneously in the cross axis.
You can get them simultaneously in the main axis of a flex container, though -- so you can fix this by adding a horizontal flex container around the header and the footer.
I've done that here:
http://jsfiddle.net/4Rv7K/16/
The relevant code (just with the 'header' for simplicity):
body {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
horizFlex {
display: -webkit-flex;
display: flex;
}
header {
-webkit-flex: 1 0 auto;
flex: 1 0 auto;
max-width: 400px;
height: 20px;
background-color: yellow;
margin: 0 auto;
}
[...]
<body><horizFlex><header>Header</header></horizFlex></body>
I think this achieves the layout you're looking for by wrapping the header and footer each in a horizontal flex container. The flex container stretches to the width of its parent (the body), and inside of it we have a single flex item (e.g. the ), which is flexible up to its max-width, and which we center (with auto margins) once it has reached its max-width.
For an element that lacks a definite size with auto margins, it looks like the element's fit-content width is supposed to be used as the element's actual width while the remaining space is counted as margin. For Chrome, it appears to be behaving inappropriately only when using flex-direction: column.
http://codepen.io/cimmanon/pen/fuhyF
ul {
display: -webkit-flex;
display: flex;
height: 5em;
background: yellow;
}
li {
margin: auto;
border: 1px solid;
}
ul.column {
-webkit-flex-direction: column;
-flex-direction: column;
}
If you look at a list with the above styles, Opera, Firefox, and Chrome agree that the li elements are shrink wrapped when the direction is row. Under the column direction, only Firefox and Opera shrink wrap the li, while Chrome has the li take the full width of the flex container.

Resources