Skip to content

Flexbox Layout: The Modern Solution Revolutionizing CSS Layout ​

Imagine you are organizing a bookshelf. If you use traditional methods, you need to precisely measure the width of each book, calculate the spacing, and also consider the total width of the bookshelf to ensure the books fit just right. If you add or remove a book, you might need to readjust the position of all the books. This process is tedious and error-prone.

Now, imagine there is a smart bookshelf. You just need to put the books on it, and it automatically adjusts the spacing of each book so that they perfectly fill the entire bookshelf. When you add a new book, the other books automatically rearrange; when you take a book away, the remaining books automatically fill the gap. This is the revolutionary change that Flexbox brings to CSS layout.

The Painful History of Layout ​

Before Flexbox appeared, CSS layout mainly relied on tools like float, position, and inline-block, which were not designed specifically for layout. Let's look back at those traditional layout methods that gave developers headaches.

The Dilemma of Float Layout ​

Float was originally designed to achieve the effect of text wrapping around images, but developers had to use it for page layout. It's like using a screwdriver as a hammer; although it can get the job done, it always feels a bit off.

css
/* Traditional float layout */
.sidebar {
  float: left;
  width: 250px;
}

.main-content {
  float: left;
  width: calc(100% - 250px); /* Need to manually calculate width */
}

.container::after {
  content: "";
  display: table;
  clear: both; /* Must clear floats, otherwise the container will collapse */
}

The problems with this method are obvious: you need to manually calculate widths, you must clear floats to prevent container collapse, and achieving equal-height columns is almost an impossible task. If you want the sidebar and main content area to have the same height, you need to rely on JavaScript or use various hacky techniques.

The Limitations of Position Layout ​

Using absolute positioning can also achieve layout, but it completely removes elements from the document flow, causing other elements to be unaware of its existence.

css
/* Layout using position */
.container {
  position: relative;
  height: 500px; /* Must set a fixed height */
}

.sidebar {
  position: absolute;
  left: 0;
  top: 0;
  width: 250px;
  height: 100%;
}

.main-content {
  position: absolute;
  left: 250px; /* Need to know the exact width of the sidebar */
  right: 0;
  top: 0;
  height: 100%;
}

This method requires you to know the dimensions of all elements, and the container must have a fixed height. If the content is dynamic, this solution becomes very fragile.

The Awkwardness of Inline-Block ​

Inline-block looks promising, allowing elements to be arranged in a line while still being able to set width and height. But it has a notorious problem: inexplicable whitespace gaps appear between elements.

css
/* inline-block layout */
.item {
  display: inline-block;
  width: 30%;
  vertical-align: top;
}
html
<!-- Line breaks in HTML create whitespace -->
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>

A gap of about 4px will appear between these elements. You need to use various strange hack methods to eliminate it, such as setting the parent element's font-size to 0, or writing the HTML in a single line. These methods make the code difficult to maintain.

The Nightmare of Vertical Centering ​

Before Flexbox, achieving vertical centering was one of the most headache-inducing problems in CSS. There was no simple and intuitive way; you had to use different techniques depending on the situation.

css
/* Method 1: Using absolute positioning + transform */
.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Method 2: Using table-cell */
.container {
  display: table;
  width: 100%;
  height: 400px;
}

.centered {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

/* Method 3: Using line-height (only suitable for single-line text) */
.centered {
  line-height: 400px;
  height: 400px;
}

Each method has strict limiting conditions, and the code is not intuitive. That's why in 2009, the CSS Working Group began designing a new module specifically for layout—Flexbox.

Design Philosophy of Flexbox ​

The full name of Flexbox is Flexible Box Layout Module. Its design philosophy can be summarized in three words: Flexible, Intelligent, Intuitive.

One-Dimensional Layout Model ​

The first thing to understand is that Flexbox is a one-dimensional layout model. What does "one-dimensional" mean here? It means that Flexbox mainly handles layout in a single direction (either a horizontal row or a vertical column).

Imagine you are queuing for coffee. The line might be long, but it is one-dimensional—everyone is on a single line. You can be queuing horizontally (horizontal direction) or vertically (vertical direction), but in any case, it is a one-dimensional arrangement.

This is different from the later Grid layout. Grid is a two-dimensional layout, handling both rows and columns simultaneously, like a chessboard. Flexbox focuses on one direction at a time, but it provides great flexibility in that direction.

Relationship Between Container and Items ​

Flexbox is built on a simple hierarchical relationship: there is a container (flex container), and inside the container are several items (flex items).

html
<div class="container">
  <!-- This is the flex container -->
  <div class="item">Item 1</div>
  <!-- These are flex items -->
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
</div>
css
.container {
  display: flex; /* Turn this element into a flex container */
}

Once you set display: flex on an element, its direct children automatically become flex items. Note that the emphasis here is on direct children. Grandchildren elements will not be affected unless you also set their parent element as a flex container.

This design is very smart: the container is responsible for defining the overall arrangement rules, while the items can adjust themselves according to their needs. The container says, "I'll set the general direction for you," and the items say, "Within this general direction, I can have my own personality."

Intelligence of Space Distribution ​

The most powerful feature of Flexbox is its intelligent distribution of space. When the container has extra space, flex items can automatically expand to fill that space; when the container space is insufficient, flex items can shrink proportionally.

Let's look at a simple example:

html
<div class="container">
  <div class="item">Home</div>
  <div class="item">Products</div>
  <div class="item">About Us</div>
</div>
css
.container {
  display: flex;
  width: 600px;
  background-color: #f5f5f5;
}

.item {
  flex: 1; /* This is key: each item shares space equally */
  padding: 20px;
  background-color: #2196f3;
  color: white;
  text-align: center;
  margin: 10px;
}

In this example, the container width is 600px. The three items will automatically divide this space equally, with each item occupying about 200px (minus margin and padding). If the container width becomes 900px, each item will automatically expand to 300px. If the container width shrinks to 300px, each item will automatically shrink to 100px.

This ability to automatically adjust is the true meaning of the word "Flexible". You don't need to write JavaScript to calculate widths, and you don't need to use media queries to cope with different screen sizes; Flexbox handles it all automatically.

Core Concepts of Flexbox ​

To truly master Flexbox, you need to understand a few core concepts. These concepts are like the "grammar" of Flexbox; once you understand them, you can write fluent "sentences" with it.

Main Axis and Cross Axis ​

This is the most important concept in Flexbox. Every flex container has two axes:

  • Main Axis: The direction in which flex items are arranged
  • Cross Axis: The direction perpendicular to the main axis

By default, the main axis is horizontal (from left to right), and the cross axis is vertical (from top to bottom). But you can change the direction of the main axis using the flex-direction property.

css
.container {
  display: flex;
  flex-direction: row; /* Default value: main axis is horizontal */
}

When the main axis is horizontal:

  • Items are arranged from left to right
  • The main axis start is on the left, and the end is on the right
  • The cross axis is vertical, starting at the top and ending at the bottom

If we change the main axis direction:

css
.container {
  display: flex;
  flex-direction: column; /* Main axis becomes vertical */
}

Now the main axis is vertical:

  • Items are arranged from top to bottom
  • The main axis start is at the top, and the end is at the bottom
  • The cross axis becomes horizontal, starting on the left and ending on the right

Understanding these two axes is very important because many Flexbox properties work based on them. For example, justify-content controls alignment along the main axis, while align-items controls alignment along the cross axis.

Default Behavior of Flex Containers ​

When you set display: flex on an element, the following things happen:

  1. Items line up in a row: All direct children will be arranged in a row along the main axis (if the main axis is horizontal) or a column (if the main axis is vertical).

  2. Items start from the main axis start: By default, items start arranging from the left side of the container (horizontal main axis) or the top side (vertical main axis).

  3. Items do not wrap automatically: Even if there isn't enough space in the container, items will squeeze into one line and might overflow the container.

  4. Items stretch along the cross axis: By default, all items will stretch to the height of the container along the cross axis.

Let's look at an example to understand these default behaviors:

html
<div class="container">
  <div class="item item-1">Short</div>
  <div class="item item-2">Medium Length</div>
  <div class="item item-3">This is a very long text content</div>
</div>
css
.container {
  display: flex;
  width: 500px;
  height: 200px;
  background-color: #f5f5f5;
  border: 2px solid #333;
}

.item {
  background-color: #2196f3;
  color: white;
  padding: 10px;
  margin: 5px;
}

You will see:

  • Three items arranged horizontally in a row
  • They start arranging from the left
  • Even if the text of the third item is very long, it will not wrap to the next line (it might cause the container to overflow)
  • The height of all items will stretch to 200px (the height of the container), even if the first item only has the word "Short".

These default behaviors can all be changed through various Flexbox properties, which is also where Flexbox's power lies—it provides great flexibility and control.

Your First Flexbox Layout ​

Let's feel the power of Flexbox through a practical example. We are going to create a simple navigation bar, which requires a lot of tricks in traditional methods but is very simple in Flexbox.

Requirement Description ​

We want to create a navigation bar that requires:

  • A Logo on the left
  • Several navigation links on the right
  • The Logo and navigation links are at opposite ends
  • Equal spacing between navigation links
  • The entire navigation bar works properly on different screen widths

Implementation with Traditional Method ​

Using the traditional float method, the code would look like this:

css
/* Traditional method: using float */
.nav-traditional {
  overflow: hidden; /* Clear floats */
  background-color: #333;
  padding: 10px;
}

.logo {
  float: left;
  color: white;
  font-size: 20px;
}

.nav-links {
  float: right;
}

.nav-link {
  float: left;
  color: white;
  padding: 10px 15px;
  text-decoration: none;
}

This method works, but has several problems:

  • Need to clear floats
  • If you want to adjust spacing, you need to modify multiple places
  • Vertical centering is difficult
  • Code is not intuitive

Implementation with Flexbox Method ​

Now let's use Flexbox to achieve the same effect:

html
<nav class="navbar">
  <div class="logo">TechCorp</div>
  <div class="nav-links">
    <a href="#" class="nav-link">Home</a>
    <a href="#" class="nav-link">Products</a>
    <a href="#" class="nav-link">About</a>
    <a href="#" class="nav-link">Contact</a>
  </div>
</nav>
css
.navbar {
  display: flex; /* Enable Flexbox */
  justify-content: space-between; /* Logo and navigation links at opposite ends */
  align-items: center; /* Vertically centered alignment */
  background-color: #333;
  padding: 15px 30px;
}

.logo {
  color: white;
  font-size: 24px;
  font-weight: bold;
}

.nav-links {
  display: flex; /* Navigation links container also uses Flexbox */
  gap: 20px; /* Spacing between links, just that simple! */
}

.nav-link {
  color: white;
  text-decoration: none;
  padding: 8px 15px;
  border-radius: 4px;
  transition: background-color 0.3s;
}

.nav-link:hover {
  background-color: #555;
}

See the difference? Flexbox code is shorter, clearer, and easier to maintain:

  • justify-content: space-between automatically places the Logo and navigation links at opposite ends
  • align-items: center easily achieves vertical centering
  • gap: 20px concisely defines the spacing between items
  • No need for float, no need to clear floats, no need to calculate positions

Making the Navigation Bar Smarter ​

The real power of Flexbox lies in responsive design. Suppose we want the navigation links to wrap on small screens; with Flexbox, it only takes one line of code:

css
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap; /* Allow wrapping */
  background-color: #333;
  padding: 15px 30px;
}

/* On small screens, let navigation links occupy the full row */
@media (max-width: 768px) {
  .nav-links {
    flex-basis: 100%; /* Occupy full row */
    justify-content: center; /* Center display */
    margin-top: 15px;
  }
}

On screens narrower than 768px, the navigation links will automatically wrap to the second line and be centered. This flexibility is hard to achieve with traditional layout methods.

Practical Application Scenarios ​

Flexbox is not just for navigation bars; it can show its skills in many scenarios. Let's look at a few common application scenarios.

Equal Height Card Layout ​

In traditional CSS, achieving equal-height card layouts has always been a difficult problem. But Flexbox makes this very simple.

html
<div class="card-container">
  <div class="card">
    <h3>Basic Plan</h3>
    <p>Perfect for individuals</p>
    <ul>
      <li>5 Projects</li>
      <li>2GB Storage</li>
    </ul>
    <button>Choose Plan</button>
  </div>
  <div class="card">
    <h3>Pro Plan</h3>
    <p>Best for professionals</p>
    <ul>
      <li>Unlimited Projects</li>
      <li>50GB Storage</li>
      <li>Priority Support</li>
      <li>Advanced Analytics</li>
    </ul>
    <button>Choose Plan</button>
  </div>
  <div class="card">
    <h3>Enterprise</h3>
    <p>For large teams</p>
    <ul>
      <li>Unlimited Everything</li>
      <li>500GB Storage</li>
      <li>24/7 Support</li>
    </ul>
    <button>Choose Plan</button>
  </div>
</div>
css
.card-container {
  display: flex;
  gap: 20px;
  padding: 20px;
}

.card {
  flex: 1; /* Each card shares space equally */
  display: flex; /* The card itself also uses Flexbox */
  flex-direction: column; /* Arrange content vertically */
  padding: 30px;
  background-color: white;
  border: 1px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.card h3 {
  margin-top: 0;
  color: #333;
}

.card ul {
  flex-grow: 1; /* Let the list occupy all remaining space */
  padding-left: 20px;
}

.card button {
  margin-top: 20px; /* Button always at the bottom */
  padding: 12px 24px;
  background-color: #2196f3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

In this example, even if the content length of the three cards is different, their height will remain consistent. And the button is always at the bottom of the card, which is difficult to achieve in traditional layouts.

Perfect Centering ​

Remember the nightmare of vertical centering we mentioned earlier? Flexbox makes this one of the simplest things.

css
.center-container {
  display: flex;
  justify-content: center; /* Horizontal centering */
  align-items: center; /* Vertical centering */
  height: 400px;
  background-color: #f5f5f5;
}

.centered-content {
  text-align: center;
  padding: 40px;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

With just these two core lines of code, the content will be perfectly centered in the container, regardless of how the container's dimensions change.

Holy Grail Layout ​

The Holy Grail layout is a classic three-column layout: fixed-width left and right sidebars, and a flexible middle content area. Before Flexbox, this layout required complex techniques.

html
<div class="holy-grail">
  <header>Header</header>
  <div class="content-wrapper">
    <nav class="sidebar-left">Left Sidebar</nav>
    <main class="main-content">Main Content</main>
    <aside class="sidebar-right">Right Sidebar</aside>
  </div>
  <footer>Footer</footer>
</div>
css
.holy-grail {
  display: flex;
  flex-direction: column; /* Vertically arrange header, content, footer */
  min-height: 100vh;
}

header,
footer {
  background-color: #333;
  color: white;
  padding: 20px;
  text-align: center;
}

.content-wrapper {
  display: flex; /* Horizontally arrange three columns */
  flex: 1; /* Occupy all remaining space */
}

.sidebar-left,
.sidebar-right {
  flex: 0 0 200px; /* Fixed width 200px, no stretching */
  background-color: #e3f2fd;
  padding: 20px;
}

.main-content {
  flex: 1; /* Occupy all remaining space */
  background-color: white;
  padding: 20px;
}

This layout automatically adapts to different screen heights, the footer is always at the bottom of the page, and the middle content area automatically expands to fill the remaining space.

Browser Support ​

Flexbox has excellent browser support. First proposed in 2009, after years of development and refinement, modern browsers fully support Flexbox.

Support status of major browsers:

  • Chrome 29+ (Released in 2013)
  • Firefox 28+ (Released in 2014)
  • Safari 9+ (Released in 2015)
  • Edge 12+ (Released in 2015)
  • iOS Safari 9+ (Released in 2015)
  • Android Browser 4.4+ (Released in 2013)

If your project needs to support very old browsers (like IE 10), you need to pay attention to some compatibility issues. But for the vast majority of modern projects, you can use Flexbox with confidence without any polyfills or fallback solutions.

It is worth noting that early versions of Flexbox had slightly different syntax. If you see code like display: -webkit-box or display: -ms-flexbox, that is the syntax of the old version. Now we use the standard syntax display: flex, without adding browser prefixes.

Usage Recommendations ​

Although Flexbox is very powerful, it doesn't mean it's suitable for all scenarios. Here are some usage recommendations.

When to Use Flexbox ​

Flexbox is best suited for the following scenarios:

  1. One-dimensional layout: When you need to arrange elements in one direction (row or column)
  2. Unknown content size: When the size of elements is dynamic or unknown
  3. Need flexible space distribution: When you want elements to automatically resize based on available space
  4. Small-scale layout: Navigation bars, toolbars, internal layout of cards, etc.
  5. Alignment and spacing control: When you need precise control over the alignment and spacing of elements

When Not to Use Flexbox ​

In the following cases, you might want to consider other solutions:

  1. Complex two-dimensional layout: If you need to control both rows and columns simultaneously, Grid layout might be more appropriate
  2. Overall page structure: For complex page layouts, Grid is usually a better choice
  3. Need to support IE 9 and below: If you must support IE 9, you might need to use traditional layout methods

Flexbox vs Grid ​

Many people ask: Should I use Flexbox or Grid? The answer is: Use both. They are not in competition, but complementary.

Simple rules of thumb:

  • If your layout is one-dimensional (a row or a column), use Flexbox
  • If your layout is two-dimensional (needs to control both rows and columns simultaneously), use Grid
  • In a page, you can use both at the same time: use Grid to build the overall layout, and use Flexbox to handle the interior of components

Summary ​

Flexbox is a revolution in CSS layout. It solves many pain points of traditional layout methods, providing an intuitive, flexible, and powerful layout solution.

Core Advantages of Flexbox:

  1. Simple and Intuitive: Achieve complex layout effects with just a few lines of code
  2. Flexible Response: Elements automatically adjust according to available space
  3. Easy Alignment: Vertical centering and spacing control become very simple
  4. High Maintainability: Code is shorter, clearer, and easier to understand

Review of Core Concepts:

  • Flexbox is a one-dimensional layout model, mainly handling arrangement in a single direction
  • Relationship between container and items: Container defines rules, items can be personalized
  • Main axis and cross axis: Understanding these two axes is the key to mastering Flexbox
  • Intelligent space distribution: Elements can automatically expand or shrink to adapt to available space

In the following chapters, we will delve into the various properties of Flex containers, Flex items, and how to apply Flexbox in actual projects. Master Flexbox, and you will have a powerful layout tool that makes web layout elegant and simple.