CSS Flexbox: A Reference

Mariel de la Garza, Former Developer

Article Categories: #Code, #Front-end Engineering

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 container
  • display: 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.

Go back to Contents

`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 current writing-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 current writing-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 your writing-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 your writing-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.

Go back to Contents

`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 book
  • flex-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

Go back to Contents

`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.

Go back to Contents

`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 as start.
  • 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 as end.
  • justify-content: center - Items are packed flush to each other toward the center of the alignment container along the main axis
  • justify-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 axis
  • justify-content: end - Items are flush with the end edge of the container in the main axis
  • justify-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 like start.
  • 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 like start.
  • justify-content: normal - In grid and flex containers, this values behaves as stretch. In other instances, items are packed in their default position as if no justify-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 by flexbox.

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.

Go back to Contents

`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 line
  • align-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 to auto, and neither of the cross axis margins are auto, 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 as stretch

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.

Go back to Contents

`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 as start.
  • 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.

Go back to Contents

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.

Go back to Contents

`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?

Go back to Contents

`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 - Using auto tells the item to get and use the value of the width or height, whichever follows the main axis. If that value is also auto, then the value that's used is content (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. The content 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 using auto and a main size (width or height) of auto.

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.

Go back to Contents

`flex` #

What is it? Like flex-flow for the container, flex is a shorthand for:

  • flex-grow
  • flex-shrink and
  • flex-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 as flex: 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. Using auto margins can align the items along the main axis.

  • flex: auto - This is the same as flex: 1 1 auto. This sizes the item based on height and width, but unlike flex: initial, it makes the items fully flexible along the main axis. To avoid unintended spacing, note that if all items are either flex: auto, flex: initial, or flex: none, any space left after the items have been sized is distributed evenly to items with flex: auto.

  • flex: none - This is the same as flex: 0 0 auto. Items are sized according to height and width, but they are fully inflexible. Items marked flex: none are not allowed to shrink, even when there's an overflow.

  • flex: [positive number] - This is the same as flex: [positive number] 1 0. The item is flexible and the flex-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.

Go back to Contents

`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.

Go back to Contents

Additional Resources #

Below are links to more reading and even a couple of games to help reinforce your understanding of flexbox.

Reading

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!"

Related Articles