We at Codesmith cultivate technologists who are at the intersection of society and tech, able to meet this moment and thrive in an ever-changing world. Ready to become a modern software engineer?
CSS Flexbox (short for “Flexible box layout”) is a layout model for arranging items inside an HTML element called a flex container. It’s a powerful tool for creating one-dimensional layouts where items can easily be aligned and evenly spaced (like a navigation bar). With Flexbox, you can lay out elements in either rows OR columns. This differs from CSS Grid Layout, which is designed for two-dimensional layouts (rows AND columns). If you're new to styling, CSS Flexbox might seem tricky, but never fear! In this article, we will discuss:
A CSS flexbox always consists of two elements:
In the image below, we have:
Eventually, “container1” will become our flex container and its four divs (its children) will be our flex items.
This styling below will render the following to the page. Note how “container1” is nested within the body as it is a child component of the body. By default, block-level child elements (like “container1”) will fill the entire width of their parent element (body). However, we have explicitly set height and width properties in “container1” to only fill 75% of the body to illustrate the relationships between our parent and child elements. This will become clearer later on.
To make “container1” a flexbox, simply set the display property flex. This will:
In the image below, notice how, as soon as we turn “container1” into a flex container, its child elements automatically line up on a horizontal axis.
Now that we know how to create a flex container, how do we arrange the items within it? First, it’s crucial to understand that each flexbox has two axes – a main axis and a cross axis.
The main axis is set using the flex-direction property and can be oriented to run horizontally OR vertically.
The cross axis will always run perpendicularly to the main axis.
The flex-direction (main axis) can be set to one of four values – row, row-reverse, column, or column-reverse. Let’s take a look at how each of these values orient the items in “container1”.
row - If the flex-direction isn’t set, this is the default. This will create a horizontal main axis that starts at the left and ends on the right meaning the flex items will be laid in a left to right direction. The cross axis will run vertically from top to bottom of the container.
row-reverse - This creates a horizontal main axis where the flex items will be laid out from right to left. The cross axis will still run vertically, from top to bottom.
column - Sets the main axis to run vertically, from top to bottom of the flex container. The flex items will be stacked vertically on top of one another. Now, the cross axis will run in a horizontal direction from left to right.
column-reverse - Will create a vertical axis where flex items will be stacked in reverse order from bottom to top. The cross axis remains in a horizontal direction from left to right.
It’s a good idea to get in the habit of thinking of the directions of your main and cross axes as start to end rather than left to right. This is because writing in a right-to-left language actually changes where the horizontal axis starts and ends.
Below is an example of setting the flex-direction to row in a left-to-right language like English compared to right-to-left language (such as Arabic). If the flex-direction is set to row in a right-to-left language, the main axis starts on the right and ends on the left. However, the cross axis still runs from top to bottom. While you probably won’t encounter this issue working strictly in English, this behavior is good to be aware of!
Before moving on, let’s recap. So far, we have learned that:
Let’s take a brief moment to understand the distinction between block-level and inline elements as this concept is essential to the next section.
Block-level elements: such as a <div> or <p> take up the entire width of their parent elements. Therefore, each new block-level element starts on a new line – stacking vertically.
Inline elements: such as a <span> only take up as much width as is necessary and do not start on a new line.
Now that we are comfortable with the difference between block-level and inline, we can set our display property to more than just flex in order to transform our elements into flex containers. This gives us more control over the flex containers themselves and not just the items within them!
To visualize this, let’s add a second element to the body of our application. Now, the body element contains two divs – “container1” and “container2”.
Without setting the display of “container2”, the element will default to display: block-direction.
This means that it will sit directly underneath “container1” and stretch to fill the entire width of its parent element (body) as we can see below.
Below, we’ve set the display in “container2” to flex. This will turn it into a block-level flex-container meaning that “container2” behaves like a block-level element but its children will be arranged using flexbox rules. Remember, by default, block-level elements take up the full width of their parent element so “container2” will still fill the width of the body element.
Below, we set the display in “container2” to inline-flex. Now, it will act as an inline-level flex-container meaning that its children will still be arranged using flexbox rules but “container2” itself will act as an inline element. Because “container2” is now an inline element, it will not take up the full width of its parent (body).
But wait. If “container2” now has a display of inline-flex, why is it still block-level with “container1”? We just learned that a display of inline-flex should cause “container2” to act as an inline-level flex container so, shouldn’t it be inline (side by side) with “container1”?
The answer is, yes, it should. However, in the example above, the display of “container1” is set to flex instead of inline-flex meaning that it is still acting as a block level flex container – causing “container2” to appear on the next line. In order for “container2” to be inline with “container1”, both containers must have a display of inline-flex as seen below.
If the items within your flex container are too large to display on one line, you can give them wrapping behavior by adding a flex-wrap property and setting it to wrap. If you set the flex-wrap property to nowrap (which is the default), the items will shrink to fit their container as seen below:
Setting the flex-wrap property to wrap will move your items onto a new line if they are too large to fit on the same line in their flex container.
In the example above, the flex-direction is set to row and the flex-wrap is set to wrap. These two properties can actually be set at the same time using the flex-flow shorthand. Below, we see how you can simply set the first value to row, row-reverse, column, or column-reverse and set the second value to wrap or nowrap and it will function just the same!
What if we’d like the items in our container to grow and shrink along with the container instead of bumping to another line? We can do this by applying the following properties to our items:
Before we dive into how these properties are used, let’s take a moment to understand the concept of available space in a css flexbox container.
Let’s say we have a container with a width of 500px and it has four items – each with their own width of 100px. This means that the total width of our items is 400px and the remaining space in the container will be 100px.
When we talk about changing the size of these items or realigning them (which we’ll get to in a moment), we are referring to the way in which this remaining space (100px in our case) is distributed among them. By setting flex-grow, flex-shrink, and/or flex-basis, we are setting how that available space should be handled among the flex-items as the container grows or shrinks.
In our example code, “container1” has its width set to 75% which means, its width will be 75% of its parent element (body in this case).
This property determines the initial size of a flex item within a container. By default, the flex-basis property is set to auto, meaning that if the item already has a specified width and/or height, then the flex-basis will be the same value. Since each element in the example above has height and width set to 100px, the flex-basis property defaults to 100px as well.
If the item’s height and/or width have not been explicitly set, then the flex-basis will be determined by the size of the content within each item. Because we’ve removed the height and width properties in the boxes below, their height will fill their outer container (container1) and their width will shrink to the content within them.
For our purposes in this article, we will explicitly set the height and width of each box to 100px to demonstrate the next properties clearly.
The flex-grow property sets how much of the container’s remaining space the item can take up. In other words, it tells the item: "If there's extra space in the container, grow by this amount."
If the item’s flex-grow property is set to 0, it will not grow to fill the remaining space. In the example below we’ve set the flex-grow property in “box1” to 0. So, it will take up none of the remaining space as “container1” grows.
If all of the item’s flex-grow property is set to 1, they will all grow at the same rate as “container1” expands.
If an item has a larger flex-grow value (say 2) then it will take up twice as much of the remaining space as an item with a flex-grow of 1.
As you might expect, the flex-shrink property is the opposite of the flex-grow property. While flex-grow increases the amount of remaining space each item consumes, flex-shrink sets how space is taken away as the items shrink as the container gets smaller. The items shrink toward their min-content size. This is the minimum space required to fit their content.. Let’s take a look!
In the example below, we can see how setting each item’s flex-shrink property to 1 will result in them taking up the same amount of space as they shrink.
As we see in the example below, changing the flex-shrink property in “box1” to 3 while leaving the rest at 1 results in “box1” shrinking 3X as much.
There’s a shorthand for the flex properties as well! Because of this, you generally won’t see flex-shrink, flex-grow, or flex-basis explicitly written. Instead, these properties can all be set using the flex property in this order – flex-grow, flex-shrink, flex-basis.
There are also some predefined shorthand values for the flex property as well:
We can set the alignment of our items on both the main axis and cross axis. Alignment on the main axis is set by the justify-content property and alignment on the cross axis is set by the align-items property.
The names of these two properties may seem a bit arbitrary and you may be wondering, “why do we have an align-items property for the cross axis and justify-content for the main axis? Shouldn’t it just be align-items and justify-items?” This question comes up a lot.
When it comes to the main axis, think of your items as a single group (content). The space between items within that group can be set with justify-content. In the example below, with flex-direction: row the main axis is horizontal and justify-content will space the items along the main axis in relation to one another.
The cross axis is a bit different. Each item can be spaced freely along the cross axis, independent from the other items as they will never collide or overlap with one another. In the example below, the items can be aligned anywhere on the cross axis.
Now that we understand the difference between align-items and justify-content, let’s look at how we can use these properties to space the items in a css flexbox.
Setting the align-items property allows you to set the position of your items on the cross axis. This property will be set on the container itself – not each individual item. Let’s take a look at the values we can assign to this property.
align-items: stretch - this is the default value for this property. This will cause the items to stretch and fill the cross axis of the container. This means that if items haven’t been given a height or width, they will stretch to fit the entire height (or width if the container is in a column layout) of their flex-container as seen below. If they have been given a height and width (as we’ve given them throughout most of this article) this property won’t do anything.
align-items: flex-start or align-items: start - this will set the items at the start of their cross axis. Since “container1” in example below has a flex-direction of row (which means the main axis is horizontal), setting align-items to start will place the items at the top of the container along the cross (vertical) axis.
align-items: flex-end or align-items: end - You can probably intuit what happens here! This will set the items within “container1” at the end point on its cross (vertical) axis.
align-items: center - This will place the items at the center of the cross axis.
align-items: baseline - This will align items along their baseline which is the line on which their text sits. This is particularly useful when you have items of different sizes as it allows the content within each item to align. You can also set align-items to first baseline (which will align items along their first line of text) or last baseline (which will align items along their last line of text). In the example below, the height of the items has been adjusted to illustrate what setting align-items to last baseline will do.
As we mentioned before, the align-items property is set on the flex-container. If you’d like to adjust the alignment of a specific item, you can set the align-self property on the individual item.
The justify-content property sets how space between items is distributed along the main axis of a container. In the example below,
Let’s take a look at the other possible values justify-content can be set to.
justify-content: flex-end - This will align the content at the end of the main axis.
justify-content: center - This aligns the content at the center of the main axis.
justify-content: space-evenly - This evenly distributes the space between content on the main axis. It places equal space between and around the items.
justify-content: space-between - This will space the content evenly on the main axis without any space at the beginning or end of the container.
justify-content: space-around - This distributes the same amount of space around each item on the main axis, including at the start and end of the container.
Congratulations! You've just leveled up from “CSS makes me cry” to “I can actually center things without Googling it!”. CSS Flexbox is a fantastic tool for arranging items within containers, and now you have an understanding of the basics! Flex-items can be aligned on both a main axis (set by flex-direction) and cross axis, they can shrink or grow along with their container, or wrap if their container shrinks too small. Whether you’re arranging elements within a navigation bar, a form, or even within the entire body of your application, Flexbox makes the process easier. While it won't solve all of life’s problems, it’ll definitely solve your layout problems! And sometimes, that’s enough. Happy flexing!
CSS Flexbox is a powerful layout system for aligning items (CSS elements) within a parent element. For example, by turning a <div> into a flex-container, you can now control how its child elements are spaced on a main and cross axis. Flexbox makes it easy to distribute space, align items, or change their size dynamically as the size of their container changes. This tool is especially useful for navigation bars, buttons, and forms.
Does a bear… yes. Absolutely yes. CSS Flexbox is still the go-to choice for spacing HTML elements in a one dimensional layout type (navigation bars, buttons, forms, etc.) where items need to be placed along a row or column. It’s used when you need agency over the spacing of items within a single container – as opposed to CSS Grid which is used to space items in a two-dimensional layout (an entire page with multiple sections). CSS Flexbox is less nuanced than CSS Grid and excels at simpler, linear designs. It’s a great option when you need precise control over spacing, alignment, and item sizing without the complexity of a full grid system.
Applying flex in CSS is as simple as setting an element’s display property to flex or inline-flex.
Once an element has been turned into a flex- container, its sibling elements can:
flex is a shorthand property for flex-grow, flex-shrink, and flex-basis. Instead of adding each of these properties one-by-one, you can simply use the flex property and assign it three values:
flex: [flex-grow] [flex-shrink] [flex-basis];
Setting flex: 50% is interpreted by most browsers as a shorthand for flex: 1 1 50% which means:
flex-grow: 1 - The item can grow if extra space is available.
flex-shrink: 1 - The item can shrink if necessary.
flex-basis: 50% - The item starts at 50% of the container’s width.
Explore CS Prep further in our beginner-friendly program.
Get more free resources and access to coding events every 2 weeks.
Connect with one of our graduates/recruiters.
Our graduates/recruiters work at:
Alex Stewart is a former professional actor turned software developer and proud Codesmith alumni. Alex works to make technology both fun and accessible through tech talks, video tutorials, and blogs. With hands-on experience in React, Node, SQL databases, and more, Alex brings a deep respect for the development process and is committed to finding new ways to connect with developers and showcase their incredible work in the way it deserves.
Connect with one of our recruiters to learn about their journeys.
Our graduates/recruiters work at: