Have you been using floats, tables or CSS positions to create web page layouts in CSS? That was stressful, difficult and limiting, right😰?
CSS Flexbox has changed the way we create layouts. Flexbox makes it easier to create flexible and dynamic web page layouts.
In this article, I’ll introduce you to this superpower called Flexbox; we’ll explore its properties and explore how you can use it to build responsive website layouts. Let’s dig in!
Prerequisites
Before you begin this tutorial, you’ll need the following:
A Web Browser (preferably Google Chrome)
A text editor (preferably VS Code)
A Basic understanding of HTML and CSS
What is CSS Flexbox?
The CSS Flexbox layout (Flexible Box) is a one-dimensional layout system that makes the task of alignment, layout, and distribution of space between items on a web page easier.
It is a flexible kind of layout because it gives the container (parent element in simple terms) the ability to shrink or grow to fill the available space; that is why we say that Flexbox helps us create responsive layouts.
Before the release of Flexbox, there were other CSS features available for creating layouts, like floats, tables and positioning, which were stressful and couldn’t build all kinds of layouts. Some things that were either impossible or difficult to do are vertical centering, ordering elements, content alignment, and dynamic content scaling, among others, but with the introduction of Flexbox, there is almost. o layout that can’t be built.
To better understand Flexbox, let’s take a look at this example:
• Flex container: Think of the bookshelf as the flex container. It holds all the books (elements) and manages their layout.
• Flex Items: Each book represents a flex item. These individual elements will be arranged within the container (bookshelf).
• Flex Direction: Flex direction determines how the books will be positioned in the container. It can be either horizontal or vertical. For example, if the flex-direction is set to "row," the books will be arranged from left to right.
• Justify Content: Justify content defines how the books are arranged horizontally within the container. It controls the spacing between the books. Using Flexbox in this example, you can easily rearrange and organize the books on the bookshelf, adjust their spacing, and align them as needed.
Similarly, in web development, Flexbox provides a flexible and easy way to arrange and align elements within a container, adapting to different screen sizes and orientations.
Getting Started with Flexbox
To start working with Flexbox, we have to declare the property:
display: flex; /* or inline-flex */
The element of which the display: flex;
is applied is called the flex container (parent element), and the items that are laid out as flexible boxes (the children) are called flex items.
Let’s take an example:
<section class="flex-container"> /* flex container */
<button>Flex Item 1</button> /* flex item */
<button>Flex Item 2</button> /* flex item */
</section>
In the example above, the <section>
element is the flex container and the <button>
elements are the flex items.
Note: The display must be set to flex
to use Flexbox.
There are two axes in Flexbox — the main axis (horizontal) and the cross axis(vertical) and everything we do in Flexbox refers back to these axes.
The main axis
This is the primary axis where flex items are laid out. It is not necessarily horizontal; it is defined by the flex-direction
property, which has four values:
row
(default)row-reverse
column
column-reverse
If the flex-direction
property has the value of row
or row-reverse
, your main axis will run in the inline direction (horizontally).
If the flex-direction
property has the value of column
or column-reverse
, your main axis will run in the block direction (vertically).
Source: MDN Web Docs
The cross axis
This is the axis that is perpendicular to the main axis. Its direction depends on the direction of the main axis.
Therefore, when the flex-direction
(main-axis) has the value of row
or row-reverse
as we've seen in the first image, the cross-axis run in the block direction (vertically) since it is perpendicular (90 degrees) to the main axis.
And when the flex-direction
(main-axis) has the value of column
or column-reverse
, the cross-axis runs in the inline direction (horizontally).
Source: MDN Web Docs
The image below shows the Flexbox architecture (with flex-direction of row).
Source: MDN Web Docs
Flexbox Properties
Flexbox has a lot of properties that help us achieve building great responsive layouts; we’ll group these properties into two:
Properties for the flex container (parent)
Properties for the flex items (children)
Properties for the flex container
flex-direction
: This property defines the direction of the main axis where flex items are laid out..container { flex-direction: row | row-reverse | column | column-reverse; }
row
(default): The flex items are displayed from left to right.row-reverse
: The flex items are displayed from right to left.column
: The flex items are displayed from top to bottom.column-reverse
: The flex items are displayed from bottom to top.
Source: Pinterest
flex-wrap
: By default, flex items will try to fit in one line; when they can’t, they overflow, breaking the container. Theflex-wrap
property allows us to change that and allow the items to wrap when they can’t fit..container { flex-wrap: nowrap | wrap | wrap-reverse; }
nowrap
(default): Flex items will be on the same line, even if they don’t fit.wrap
: Flex items will wrap (move) into multiple lines.wrap-reverse
: Flex items will wrap into multiple lines from bottom to top.
Source: Pinterest
justify-content
: This property is used to align items on the main axis, the direction in which theflex-direction
has set the flow..container { justify-content: flex-start | flex-end | start | end | left | right | center | space-between | space-around | space-evenly; }
flex-start
(default): Flex items are packed towards the start of the flex-direction.flex-end
: Flex items are packed towards the end of the flex-direction.center
: Flex items will be centered along the line.space-between
: Flex items are evenly distributed in the line, where the first item is at the main start and the last item is at the main end.space-around
: Flex items are evenly distributed in line with equal space around them.space-evenly
: Flex items are distributed so that the spacing between any two items (and the space to the main edges (main-start and main-end) is equal.NOTE: These are the most used justify-content property values.
Source: Pinterest
align-items
: This property is used to align items on the cross axis. Think of it as the opposite of justify-content (but on the cross axis)..container { align-items: stretch | flex-start | flex-end | center | baseline; /* there are other values, but these are the most used */ }
stretch
(default): Flex items stretch to the height of the flex container. This is guided by the height of the container as well.flex-start
(default): Flex items are placed at the start of the cross axis.flex-end
: Flex items are placed at the end of the cross axiscenter
: Flex items will be centered on the cross axis.space-between
: Flex items are aligned according to their baselines.
Source: Google
flex-direction
is set to column
, there will be a switch of roles between justify-content
and align-items
i.e. the main axis changes to vertical so when we make a declaration like this: justify-content: center;
, instead of centering the children horizontally, it centers them vertically.align-content
: This property is used to align flex items on the cross axis.
```css
.container {
/ align-content won't work without this line /
flex-wrap: wrap;
align-items: flex-start | flex-end | center | stretch | space-between | space-around | space-eve;
/ there are other values, but these are the most used /
}
```
normal
(default): flex items are packed in their default position.
flex-start
: Flex items are packed to the start of the container.
flex-end
: Flex items are packed to the end of the container.
center
: Flex items are centered in the container.
stretch
: flex items stretch to take up all the space on the cross axis.
space-between
: Flex items are evenly distributed, just like justify-content where the first line is at the cross-start, and the last item is at the cross-end.
space-around
: Flex items are evenly distributed with equal space around each line.
Source: Google
---
### Properties for the flex items
flex-grow
: This property determines if the size of a flex item should grow depending on the width of the flex container. If all flex items have flex-grow: 1;
, the remaining space in the container will be shared equally with the other flex items. If it has flex-grow
set to 2, it will take up twice as much space as the other children.
```css
.item {
flex-grow: 2; / this means "grow twice your size" /
}
```
0
(default): This means that all the children will occupy equal space in the container.
NOTE: Negative numbers are invalid.
flex-shrink
: This property determines the ability of a flex item to shrink.
```css
.item {
flex-shrink: 3; / this means "shrink" /
}
```
1
(default): This means “don’t shrink."
Negative numbers are invalid.
For this to work, you have to disable the flex-wrap
property first
Source: Freecodecamp
order
: Flex items are laid out by default in the order in which they were written in an HTML document; the order property gives us control of that order. i.e. making the first child appear last etc.
```css
.item {
order: 5; / this means that the targeted child will become the fifth element /
}
```
0
(default): This means “remain where you are”.
-1
will be positioned before another child with an order of 1
![](css-tricks.com/wp-content/uploads/2018/10/o.. align="center")
Source: CSS Tricks
flex-basis
: This is the size of the element before the remaining space is distributed i.e. this means “before the other children share the parent’s space, this is the size I’m taking.”.item { flex-basis: (length) | auto; }
0
: If its value is set to 0, the space it takes is calculated based on itsflex-grow
value.The default is
auto
.
align-self
: This property, when set on an individual flex-item, allows that flex-item to override existingalign-items
rules.item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }
Flexbox in Practice
Flexbox Shorthands
Wait!… before we put our new superpowers to practice, why don’t we give it some spice by learning about Flexbox shorthands 😁?
According to Google, shorthands are a short and simple way of expressing or referring to something. In other words, they help us do things easier, thereby saving us time. The same applies to Flexbox shorthands.
Note: These are not compulsory to know; you’ll get the hang of it as you practice.
flex
: This property is the shorthand forflex-grow
,flex-shrink
andflex-basis
(in that order). Let’s see how it works./* This means flex-grow is 5, flex-shrink is 1, and flex-basis is 50% */ .child { flex: 5 1 50%; /* default is 0 1 auto */ }
💡This only works on flex items (children) • The second and third parameters (flex-shrink
andflex-basis
) are optional. • If you see this property with one value (flex: 2;
), the value is forflex-grow
, i.e. it sets the other parameters to their default values.flex-flow
: This property is the shorthand forflex-direction
andflex-wrap
(in that order)..parent { flex-flow: row wrap; /* This means flex-direction is row and flex-wrap is wrap */ /* default is row nowrap */ }
💡This only works on flex-containers (parent)place-content
: This property is the shorthand foralign-content
andjustify-content
(in that order)..parent { place-content: center flex-end; /* This means flex-direction is row and flex-wrap is wrap */ /* default is row nowrap */ }
💡This only works on flex-containers (parent).
Now that we’re fully equipped, why don’t we put it into practice?
Building Projects
The first thing we’re going to do is vertical and horizontal centering, this is something that a lot of people struggle with. A real-life example of this can be seen in the vertical alignment of content within a pricing table, which is what we'll be building. We’ll be solving that problem with our new superpower, Flexbox!
Let’s set up our project:
Create a folder anywhere you like on your PC and give it the name “flexbox-centering” (it can have any name)
Open your text editor; I’ll guide you with VS Code
Click
Ctrl/Cmd
+O
or head over to File at the upper-left corner and click on "Open Folder " to open the folder you just createdCreate a new file in VSCode, name it
index.html
, create a second file and name itstyle.css.
Go to your browser and click
Ctrl/Cmd
+O
or click on the index.html file from your folder to open it with your browserYou can also skip the above steps, open Codepen and start coding.
Adding the content with HTML
<div class="pricing-table">
<!-- the first card -->
<div class="pricing-card">
<h2>Basic</h2>
<p>$9.99/month</p>
<p>10GB Storage</p>
<p>1 User</p>
<a href="#" class="btn">Choose Plan</a>
</div>
<!-- the second card -->
<div class="pricing-card">
<h2>Pro</h2>
<p>$19.99/month</p>
<p>25GB Storage</p>
<p>3 Users</p>
<a href="#" class="btn">Choose Plan</a>
</div>
<!-- the third card -->
<div class="pricing-card">
<h2>Premium</h2>
<p>$39.99/month</p>
<p>50GB Storage</p>
<p>10 Users</p>
<a href="#" class="btn">Choose Plan</a>
</div>
</div>
From the above code, the div
with the class of pricing-table
represents the container for the pricing cards. The div
with the class of pricing-card
represents each pricing card.
This is the result:
Styling the Pricing Table with CSS
Let's style this project with CSS because it looks ugly 😂
/* importing an external font from google fonts */
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;500;700;900&display=swap");
/* styling the cards */
.pricing-card {
/* some basic styles */
background-color: tomato;
color: #fff;
font-family: "Roboto", sans-serif;
margin: 20px;
height: 300px;
width: 200px;
border-radius: 9px;
text-align: center;
padding-bottom: 10px;
}
/* some styles to make it the cards look beautiful */
.pricing-card h2 {
font-weight: 900;
padding: 20px;
border: 4px solid #000;
background: #fff;
color: #000;
}
.pricing-card p {
font-weight: 300;
border-bottom: 1px solid #000;
padding-bottom: 12px;
}
.btn {
display: inline-block;
background: #000;
color: #fff;
text-decoration: none;
padding: 8px 12px;
border-radius: 4px;
}
From the CSS code above, we have designed the cards by giving them colour etc. But as we can see, the cards are stacked up on each other and we're trying to align them vertically and horizontally in the container. This is where Flexbox comes in, we will use Flexbox to do just that.
/* adding flexbox properties to the parent element */
.pricing-table {
display: flex;
/* centering them horizontally and vertically */
justify-content: center; /* horizontal centring */
align-items: center; /* vertical centring */
}
That's it! Easy right?
To notice the change, let's give the container (pricing-table
) a large width and height and a border.
.pricing-table {
width: 50em;
height: 50em;
border: 2px solid black;
}
As we can see below; the cards are perfectly centered in their container.
And that's how we center items vertically and horizontally in their container easily using Flexbox!
Building a Navigation Menu with Flexbox
The next project we'll build is a responsive navigation menu. Use the steps above to set up your project. I'll be using codepen for this project.
Adding content with HTML
<!-- Container for the navigation menu -->
<div class="nav-container">
<!-- Unordered list for the menu items -->
<ul class="nav-menu">
<li class="nav-item">
<a href="#" class="nav-link">Home</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">About</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Services</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Contact</a>
</li>
</ul>
</div>
This is the result of the above HTML code:
Let's style it with CSS.
Styling the Navigation Menu with CSS
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
The above CSS rule sets some basic styles for the entire page. It removes any default margin and padding on the body
element and specifies the font family as Arial or a similar sans-serif font.
.nav-container {
background-color: #333;
padding: 20px;
}
The .nav-container
class represents the container for the navigation menu. This rule sets the background colour of the container to a dark grayish color (#333) and adds 20 pixels of padding to create spacing around the menu.
.nav-menu {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
The .nav-menu
class represents the flex container for the menu items. This rule enables Flexbox by setting the display
property to flex
. It uses justify-content: space-between;
to evenly distribute the menu items along the main axis, with the first item aligned to the start and the last item aligned to the end. The align-items: center
property vertically centers the menu items along the cross axis. The flex-wrap: wrap
property allows the items to wrap onto multiple lines if necessary.
.nav-item {
list-style: none;
margin: 10px;
order: 1;
}
The .nav-item
class represents each menu item. This rule removes the default list-style (bullet point) on list items using list-style: none;
. It adds 10 pixels of margin around each item to create spacing between them. The order: 1
property specifies the initial order of the items, ensuring they maintain their natural order.
.nav-link {
text-decoration: none;
color: #fff;
padding: 8px 12px;
border-radius: 4px;
background-color: #666;
flex-grow: 1;
flex-shrink: 1;
}
The .nav-link
class represents the links within each menu item. This rule removes the default underline decoration on the links using text-decoration: none
. It sets the text color to white (#fff
) and adds 8 pixels of padding on the top and bottom and 12 pixels of padding on the left and right. The border-radius: 4px
property creates rounded corners for the links, and the background-color: #666
sets the background color to a dark grayish color.
The flex-grow: 1
and flex-shrink: 1
properties allow the links to grow and shrink as needed, ensuring they occupy the available space within the menu container.
.nav-item:nth-child(1) {
order: 2;
}
.nav-item:nth-child(2) {
order: 3;
}
.nav-item:nth-child(3) {
order: 1;
}
.nav-item:nth-child(4) {
order: 4;
}
These CSS rules target specific menu items using the :nth-child()
pseudo-class selector. They adjust the order
property to change the positioning of the menu items. In this example, the first item (:nth-child(1)
) is given an order
value of 2
, the second item (:nth-child(2)
) has an order
value of 3
, the third item (:nth-child(3)
) has an order
value of 1
This is the result:
Looking good right?
But there's a problem. When we resize the window, it isn't responsive though it behaves like it is, due to the flex-wrap
property we applied on the flex-items. So, let's fix that with CSS media queries. You can learn more about it here
Making the Navigation Menu Responsive
@media screen and (max-width: 600px) {
.nav-menu {
justify-content: center;
}
.nav-item:nth-child(1) {
order: 1;
}
.nav-item:nth-child(2) {
order: 2;
}
.nav-item:nth-child(3) {
order: 3;
}
.nav-item:nth-child(4) {
order: 4;
}
}
The media query above is used to apply specific CSS styles when the screen width is equal to or less than 600 pixels. It allows for responsive design by adapting the navigation menu layout on smaller screens.
Inside the media query, the .nav-menu
class is targeted, and the justify-content
property is set to center
. This centers the menu items horizontally within the container on smaller screens, overriding the previous justify-content: space-between
property.
The subsequent rules target each .nav-item
class using the :nth-child()
pseudo-class selector. These rules modify the order
property for each item, ensuring they maintain the desired order within the centered menu layout.
This is the result:
Conclusion
In conclusion, CSS Flexbox offers a versatile and efficient way to design flexible and responsive layouts. However, it's important to remember that you don't have to be an expert in every aspect of Flexbox or web development in general. The true mark of a skilled developer lies in their ability to research.
The journey of a developer is filled with continuous learning and exploration. When you encounter challenges or can't recall a specific Flexbox property or technique, don't be discouraged. Instead, embrace the opportunity to dive into the vast resources available to you. Whether it's reading documentation, watching tutorials, or joining developer communities, the ability to seek and find answers is an invaluable skill.
As Steve Jobs once said, "Stay hungry, stay foolish." Keep your curiosity alive and never stop learning. Embrace the joy of discovery and the satisfaction of finding solutions through research. With consistent practice, you will become more proficient not only in Flexbox but also in your overall development journey.
So, let go of the pressure to know everything and focus on developing your ability to research effectively. Trust in the process, and remember that even the most experienced developers rely on research to solve problems. As you continue to practice and grow, you'll gain confidence in your skills and find yourself overcoming obstacles with ease.
In the end, it's not about memorizing every detail; it's about cultivating a mindset of continuous improvement and resourcefulness. Embrace the quote by Confucius: "It does not matter how slowly you go as long as you do not stop." Keep researching, keep learning, and enjoy the ever-evolving journey of becoming a skilled and knowledgeable developer.