CSS Flexbox: A Reference
Mariel de la Garza, Former Developer
Article Categories:
Posted on
Need help with flexbox, don't like reading specs, but still need good explanations? Here's a rundown of every property and value, with examples!
Flexbox is a layout method that consists of boxes that ... flex. Content is organized in boxes that can grow and shrink in size and be arranged in rows and columns. This layout method allows a site to be responsive, which creates a better experience for a user. The pattern used with flexbox
is a parent (also called a 'container') that holds the other boxes, called children (the 'flex items'). There might be one parent and one set of children, or a child might contain its own children. Either way, all you need to know to start understanding the flexbox
properties is whether you're styling a container or something inside it.
Flexbox is a one-dimensional layout, meaning its properties and specifications deal with a row or a column. This is different from CSS Grid, which is two-dimensional and lays out both rows and columns at once. By nesting containers and items you can create what looks like a grid
layout with flexbox
. The flexbox
property has been around in various ways since about 2009 and came about as a way to help ease the creation of responsive layouts. While a step up from relying on properties like float
, flexbox
being one-dimensional limits its potential when it comes to the complex layouts we want for all of the different devices and ways to consume media that exist today. In March of 2017, CSS Grid was released as a full-fledged CSS specification, shipped with major browsers, and has since become the preferred layout method of many designers and developers. It has full support in browsers like Chrome and Safari and has partial support in IE 10 and 11.
So if grid
is newer and has become favored over flexbox
for many, why bother learning flexbox
? Because of its history of use, flexbox
is going to be around for a while. Bootstrap, a popular CSS framework, actually relies on flexbox
, even for its grid
design. Other frameworks may also rely on flexbox
, and you'll see it in code you work on yourself. Additionally, because it lacks complete support, you'll need to use flexbox
for IE11, or include flexbox
fallbacks if you use grid
. It's not a matter of learning flexbox
or grid
, but understanding both and learning when to use each (sometimes even using them together!).
For a thorough discussion and comparison of grid
and flexbox
, visit the MDN page on the "Relationship of grid layout to other layout methods". For more about how to use the Grid Layout, check out Viget's "Getting Started with CSS Grid" Part 1, Anatomy and Part 2, Three Coding Approaches.
Below is a rundown of parent properties, followed by child properties. We cover what they are, what the value options are, and what they look like. Each property has a JSFiddle below it illustrating what the different values will do. You can click on the JSFiddle and go edit it directly to experiment with the code yourself. For additional resources, check those listed in the "Resources" section.
Parent (flex-container) #
`display` #
What is it?
The display
property is where you tell a stylesheet how it should treat the item you're styling: should it be treated as an inline element? Or block? Or flex? Or both?
By setting display
to flex
, you're telling your element that it's now a flex container and will have items that go inside it. Note that flex
alone doesn't tell a container everything it should do with the items inside it. In the examples below, you'll see that the orange items can actually overflow the blue container they're in if we make it too small. Try widening and narrowing your browser window to observe the changes at different widths. Below, we'll cover flex-wrap
, which can help avoid the overflow issue altogether.
What are the options?
display: flex
- Tells your element that it's a flex containerdisplay: inline-flex
- While it's a flex container, it will also be displayed inline. This does not affect the container's children - those will still be regular flex items that need their own styling. An inline parent does not mean the children are also inline.
`flex-direction` #
What is it? The "flex-direction" property tells your container which direction its items should go in and therefore also says which direction the main-axis is going in.
Direction is writing-mode
sensitive. For languages that are written and read horizontally, like English, we use the horizontal-tb
mode, indicating our text is going left to right, top to bottom. When the direction is row
, the main axis runs left and right, and the cross axis goes up and down. If the direction is column
, then the main axis goes up and down along the column and the cross axis goes left and right.
There are other languages (and thus writing-modes) that run horizontally right-to-left, and still others that run vertically. Understanding and noting the writing mode and direction you are working in becomes important for internationalization. Interestingly, the different writing modes are why we use start
and end
when discussing direction instead of only using right
and left
. For a really deep and interesting discussion on writing modes and CSS, see "CSS Writing Modes" by Jen Simmons.
What are the options?
flex-direction: row
- This tells your container that the main axis goes the same way as the inline axis of your currentwriting-mode
. For us, that means a row is horizontal, running left-to-right.flex-direction: row-reverse
- This tells your container that, like row, its main axis is going the same way as the inline axis of your currentwriting-mode
, but to swap the main-start and main-end. For us, that means a row is horizontal and runs right-to-left.flex-direction: column
- This tells your container that its main axis is the same as the block axis of yourwriting-mode
. For us, the block axis starts at the top of a container and ends at the bottom which means your content will also run vertically, top to bottom.flex-direction: column-reverse
- Like column, you're telling your container that its main axis matches the block axis of yourwriting-mode
, but to swap its main-start and main-end. So, instead of the content running vertically, top to bottom, it will run vertically, bottom to top.
`flex-wrap` #
What is it? The "flex-wrap" property tells your container whether its items are allowed to wrap to the next line, like the lines on the page of a book, or whether they need to stay forced onto one line.
What are the options?
flex-wrap: wrap
-- Your items wrap to the next line, like the lines on the page of a bookflex-wrap: nowrap
-- Your items stay next to one another and can run outside of their container or even off the page (see below example)flex-wrap: wrap-reverse
-- Items wrap to the next line, but their order is reversed
`flex-flow` #
What is it?
"Flex-flow" is actually shorthand that combines flex-direction
and flex-wrap
, so you only need to specify the one combined property instead of direction
and wrap
separately.
What are the options?
The options draw from both direction
and wrap
, so there are combinations for each one. You can also use flex-flow
to specify only direction
or only wrap
. You do not need to specify both in order to use flex-flow
.
`justify-content` #
What is it?
In a flex container, the justify-content
property tells your container and its items how to share the space between and around the items along the main axis. Remember from flex-direction
that the main axis is determined by the direction, which in turn is determined by writing-mode
- if the direction is row
, then your main axis is horizontal. If the direction is column
, then the main axis is vertical.
What are the options?
When you look up the options for the justify-content
property, beware that not all of them apply to flexbox
, and not all of those applicable to flexbox
will work on other items.
justify-content
values used in flexbox
:
justify-content: flex-start
- Items packed flush to each other toward the edge of the container's main-start side. For items that are not children of a flex container, this value is treated the same asstart
.justify-content: flex-end
- Items packed flush to each other toward the edge of the container's main-end side. For items that are not children of a flex container, this value is treated the same asend
.justify-content: center
- Items are packed flush to each other toward the center of the alignment container along the main axisjustify-content: space-between
- Items are evenly distributed within alignment container along the main axis. Spacing between each pair of adjacent items is the same. The first item is flush with the main-start edge, and the last item is flush with the main-end edge.justify-content: space-around
- Items evenly distributed within the alignment container along the main axis. Spacing between each pair of adjacent items is the same. The empty space before the first item and after the last item equals half of the space between each pair of items.justify-content: space-evenly
- Items evenly distributed with the alignment container along the main axis. Spacing between each pair of adjacent items, the main-start edge and the first item, and the main-end edge and the last item, are all exactly the same.
Other justify-content
values:
justify-content: start
- Items are flush with the start edge of the container in the main axisjustify-content: end
- Items are flush with the end edge of the container in the main axisjustify-content: left
- The items are packed flush toward each other toward the left edge of the alignment container. If the property's axis is not parallel with the inline axis, this value behaves likestart
.justify-content: right
- Items are packed flush to each other toward the ridge edge of the alignment container. If the property's axis is not parallel with the inline axis, this value behaves likestart
.justify-content: normal
- In grid and flex containers, this values behaves asstretch
. In other instances, items are packed in their default position as if nojustify-content
value was set.justify-content: stretch
- If the combined size of the items along the main axis is less than the size of the alignment container, any auto-sized items have their size increased equally while still respecting the constraints imposed by max-height and max-width, so that the combined size exactly fills the alignment container along the main axis. Note:stretch
is not supported byflexbox
.
What does that look like?
The below examples are for flex-flow: row wrap
. We've fixed the width and removed the margin from the left and right of the items so it's easier to see what's happening in space-between
, space-around
, and space-evenly
.
`align-items` #
What is it?
When using flexbox
, align-items
controls the alignment of items on the cross axis. Remember from flex-direction
that the cross axis is determined by your direction, which in turn is determined by writing-mode
. If your direction is row
, your cross axis is going to be vertical (up and down). If your direction is column
, your cross axis is horizontal (left and right).
What are the options?
Similar to what we saw in justify-content
, not all values apply to flexbox
and not all values that apply to flexbox
will work in other layout modes. For a list of all align-items
values and illustrations, visit the MDN align-items page and the W3 flexbox page.
align-items: flex-start
- Cross-start margin edges of flex items are flush with the cross-start edge of the line.align-items: flex-end
- The cross-end margin edges of the flex items are flush with the cross-end edge of the linealign-items: center
- The items' margin boxes are centered within the line on the cross axis. if the cross-size of an item is larger than the flex container, it will overflow equally in both directions.align-items: baseline
- All items are aligned such that their baselines align. The item with the largest distance between its baseline and its cross-start margin edge is placed flush against the cross-start edge of the line. If the item doesn't have a baseline in the necessary axis, one is synthesized from the item's border box.align-items: stretch
- If the cross-size property of the flex-item computes toauto
, and neither of the cross axis margins areauto
, then the item is stretched. Its value is the length necessary to make the cross-size of its margin box as close to the same size as the line as possible, while respecting any min or max height or width.align-items: normal
- Behaves the same way asstretch
What does that look like?
For the examples below, we've added background colors, set the item width at 50px, and given them varying minimum heights so it's easier to see the change in behavior for each value. The flex-direction
is row
, which dictates what the main and cross axes are. For flex-start
, imagine a line going across the top of each box. For flex-end
, imagine a line across the bottom. For center
, imagine a line going through the center of each box and notice how this affects how the boxes line up with one another.
`align-content` #
What is it?
When there's extra space along a container's cross axis, the align-content
property affects how items appear on that container's lines. It lines up the items as a whole. It has no effect on single-line containers because only multi-line containers will have any extra space along the cross axis. In a single-line container, that one line will automatically stretch to fill the space.
What are the options?
The below values are applicable to your flex-container. For a list of all align-content
values and how they affect non-flex layouts, see the MDN page or W3 page.
align-content: flex-start
- Moves items to be flush against the edge of the container, depending on the cross-start side. For non-flex layouts, this is treated the same way asstart
.align-content: flex-end
- Moves items to be flush against the edge of the container depending on the cross-end side.align-content: center
- Packs items flush to one another in the center of the container along the cross axis. For a container whose direction is "row", the cross axis is up and down. Equal amounts of space are given between the cross-start edge and the container's first line, and the cross-end edge and the container's last line.align-content: space-between
- With lines evenly distributed in the container, the content edges are flush with the cross-start and cross-end edges of the container. Remaining lines are distributed so the spacing between any two adjacent lines is the same.align-content: space-around
- With lines evenly distributed in the container and a half-size space on either end, the spacing between any two adjacent lines is the same and the spacing between the first and last lines and the flex container edges is half the size of the spacing between the lines.align-content: stretch
- Lines stretch to take up remaining space. Free-space is split equally between all lines, which increases their cross-size.
What does that look like? The definitions for align-content
are lengthy, so the best way to see what's happening is to use examples. Carefully compare the differences between align-content
and align-items
. The align-items
property affects both: how items are aligned along the lines and along the cross axis. This difference is easiest to see in the center
value.
Children (Flex-Items) #
`flex-grow` #
What is it? The flex-grow
property tells an item how much it should grow in relation to the rest of the items in the container when free space is distributed. Unlike other properties, the flex-grow
value does not have a unit attached to it. If no value is set, the default is 1.
What are the options? It must be a number, but it can be positive or negative. All you're doing is describing its relation to other items.
What does it look like? Below, we have 4 items arranged in a row. The flex-grow factors for each are 1
, 1
, 2
, and 1
. By widening and narrowing your browser window, you can see the items in the JSFiddle grow and shrink. Item number 3 is 2 times the size of items 1, 2, and 4. If you open the JSFiddle you can edit the CSS and test what happens with different values, including negative values.
`flex-shrink` #
What is it? Similarly to flex-grow
, with flex-shrink
you are describing how much an item should shrink in relation to other items in the same container. If no value is specified, it's set to 1. Like flex-grow
, there is no unit attached to the value.
What are the options? It must be a number, but can be positive or negative. All you're doing is describing its relation to other items.
What does it look like? Below, we have 4 items arranged in a row. The flex-grow
factor for each item is 1
, but the flex-shrink
values are: 1
, 1
, 2
, and 1
. If you widen and shrink the browser window, you'll see what the flex-shrink
value does in the JSFiddle as the window changes size; it's most obvious when the window is made very narrow. Watch how item 3 changes in relation to the other items: What happens when you make the browser window as wide as your screen? What happens as you narrow it?
`flex-basis` #
What is it? The flex-basis
is the initial size of the flex-item before any other flex factors are applied. If you don't specify it, the default value is 0.
What are the options? You may use the same values as those for width
and height
, including auto
and content
. You may not use negative values.
auto
- Usingauto
tells the item to get and use the value of the width or height, whichever follows the main axis. If that value is alsoauto
, then the value that's used iscontent
(below).content
- The item's content is used to set the size and adjustments are made to handle aspect ratios, sizing constraints, and orthogonal flows. Thecontent
property was a later addition to the flexbox layout so older implementations of the layout may not support it. You can get the same effect by usingauto
and a main size (width
orheight
) ofauto
.
What does it look like? The items in the JSFiddle below all have the same flex-grow
value of 1
and the same flex-basis
of 5em
. Item 3 has a flex-shrink
value of 2. The items are the same initial size because they have the same flex-basis
, but that as the window narrows, Item 3 ends up smaller because of its flex-shrink
value.
`flex` #
What is it? Like flex-flow
for the container, flex
is a shorthand for:
flex-grow
flex-shrink
andflex-basis
The last two values - flex-shrink
and flex-basis
- are optional. The default for flex
is flex: 0 1 auto
. Note: The initial values of flex-grow
and flex-basis
are different from their defaults when omitted in the flex
shorthand. The default for flex-grow
is normally 1
, and the default for flex-basis
is auto
. This change is so that the use of flex
can accommodate the most common cases. By default, flex items won't shrink below the minimum content size so if you want different behavior, you'll need to set the min-width
or min-height
property.
What are the options? Like the values it represents, the flex
shorthand can have numbers, auto
, content
, and units for width and height like em
. The W3 specs note four of the "most commonly-desired effects" that account for the change in default values discussed above.
flex: initial
- This is the same asflex: 0 1 auto
. The item is sized based on height and width. If the main-size (the size following the main axis) is auto, the item flexes based on its contents. This setting makes the item inflexible when there's positive free space, but allows it to shrink to its minimum size if needed. Usingauto
margins can align the items along the main axis.flex: auto
- This is the same asflex: 1 1 auto
. This sizes the item based on height and width, but unlikeflex: initial
, it makes the items fully flexible along the main axis. To avoid unintended spacing, note that if all items are eitherflex: auto
,flex: initial
, orflex: none
, any space left after the items have been sized is distributed evenly to items withflex: auto
.flex: none
- This is the same asflex: 0 0 auto
. Items are sized according to height and width, but they are fully inflexible. Items markedflex: none
are not allowed to shrink, even when there's an overflow.flex: [positive number]
- This is the same asflex: [positive number] 1 0
. The item is flexible and theflex-basis
is 0, so it receives the specified proportion of free space in the container. If all items use this pattern, their sizes will be proportional to the specified flex factor.
What does it look like? Below we have the same 4 items, and by only using flex
and a couple values, we see the beginning of a decent layout.
`align-self` #
What is it? The align-self
property is specific to individual items, where align-items
applied to all of the items at once. By using align-self
, you can override the settings in align-items
as needed.
What are the options? The options for align-self
are the same that are available for align-items
:
flex-start
flex-end
center
baseline
stretch
- This is the default. The item will stretch to fill its container while respecting the min and max width.
What does it look like? Below, each item is set to one of the available options. To compare with align-items
, look at the JSFiddle in that section.
Additional Resources #
Below are links to more reading and even a couple of games to help reinforce your understanding of flexbox.
Reading
- CSS Flexible Box Layout Module Level 1, W3 Specifications
- CSS Box Alignment Module Level 3, W3 Specifications
- "A Complete Guide to Flexbox", by Chris Coyier (CSS-Tricks)
- Properties Almanac, CSS-Tricks
Games
Flexbox Defense - "Your job is to stop the incoming enemies from getting past your defenses. Unlike other tower defense games, you must position your towers using CSS!"
Flexbox Froggy - "Welcome to Flexbox Froggy, a game where you help Froggy and friends by writing CSS code!"