Consider flex-direction
The first thing that comes to mind when reading your question is that flex-basis
doesn't always apply to width
.
When flex-direction
is row
, flex-basis
controls width.
But when flex-direction
is column
, flex-basis
controls height.
Key Differences
Here are some important differences between flex-basis
and width
/ height
:
flex-basis
applies only to flex items. Flex containers (that aren't also flex items) will ignore flex-basis
but can use width
and height
.
flex-basis
works only on the main axis. For example, if you're in flex-direction: column
, the width
property would be needed for sizing flex items horizontally.
flex-basis
has no effect on absolutely-positioned flex items. width
and height
properties would be necessary. Absolutely-positioned flex items do not participate in flex layout.
By using the flex
property, three properties – flex-grow
, flex-shrink
and flex-basis
– can be neatly combined into one declaration. Using width
, the same rule would require multiple lines of code.
Browser Behavior
In terms of how they are rendered, there should be no difference between flex-basis
and width
, unless flex-basis
is auto
or content
.
From the spec:
7.2.3. The flex-basis
property
For all values other than auto
and content
, flex-basis
is resolved the same way as width
in horizontal writing modes.
But the impact of auto
or content
may be minimal or nothing at all. More from the spec:
auto
When specified on a flex item, the auto
keyword retrieves the value
of the main size property as the used flex-basis
. If that value is
itself auto
, then the used value is content
.
content
Indicates automatic sizing, based on the flex item’s content.
Note: This value was not present in the initial release of Flexible
Box Layout, and thus some older implementations will not support it.
The equivalent effect can be achieved by using auto
together with a
main size (width
or height
) of auto
.
So, according to the spec, flex-basis
and width
resolve identically, unless flex-basis
is auto
or content
. In such cases, flex-basis
may use content width (which, presumably, the width
property would use, as well).
The flex-shrink
factor
It's important to remember the initial settings of a flex container. Some of these settings include:
flex-direction: row
- flex items will align horizontally
justify-content: flex-start
- flex items will stack at the start of the line on the main axis
align-items: stretch
- flex items will expand to cover the cross-size of the container
flex-wrap: nowrap
- flex items are forced to stay in a single line
flex-shrink: 1
- a flex item is allowed to shrink
Note the last setting.
Because flex items are allowed to shrink by default (which prevents them from overflowing the container), the specified flex-basis
/ width
/ height
may be overridden.
For example, flex-basis: 100px
or width: 100px
, coupled with flex-shrink: 1
, will not necessarily be 100px.
To render the specified width – and keep it fixed – you will need to disable shrinking:
div {
width: 100px;
flex-shrink: 0;
}
OR
div {
flex-basis: 100px;
flex-shrink: 0;
}
OR, as recommended by the spec:
flex: 0 0 100px; /* don't grow, don't shrink, stay fixed at 100px */
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.
Browser Bugs
Some browsers have trouble sizing flex items in nested flex containers.
flex-basis
ignored in a nested flex container. width
works.
When using flex-basis
, the container ignores the sizing of its children, and the children overflow the container. But with the width
property, the container respects the sizing of its children and expands accordingly.
References:
Examples:
flex items using flex-basis
and white-space: nowrap
overflow inline-flex
container. width
works.
It seems that a flex container set to inline-flex
doesn't recognize flex-basis
on a child when rendering a sibling with white-space: nowrap
(although it could just be an item with undefined width). The container doesn't expand to accommodate the items.
But when the width
property is used instead of flex-basis
, the container respects the sizing of its children and expands accordingly. This is not a problem in IE11 and Edge.
References:
Example:
flex-basis
(and flex-grow
) not working on table element
References:
flex-basis
fails in Chrome and Firefox when the grandparent container is a shrink-to-fit element. The set-up works fine in Edge.
Like in the example presented in the link above, involving position: absolute
, the use of float
and inline-block
, will also render the same flawed output (jsfiddle demo).
Bugs affecting IE 10 and 11: