An exploration into the initial/default values of flexbox and their effects.
What is display: flex
?
.container {
display: flex;
}
display: flex
is a CSS display declaration, which enables flexbox (the Flexible Box Layout Module).
With flexbox enabled:
- The selected element becomes a flex container
- Its child contents become flex items
- It will algorithmically layout its contents
To the uninitiated, this can be a little surprising and confusing at first. So let's get a better understanding of flexbox and its default settings.
Flexbox overview
Flexbox is a layout system, which assumes the responsibility of arranging, aligning and flexibly sizing flex items within its flex containers.
It's a line-based system, meaning it will arrange and align its contents along a single-line, which can be wrapped.
This single breakable line can appear horizontally like in rows, or vertically like in columns, but it cannot be both at the same time.
Flexbox is a one dimensional layout system
Flexbox is also writing mode aware.
This means it will automatically arrange its flex items in the same orientations and directions as text flows in the document.
Writing mode
The writing mode details how text/content flows within its documents or components. Its purpose, is to internationalize writing on the web.
It determines:
inline direction:
The direction a line of text flows inblock flow direction:
The direction new lines of text are addedinline base direction:
The primary direction content (text and other elements) flows within the line
Browser default writing mode - horizontal-tb
By default, the browser will arrange lines of text in horizontal
rows.
New lines of text are added vertically, in a top-to-bottom direction (tb
) .
Within each line, text flows from left-to-right (ltr
)
Layout axes and default directions
Layout in flexbox consists of two axes, which determine how content is arranged and aligned.
By default, the document's writing mode will determine how these axes are organised:
Main axis
- The main axis is the primary axis of flexbox
- Flex items are arranged in a single direction along this axis
- Its default orientation will follow the inline direction of the document's writing‑mode (
horizontal
)
Cross axis
- The cross axis runs perpendicular (or 90 degrees) to the main axis (it "crosses" the main axis)
- This axis is used to align content in relation to the main axis
- Its default orientation and direction will follow the block flow direction of the document's writing‑mode (
tb
)
Flex items will flow in the same directions as the document's flow of text (left-to-right, top-to-bottom).
Default axes and writing mode
Note:
The orientation and direction of flexbox axes can be overridden. The main axis can appear horizontal or vertical, regardless of the inline axis direction.
A deep dive into display: flex
When we create a flex container, we set two display types or contexts:
an Outer display type
for the flex containeran Inner display type
for its flex-items
Outer display type
When declaring flex
, the outer display type of the flex container is set to block
.
For layout, this means:
- the selected element's width expands to fit its parent container or to its own set width
- its vertical height is equal to that of its contents
-
overflow
applies to the container
Note:
Setting display: inline-flex
will create a flex container, which acts like an inline-element in normal document flow
e.g. a flex container inline with text
Inner display type
Within the flex container, its child contents become 'flex items'.
Child contents such as:
- HTML elements
- e.g.
div
,li
,img
,span
,input
,table
etc
- e.g.
- Pseudo elements
- i.e.
::before
,::after
- i.e.
-
Non-empty text nodes
- i.e. a continuous string of text, other than whitespace, without a containing element, such as
"lorem ipsum"
- String content will be wrapped in an anonymous flex-item wrapper and ⚠ cannot be directly styled with CSS due to being anonymous.
- i.e. a continuous string of text, other than whitespace, without a containing element, such as
However, not all child items become flex-items:-
Absolutely-positioned child elements
- Elements that are absolutely positioned with CSS (e.g.
position: absolute
) are not flex items, as they are taken out of document flow
Note:
Flex items can also be set as flex containers.
The item will act as both:
- a flex item to its parent container
- a flex container to its contents
Flex formatting context
Flex items participate in a flex formatting context.
This participation is regardless of the flex item's initial display type. The flex items will instead act "like blocks".
However, there are differences in block and flex formatting contexts.
Within a flex container:
- float and clear do not apply to flex items
- vertical-align has no effect on flex items
margin collapsing is not a feature of flex formatting contexts
first formatting pseudo elements do not apply
(::first-line
,::first-letter
)
Default flexbox layout
Declaring flex
on a parent element, will typically result in one of the following layouts:
content in a row with free space
content in a row with no free space
content in a row overflowing its container
In all scenarios, we see:
- a single row of flex items
- equal height flex items within this row
This is because flexbox was optimized for user interfaces and common interface designs call for a row of equal height elements/columns.
In the past, this default layout was difficult to produce and developers often resorted to workarounds and hacks, such as:
- Floated faux columns
- CSS table styling
- Set column heights
Thankfully, we can now achieve this with a single style declaration:
display: flex
Default flexbox properties and values
When a flex container is created with display: flex;
the following initial browser styles will take effect:
For the flex container:
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: stretch;
For its flex items:
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
order: 0;
Flexbox terminology
To help describe the behaviour of flexbox, let's take a detour and introduce some more terminology:
Main-size - The size of the flex item/container along the main axis/dimension.
Cross-size - The size of the flex item/container along the cross axis/dimension.
Flex base size (or base size) - The content box size of the flex item, before it resizes (grows or shrinks).
Hypothetical main size - The flex base size clamped by min/max values (such as min-width
,max-width
).
Inner size - The content box size of an element.
Outer size - The margin box size of an element.
The margin box includes the content, padding, borders and margins of an element.
Flex container - default arrangement
What properties and values define how flex items are arranged in the container.
Main axis orientation
flex-direction: row;
The flex-direction property sets the orientation of the main-axis.
In default layout, the main-axis will match the orientation of the writing mode's inline axis, which is horizontal.
Flex items are arranged horizontally in a row
If the writing mode was vertical (such as in Chinese or Japanese)
the flex-direction: row
would run vertically, following the inline axis.
Cross axis orientation
The cross-axis runs perpendicular to the main axis.
In default layout, the cross axis runs vertically from top to bottom in the block flow direction.
Main axis direction
By default, the main axis direction matches the inline base direction of the document.
The main-start and main-end directions are equivalent to the inline-start and inline-end of the inline axis.
Flex items are arranged from left-to-right (ltr
).
Single flex line
Initially flex items are laid out in a single line along the main axis of the flex container.
This line of flexbox content is called a flex line.
Flex items do not automatically wrap onto new flex lines.
This is due to the default setting:
flex-wrap: nowrap;
If there is not enough space within the flex container, the contents will overflow.
Flex container - default alignment
What properties and values define how flex items are aligned in the container.
Main axis alignment
justify-content: flex-start;
Initially, flex items will align to the main-start of the main axis.
In default layout, the main-start is equivalent to the inline-start of the inline axis.
Flex items are aligned as a group to the left side of the container.
Cross axis alignment
align-items: stretch;
By default, flex items will "stretch" to fill the flex container's cross size, aligning to its cross-start and its cross-end.
The flex items will stretch vertically from top-to-bottom, following the block flow direction of the writing mode.
Flex items with the same cross size will appear equal height.
The cross size of a flex container is determined by either of the following:
- The flex-item with the largest cross size
- The set cross size of the flex container
Cross size determined by flex item
By default, the flex container will expand to fit its largest flex item. If the flex container contains other flex items, the smaller flex items will be stretched to fit the flex container.
This results in all flex items having equal cross sizes/heights.
Cross size determined by container
If the flex container has a set cross size (such as a set height
), each smaller flex item will be stretched to fit the flex container's cross size.
This results in all flex items having equal cross sizes/heights.
Overflow (cross axis)
If there is a shortage of free space in the cross dimension, flex items may overflow their flex container.
How do flex items stretch?
When a flex item is “stretched”, its outer margin edge will become flush with the cross-start and cross-end of the flex container's content box. This results in a larger content box cross size for the flex item.
If the margin box of the flex item has no value, then its margin edge will be flush against whichever of the flex item's box model has a value. Falling back in the following order: margin > border > padding > content
Exceptions to flex item stretch
Height
If a flex item has a set height
, then the item will not be be stretched. The item will be sized in the cross axis to this height and will be aligned to the cross-start of the flex container.
Min/max-height
If a min
/max-height
value is set, the flex item will be stretched, however, its cross size will be limited by these values.
Auto margins
e.g. margin-top: auto
If a flex item has an auto
margin in the cross axis, then this margin will take the positive free space for itself, preventing the item stretching. The margin will push the flex item's box content away from the cross edge.
If the flex item has auto margins set on both cross sides and free space is available, this will center the flex item within the cross axis. The free space is equally shared by the margins.
Flex item - default ordering
order: 0;
By default, flex items will display in their source document order following the main axis direction from left-to-right.
This default order can be overridden by specifying an integer value for the flex item. Items with an order greater than zero will display after items with a smaller order value.
Flex item - default sizing
What properties and values define how flex items are sized within the container.
The default flex item sizing properties, relate to three sizing questions:
flex-grow
- can the flex item grow, if there is space available?
flex-shrink
- can the flex item shrink, if there is a shortage of space?
flex-basis
- what is the flex item's initial size, before any resizing occurs?
The application of these properties are dependent upon:
- the content size of the flex items
- the available free space within the flex container
Flex item growth
flex-grow: 0;
By default, flex items do not grow beyond their initial content-size.
The flex items have a growth factor/value of 0
.
If there is positive free space available within the flex container, the flex items are inflexible.
Flex item shrinkage
flex-shrink: 1;
flex items are allowed to shrink by default.
This is because each flex item has a shrink-factor of 1
.
Shrinking happens when the summed flex items are larger than the flex container, resulting in negative free space (a shortage of space).
Flexbox will distribute this negative free space when applying the flex-shrink factor to its flex items.
As each flex item has the same flex-shrink value, you would think each flex item would shrink by the same amount, but this is not the case.
The flex shrink factor determines the items shrink rate and should not to be confused with the shrink amount.
The amount each item shrinks depends upon its base size (content) and its shrink factor.
As seen in Section 7.1 of the specification:
Note: The flex shrink factor is multiplied by the flex base size when distributing negative space. This distributes negative space in proportion to how much the item is able to shrink, so that e.g. a small item won’t shrink to zero before a larger item has been noticeably reduced.
The larger flex items will proportionally shrink more than their smaller siblings. This means that when large items are present, the smaller items are less likely to shrink to a tiny unreasonable size.
Furthermore, default flex items will not shrink below their smallest content size (min-content
).
The
min-content
sizing keyword represents the intrinsic minimum width of the content. For text content this means that the content will take all soft-wrapping opportunities, becoming as small as the longest word.
-- mdn web docs
For replaced elements, such as img
, video
or input
:
the min-content
size is the natural/intrinsic size of the element or the browser set default size (unless overridden by CSS).
Overflow (main axis)
If there is a shortage of free space in the main dimension, flex items may overflow the flex container.
Flex item initial size
flex-basis: auto;
flex-basis
relates to the flex item's initial main size, before any growth or shrinking is applied.
The default auto
value, is equal to the max-content
size of the flex item.
The
max-content
sizing keyword represents the intrinsic maximum width or height of the content. For text content this means that the content will not wrap at all even if it causes overflows.
-- mdn web docs
If free space is available within the flex container, the flex item will appear as big its contents and will not grow beyond this.
Default layout - Resolving flexible lengths
How and when should flex items grow or shrink?
Please note:
The following is an oversimplification of the flexbox sizing algorithm and concerns default layout only.
1. Determine the used flex factor
When sizing flex items, flexbox determines whether the flex container has positive or negative free space.
Flexbox does this by summing the flex items outer hypothetical main sizes and compares this sum against the inner main size of the flex container.
If the sum is less than the flex container's, then there is positive free space, otherwise, there is negative free space.
if there is positive free space
then the flex grow factor is used
if there is negative free space
then the flex shrink factor is used
2. Size inflexible items
Before flexbox applies flex grow or shrink, it first determines if any flex items are inflexible.
When there is positive free space, the flex-grow
factor applies. However, flex items are inflexible in this case, as their flex grow factor is zero.
Flex items in this scenario are set to their target hypothetical main size, this is their max-content
size clamped by min/max sizing.
3. Calculate the initial free space
In this step, flexbox will calculate the amount of free space available within the flex container. This free space can either be positive or negative.
Both frozen and unfrozen flex items are included in this calculation.
4. Loop and distribute free space
In default layout, if the algorithm has got to this step, it can mean one of two things regarding the space in the flex container:
if there is no free space
do nothing
if there is negative free space
apply the flex shrink factor
Applying the free shrink factor
Flexbox will distribute negative free space by calculating a target size for each flex item. The target size will take into account its content-size, shrink factor and shrinkable siblings, like so:
For each unfrozen flex item:
Calculate its scaled flex shrink factor
flex-shrink factor 1 multiplied by its inner base size
Calculate its shrink ratio
its scaled shrink factor / sum of the scaled flex shrink factors of all unfrozen items on the line
Reduce the flex item by a fraction of the absolute negative free space proportional to its shrink ratio
item base size - (abs. negative free space multiplied by its shrink ratio)
In this example, we'll focus on the first flex item and the the application of The flex container has negative free space: When expressed as an absolute number, the negative free space is: The first flex item in the row has a base size of: Its scaled flex factor is: Its shrink ratio is: Its target flex item size is: Its shrink amount is: worked example of default flex shrink
flex-shrink: 1;
-400px
600px - (100px + 200px + 300px + 400px) = -400px
This is the flex container's main size minus the total main size of the flex items.400px
100px
100
100 * 1 = 100
0.1
100 / (100 * 1, 200 * 1, 300 * 1, 400 * 1) = 0.1
60px
100px - (400 * 0.1) = 60px
-40px
-400 * 0.1 = -40px
Alternatively, the flexbox algorithm will exit this loop, when there is no remaining free space left to distribute.
Once the loop is complete, the used main size is set to the target main size, its final size.
Summary
Often CSS can be tricky when we don't fully understand how it works.
Assuming that the web page is written in English, we can assume that display: flex
will most likely create:
- a block styled flex container
- a single row of flex items
- left-to-right ordered flex items
- equal height flex items
-
max-content
sized flex items unless shrunk -
min-content
sized flex items when shrunk - content overflow if the flex container is smaller than the final size of its flex items
If it doesn't, we can check for possible causes:
a default flexbox value may have been overridden
(e.g.flex: 1
,flex-direction: column
)additional layout values may have been set
(e.g.height
,width
)the document may have a different writing mode
(e.g.veritical-rl
)
Its also worth remembering that not all flex items are flexible, and that flex item sizing is based upon the flex item's content, unless overridden.
Related reading
- CSS Tricks - A Complete Guide to Flexbox
- Learn CSS Layout - the pedantic way - 4. Flexbox
- Samantha Ming - flex-shrink calculation
- MadeByMike- Understanding flexbox
- Smashing Magazine - Flexbox: How Big Is That Flexible Box?
- Smashing magazine - What Happens When You Create A Flexbox Flex Container?
- CSS Flexible Box Layout Module Level 1 specification
- CSS Writing Modes Level 3 specification
Top comments (0)