Flexbox in CSS
The layout model known as Flexbox (flexes) is becoming increasingly popular. Primarily due to its convenient use in creating frameworks and layouts for individual HTML elements on a page. Secondly, due to its completely new capabilities. In this article, I will try to delve into all the intricacies of Flexbox, create a kind of cheat sheet for flexes, and share my knowledge with you in an accessible way.
In short, when it comes to flex documentation, Flexbox layout provides simple solutions to once complex tasks. For example, when you need to align an element vertically, or stick the footer to the bottom of the screen, or simply insert multiple blocks in a single row so that they occupy all available space. Similar tasks can be solved without flex. However, these solutions usually resemble more like "crutches," and this becomes even more complicated when you need to create a responsive layout for mobile devices. In contrast, with flexbox, such tasks are elegantly solved just as the flex model intends (without adding auxiliary styles and the like).
The CSS Flexible Box Layout Module (CSS module for flexible blocks), or flexbox, was created to eliminate the shortcomings when creating various HTML constructs, including those adapted for different widths and heights, and to make the layout logical and simple. A logical approach usually works in unexpected places, where the result has not been verified - logic is everything!
Flexbox allows for elegant control over various parameters of elements inside a container: direction, order, width, height, alignment along and across, distribution of free space, stretching and compressing of elements.
Also read: Grid in CSS
Basic Knowledge
FlexBox consists of a Container and its Child elements (items) (flexible elements).
-
Main Axis - the main direction of movement of elements inside the container. The direction of the main axis can be changed using the flex-direction property. Note that when axes are changed, only the directions of movement of blocks inside change, while the start, end, and size of the container remain the same.
-
Start and End of the Main Axis - elements are positioned from the start to the end of the container.
-
Cross Axis - the direction of movement of elements when they do not fit into the container along the main axis. The cross axis is always perpendicular (⊥) to the main axis.
-
Start and End of the Cross Axis - rows are filled along the cross axis from the start to the end of the container. In each such row, elements are arranged (see below).
- Size (main and cross) - the basic value by which the width or height of internal elements is calculated, if the size is not specified precisely (specified in percentages or not specified at all, and the element needs to stretch or compress).
To enable flexbox, it is sufficient to assign the display: flex;
or display: inline-flex;
CSS property to any HTML element.
<style> .flex{ display: flex; } </style> <div class="flex"> <div class="item">1</div> <div class="item">2</div> </div>
After enabling the flex properties, two axes are created inside the container: the main and cross axes (perpendicular, cross axis). All nested elements (first level) are arranged along the main axis. By default, the main axis is horizontal and has a left-to-right direction (→), and the cross axis is vertical and directed from top to bottom (↓).
The main and cross axes can be swapped, so the elements will be arranged from top to bottom (↓) and when they no longer fit in height, they will move from left to right (→) - in other words, the axes have simply swapped places. At the same time, the start and end positions of the elements do not change - only the directions (axes) change! This is why it is necessary to visualize the axes inside the container. However, it is not necessary to think that there are any "physical" axes and they have an impact on something. The axis here is only the direction of movement of elements inside the container. For example, if we specified the alignment of elements in the center of the main axis and then changed the direction of this main axis, the alignment would change: the elements were in the middle horizontally, and now they are in the middle vertically... See example.
Another important feature of Flexbox is the presence of rows in the cross direction. To understand what this means, let's imagine that there is a main horizontal axis, many elements, and they do not "fit" in the container, so they move to another row. That is, the container looks like this: a container, inside it two rows, with several elements in each row. Can you imagine it? And now remember that we can align not only elements but also rows along the vertical axis! How this works is clearly seen in the example for the align-content property. Here is a schematic representation:

CSS properties that can affect the layout construction model: float
, clear
, vertical-align
, columns
do not work in flex constructs. A different layout construction model is used here, and these CSS properties are simply ignored.
CSS Flexbox Properties
Flexbox contains various CSS rules for controlling the entire flex construction. Some need to be applied to the main container, and others to the elements of this container.
For the container
- display:
Includes the flex property for the element. This property affects the element itself and its nested elements: only the first-level descendants are affected - they become flex container elements.
- flex - the element stretches to the full width and has its own space among the surrounding blocks. Line breaks occur at the beginning and end of the block.
- inline-flex - the element flows around other elements. Its inner part is formatted as a block element, and the element itself is treated as an inline element.
flex and inline-flex differ in how they interact with surrounding elements, similar to
display: block
anddisplay: inline-block
.- flex-direction:
Changes the main axis direction of the container. The cross axis changes accordingly.
- row (default) - direction of elements from left to right (→)
- column - direction of elements from top to bottom (↓)
- row-reverse - direction of elements from right to left (←)
- column-reverse - direction of elements from bottom to top (↑)
It is important to understand that when transitioning from
row
tocolumn
or fromrow-reverse
tocolumn-reverse
, only the axis direction changes and nothing else. The beginning and end of block placement remains unchanged (see the image at the beginning). That is, if withrow
the elements started their path from the right/top, then withcolumn
everything will remain the same - only the direction will change. (see flex-wrap property example)- flex-wrap:
Controls the wrapping of elements that do not fit into the container.
- nowrap (default) - nested elements are placed in a single row (when direction=row) or in a single column (when direction=column) regardless of whether they fit into the container or not.
- wrap - enables wrapping of elements onto the next row if they do not fit into the container. This activates the movement of elements along the cross axis.
- wrap-reverse - same as wrap, but the wrapping will be upwards (in the opposite direction).
- flex-flow: direction wrap
Combines both
flex-direction
andflex-wrap
properties. They are often used together, so theflex-flow
property was created to write less code.flex-flow
takes the values of both of these properties, separated by a space. Or you can specify a single value for any property./* only flex-direction */ flex-flow: row; flex-flow: row-reverse; flex-flow: column; flex-flow: column-reverse; /* only flex-wrap */ flex-flow: nowrap; flex-flow: wrap; flex-flow: wrap-reverse; /* both values at once: flex-direction and flex-wrap */ flex-flow: row nowrap; flex-flow: column wrap; flex-flow: column-reverse wrap-reverse;
- justify-content:
Aligns elements along the main axis: if direction=row, then horizontally, and if direction=column, then vertically.
- flex-start (default) - elements will go from the beginning (there may be space left at the end).
- flex-end - elements are aligned to the end (space will remain at the beginning)
- center - at the center (space will remain on the left and right)
- space-between - outer elements are pushed to the edges (space between elements is distributed evenly)
- space-around - free space is evenly distributed between elements (outer elements are not pushed to the edges). The space between the container edge and the outer elements will be half as much as the space between the elements in the middle of the row.
- space-evenly - same as space-around, but the distance from the outer elements to the edges of the container is the same as between the elements.
- align-content:
Aligns rows containing elements along the cross axis. Similar to
justify-content
but for the opposite axis.Note: Works only when the container height is fixed (higher than the rows inside it).
That is, if
flex-direction: row
, then this property will align the invisible rows vertically↕
. It is important to note that the block height must be set rigidly and must be greater than the height of the rows, otherwise the rows themselves will stretch the container and any alignment loses its meaning, because there is no free space between them.But when
flex-direction: column
, the rows move horizontally↔
and the container width is almost always greater than the width of the rows, and aligning the rows immediately becomes meaningful.This property is rarely needed and is often replaced by
align-items
(see below).- stretch (default) - rows stretch to fill the entire line
- flex-start - rows are grouped at the top of the container (there may be space left at the end).
- flex-end - rows are grouped at the bottom of the container (space will remain at the beginning)
- center - rows are grouped in the center of the container (space will remain on the edges)
- space-between - outer rows are pushed to the edges (space between rows is distributed evenly)
- space-around - free space is evenly distributed between rows (outer elements are not pushed to the edges). The space between the container edge and the outer rows will be half as much as the space between the elements in the middle of the row.
- space-evenly - same as space-around, but the distance from the outer elements to the edges of the container is the same as between the elements.
- align-items:
Aligns elements along the cross axis within a row (invisible line). That is, the rows themselves are aligned via
align-content
, and the elements inside these rows (lines) viaalign-items
, all along the cross axis. There is no such division along the main axis, there is no concept of rows and elements are aligned viajustify-content
.- stretch (default) - elements stretch to fill the line completely
- flex-start - elements are aligned at the beginning of the row
- flex-end - elements are aligned at the end of the row
- center - elements are aligned in the center of the row
- baseline - elements are aligned along the baseline of the text
- column-gap:
- gap:
Sets the size of the gap between elements in the container. Accordingly:
column-gap:
— only spreads columns.gap:
— spreads both columns and rows.
Sizes can be specified in absolute or relative values:
px, em, ...
or in%
.Support for
gap
{percent} (the support forcolumn-gap
is exactly the same):
For container elements
- flex-grow:
Sets the coefficient for increasing the element when there is available space in the container. By default,
flex-grow: 0
, meaning none of the elements should increase and fill the available space in the container.By default
flex-grow: 0
Examples:
- If all elements are given
flex-grow: 1
, they will all stretch equally and fill all available space in the container. - If one of the elements is given
flex-grow: 1
, it will fill all available space in the container, and alignment throughjustify-content
will no longer work: there is no space to align... - With
flex-grow: 1
, if one of them hasflex-grow: 2
, it will be twice as large as all the others. - If all flex blocks inside the flex container have
flex-grow: 3
, they will be of the same size. - With
flex-grow: 3
, if one of them hasflex-grow: 12
, it will be four times larger than all the others.
How does it work? Let's say the container has a width of 500px and contains two elements, each with a base width of 100px. This means there are 300 free pixels in the container. Now, if we set flex-grow: 2; for the first element and flex-grow: 1; for the second one, the blocks will take up the entire available width of the container, and the width of the first block will be 300px, and the second one 200px. This is because the available 300px of free space in the container is distributed between the elements in a 2:1 ratio, +200px to the first and +100px to the second.
Note: Fractional numbers can be specified in the value, for example: 0.5 -
flex-grow: 0.5
- If all elements are given
- flex-shrink:
Sets the reduction coefficient of the element. This property is opposite to
flex-grow
and determines how the element should shrink if there is no available space in the container. That is, the property starts working when the sum of the sizes of all elements is greater than the size of the container.By default
flex-shrink: 1
Suppose the container has a width of 600px and contains two elements, each with a width of 300px - flex-basis: 300px;. That is, two elements completely fill the container. Let's set flex-shrink: 2; for the first element and flex-shrink: 1; for the second one. Now let's reduce the width of the container by 300px, i.e., the elements should shrink by 300px to fit inside the container. They will shrink in a 2:1 ratio, i.e., the first block will shrink by 200px, and the second one by 100px, and the new sizes of the elements will be 100px and 200px.
Note: You can specify a float values for the property, for example:
flex-shrink: 0.5
.- flex-basis:
Sets the base width of the element - the width before other conditions affecting the width of the element are calculated. The final width will depend on the base width and the values of
flex-grow
,flex-shrink
, and the content inside the block.The value can be specified in px, em, rem, %, vw, vh, etc.
With auto, the element gets a base width relative to the content inside it.
By default: auto
Sometimes it's better to set the width of the element firmly using the familiar
width
property. For example,width: 50%;
will mean that the element inside the container will be exactly 50%, but at the same time,flex-grow
andflex-shrink
properties will still work. This may be necessary when the element stretches the content inside it beyond what is specified in flex-basis. See the example in the notes.flex-basis
will be "firm" if you nullify stretching and shrinking:flex-basis: 200px; flex-grow: 0; flex-shrink: 0;
. All this can be written asflex: 0 0 200px;
.- flex: {grow shrink basis}
A shorthand for three properties:
flex-grow
,flex-shrink
,flex-basis
.By default: flex: 0 1 auto
However, you can specify one or two values:
flex: none; /* 0 0 auto */ /* number */ flex: 2; /* flex-grow (flex-basis becomes 0) */ /* not a number */ flex: 10em; /* flex-basis: 10em */ flex: 30px; /* flex-basis: 30px */ flex: auto; /* flex-basis: auto */ flex: content; /* flex-basis: content */ flex: 1 30px; /* flex-grow and flex-basis */ flex: 2 2; /* flex-grow and flex-shrink (flex-basis becomes 0) */ flex: 2 2 10%; /* flex-grow, flex-shrink, and flex-basis */
- align-self:
Allows changing the
align-items
property for an individual element.By default: from the align-items of the container
- stretch - the element stretches to fill the entire line
- flex-start - the element is aligned to the start of the line
- flex-end - the element is aligned to the end of the line
- center - the element is aligned to the center of the line
- baseline - the element is aligned to the text baseline
- order:
Allows changing the order (position) of the element in the overall row.
By default: order: 0
By default, elements have
order: 0
and are placed in the order they appear in the HTML code and the direction of the row. But if you change the value of the order property, the elements will be arranged in the order of the values:-1 0 1 2 3 ...
. For example, if you setorder: 1
for one of the elements, all zero orders will come first, and then the element with 1.This way, you can, for example, move the first element to the end without changing the direction of movement of the other elements or the HTML code.
Notes
How is flex-basis different from width?
Below are important differences between flex-basis and width/height:
-
flex-basis
works only for the main axis. This means that with flex-direction:row, flex-basis controls the width, and with flex-direction:column, it controls the height. See example. -
flex-basis
applies only to flex items. This means that if you disable flex for the container, this property will have no effect. -
Absolute elements inside the container do not participate in the flex structure... Therefore, flex-basis does not affect the flex container elements if they are absolutely positioned position:absolute. They will need to specify width/height.
- When using the css property
flex
with three values: flex-grow/flex-shrink/flex-basis, you can combine and write it shortly -flex:0 0 50%
. Whereas when using width, grow, and shrink, they have to be written separately. For example: flex:0 0 50% == width:50%; flex-shrink:0;. Sometimes this is just inconvenient.
Whenever possible, still prefer flex-basis. Use width only when flex-basis is not suitable.
Difference between flex-basis and width - a bug or a feature?
The content inside a flex element expands it and cannot go beyond its boundaries. However, if you set the width using width or max-width, rather than flex-basis, the element inside the flex container will be able to go beyond the boundaries of the container (sometimes this behavior is necessary). Example:
Flex Layout Examples
In the examples, no prefixes are used for cross-browser compatibility. I did this for easy reading of the css. Therefore, see the examples in the latest versions of Chrome or Firefox.
#1 Simple example with vertical and horizontal alignment
Let's start with the simplest example - aligning vertically and horizontally at the same time and at any height of the block, even a liquid one.
<div class="parent"> <span class="child">Text in the middle</span> </div> <style> .parent { display: flex; } .child { margin: auto; } </style>
Or like this, without a block inside:
<div class="center-text"> Text in the middle </div> <style> .center-text { display: flex; justify-content: center; align-items: center; } </style>
#1.2 Spacing between elements of a flex block
To place the elements of the container at the edges and arbitrarily choose the element after which there will be a gap, you need to use the margin-left:auto
or margin-right:auto
property.
#2 Adaptive menu on flex
Let's create a menu at the very top of the page. On a wide screen, it should be on the right. In the middle, it should be aligned. And on a small screen, each item should be on a new line.
<div class="nav"> <a href="#">Home</a> <a href="#">About</a> <a href="#">Products</a> <a href="#">Contact</a> </div> <style> .nav { display: flex; justify-content: flex-end; /* place it on the right */ background: #6e9cc3; } .nav a { color:#fff; padding:15px 10px; text-decoration:none; text-align:center; } .nav a:hover { background:#5c8db7; } /* less than 800px */ @media all and (max-width: 800px) { .nav { justify-content: space-around; } .nav a{ flex-grow:1; /* stretch to fill the entire width */ } } /* less than 500px */ @media all and (max-width: 500px) { .nav { flex-direction: column; } } </style>
Go to jsfiddle.net and change the width of the "result" section
#3 Adaptive 3 columns
This example shows how to quickly and conveniently create 3 columns that will transform into 2 and then into 1 when narrowed.
Note that this can be done without using media rules, all with flex.
<div class="flex"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> </div> <style> .flex{ display: flex; flex-wrap: wrap; max-width: 700px; /* max width */ margin: 0 auto; /* center align */ } .item{ flex:1 1 calc(33.33% - 30px); /* subtract margin and stretch */ margin:5px; box-sizing:border-box; /* so that the inner padding does not affect when there is text... */ min-width:170px; /* min block width to wrap to the next line */ padding:50px 20px; font-size:400%; text-align:center; background:#b5ced8; /* for beauty */ } </style>
Go to jsfiddle.net and change the width of the "result" section
#4 Adaptive blocks on flex
Suppose we need to display 3 blocks, one large and two small ones. At the same time, the blocks should adapt to small screens. Let's do it:
<div class="flex"> <div class="mainitem">1</div> <div class="sideitem"> <div class="item">2</div> <div class="item">3</div> </div> </div> <style> .flex{ display: flex; max-width: 700px; /* max block width */ margin: 0 auto; /* center align block */ font-size:400%; } .mainitem, .item{ flex-grow:1; /* stretching elements */ background:#b5ced8; display: flex; justify-content: center; align-items: center; /* center the numbers */ } .mainitem{ min-height:300px; /* height of the main block */ } .sideitem{ /* flex:0 0 150px; */ flex-basis:150px; /* width 150 */ flex-shrink:0; /* Remove shrinkage = 150 */ display: flex; flex-direction: column; } .item{ flex-basis:50%; min-height:150px; margin-left:10px; } .item:first-child{ margin-bottom:10px; } /* less than 600px */ @media screen and (max-width: 600px) { .flex{ flex-wrap: wrap; } /* for wrapping */ .sideitem{ flex-direction:row; flex-basis:100%; } .item{ margin-left:0; margin-top:10px; } .item:first-child{ margin-bottom:0; margin-right:10px; } } /* less than 450px */ @media screen and (max-width: 450px) { .sideitem{ flex-wrap: wrap; } /* allow wrapping */ .item{ flex-basis:100%; } /* for full width */ .item:first-child{ margin-right:0; } } </style>
Go to jsfiddle.net and change the width of the "result" section
#5 Gallery on flex and transition
This example shows how to quickly create a nice accordion with images using flex. Note the transition property for flex.
<div class="flex"> <div class="item img1"></div> <div class="item img2"></div> <div class="item img3"></div> <div class="item img4"></div> <div class="item img5"></div> </div> <style> .flex { display: flex; overflow:hidden; /* hide the shadow */ } .item { height:300px; flex:20%; /* = flex-basis:20%; */ transition: flex 300ms ease; box-shadow: 0 0 19px 3px #000; margin: 1px; /* shadow beauty */ } .item:hover { flex: 0.1 0.1 400px; background-size: 100% 100% } .img1 { background: url('http://lorempixel.com/400/300/cats/1') 0 0 no-repeat; } .img2 { background: url('http://lorempixel.com/400/300/cats/2') 0 0 no-repeat; } .img3 { background: url('http://lorempixel.com/400/300/cats/3') 0 0 no-repeat; } .img4 { background: url('http://lorempixel.com/400/300/cats/4') 0 0 no-repeat; } .img5 { background: url('http://lorempixel.com/400/300/cats/5') 0 0 no-repeat; } </style>
#6 Flex within flex (just an example)
The task is to create a flexible block so that the beginning of the text in each block is on the same line horizontally. i.e. when the width is narrowed, the blocks grow in height. The image should be at the top, the button should always be at the bottom, and the text in the middle should start on the same horizontal line...
To solve this task, the blocks themselves stretch with flex and have a maximum width set. Each inner block is also a flex structure, with the axis turned flex-direction:column; and the element in the middle (where the text is) stretches flex-grow:1; to fill all the available space, thus achieving the result - the text starts on the same line...
More examples
See here alexriz.github.io
Browser support - 99%
There is no full support, but all modern browsers support flexbox constructions. Some still require prefixes.
To know which prefixes are relevant today (June 2019), here is an example of all flex rules with necessary prefixes:
It is better if properties with prefixes come before the original property.
This list does not include unnecessary prefixes for today (according to caniuse), but there are actually more prefixes.
Videos
And don't forget about videos, sometimes they are also interesting and understandable. Here are a couple of popular ones:
Useful Flex Links
-
flexboxfroggy.com - a game that teaches flexbox.
-
Flexplorer - a visual flex code constructor.
- Flexbox Cheat Sheet