Mastering CSS: Simplify Layouts with Flexbox Magic

Sagnik GuruSagnik Guru
14 min read

What Is a Flexbox and Why Do You Need It?

If you've ever struggled to align items on a web page—whether it's centering a button or creating a responsive layout—you’re not alone. Enter Flexbox, one of CSS's most powerful and intuitive layout systems. But what exactly is a Flexbox, and why has it become a must-have skill for modern web developers?

Flexbox, short for Flexible Box Layout, is a CSS3 layout model that allows you to design complex layouts easily. It is especially useful for distributing space and aligning items in a container, even when their size is unknown or dynamic.

With Flexbox, you can:

  • Align items horizontally or vertically

  • Distribute space evenly between elements

  • Automatically adjust item sizes to fit the container

  • Handle both small-scale and large-scale layout challenges

It was specifically designed to fix the limitations of older layout methods like floats and inline-block, offering greater flexibility and cleaner code.

Every HTML element that holds any type of content can be a flexbox

At its core, Flexbox consists of a flex container and flex items.

.container {
  display: flex;
}

How to Center a Div ?

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

🧭 Main Axis vs. Cross Axis: The Backbone of Flexbox

To truly harness the power of Flexbox, you need to understand two foundational concepts: the main axis and the cross-axis. These axes determine how items are laid out and aligned inside a flex container.


Get started with Flexbox. - DEV Community

What Is the Main Axis?

The main axis is the primary direction in which Flexbox lays out items.

  • By default, this is horizontal, left to right.

  • You control it using the flex-direction property.

Flexbox uses the main-axis to align items with properties like justify-content

.container {
  display: flex;
  flex-direction: row; /* horizontal (default) */
  justify-content: center;
}

What Is the Cross Axis?

The cross axis runs perpendicular to the main axis.

  • If the main axis is horizontal (row), the cross axis is vertical.

  • If the main axis is vertical (column), the cross axis is horizontal.

Flexbox uses the cross-axis to align items with properties like align-items .

.container {
  display: flex;
  flex-direction: row;
  align-items: center; /* aligns items along the cross axis (vertical here) */
}

So if you're ever wondering why your items aren’t aligning the way you expect, check the axis you're working on!

🎯 Justify Content vs. Align Items: Flexbox Alignment Made Easy

Two of the most powerful tools in your Flexbox toolkit are justify-content and align-items. They control how your flex items are positioned along the main axis and cross axis, respectively.


🔹 justify-content: Aligning Along the Main Axis

justify-content controls how items are distributed along the main axis (which is horizontal by default, unless flex-direction is changed).

.container {
  display: flex;
  justify-content: center;
}
✅ All values of justify-content:
ValueDescription
flex-startItems align to the start of the main axis (default).
flex-endItems align to the end of the main axis.
centerItems are centered along the main axis.
space-betweenItems are spaced evenly; first item at start, last at end.
space-aroundItems are spaced evenly with equal space around them.
space-evenlyItems are spaced so the space between all items (and edges) is equal.
start / endLogical alignments (based on writing direction; less commonly used).
left / rightAlign items to the left or right (in horizontal layouts).

🔸 align-items: Aligning Along the Cross Axis

align-items determines how items are aligned vertically by default, because it works along the cross axis.

.container {
  display: flex;
  align-items: center;
}
✅ All values of align-items:
ValueDescription
stretchItems stretch to fill the container (default).
flex-startItems align to the start of the cross axis.
flex-endItems align to the end of the cross axis.
centerItems are centered along the cross-axis.
baselineItems align based on their text baseline. Useful for text-heavy content.

🔧 Flex Direction, Gap, and Flex Wrap: Control Your Layout Flow

Flexbox isn’t just about alignment—it’s also about controlling the direction, spacing, and wrapping behavior of your items. These three properties give you precise control over how your layout behaves, especially in responsive designs.


🔄 flex-direction: Set the Flow of Items

The flex-direction property defines the direction of the main axis, which determines how flex items are laid out and this also influences how other flexbox property behave.

.container {
  display: flex;
  flex-direction: row; /* default */
}
✅ Available values:
ValueDescription
rowHorizontal, left to right (default)
row-reverseHorizontal, right to left
columnVertical, top to bottom
column-reverseVertical, bottom to top

💡 Use column for stacking items vertically, great for mobile layouts.


📏 gap: Space Between Items, Made Easy

The gap property defines the space between flex items—without needing to mess with margins on each item.

.container {
  display: flex;
  gap: 16px;
}
🧩 You can also use:
  • row-gap: space between items along the main axis

  • column-gap: space along the cross axis

.container {
  display: flex;
  row-gap: 20px;
  column-gap: 10px;
}

✅ Works with Flexbox and CSS Grid — no more last-child margin hacks!


🔁 flex-wrap: Let Items Wrap When Needed

By default, Flexbox tries to fit all items on one line. If they overflow, they’ll just shrink. flex-wrap allows items to wrap onto multiple lines if necessary.

.container {
  display: flex;
  flex-wrap: wrap;
}
✅ Values:
ValueDescription
nowrapAll items stay in one line (default).
wrapItems wrap to the next line, from top to bottom.
wrap-reverseItems wrap in reverse order, from bottom to top.

💡 Combine flex-wrap: wrap with align-content to control how wrapped lines are spaced vertically.


Line Breaks in Flexbox

When items overflow the container (or if you explicitly set flex-wrap: wrap), they will wrap to the next line (or column) depending on the flex-direction. This wrapping creates multiple lines of flex items.

Each line of items has its own main axis and cross-axis. However, the main and cross axes of wrapped lines behave differently from a single line of items:

  • For each line of items:

    • The main axis (in the direction of the flex-direction) will control how the items in that line are distributed.

    • The cross axis (perpendicular to the flex-direction) controls how the items are aligned vertically (if in rows) or horizontally (if in columns).

When flex items wrap, the entire set of lines will still adhere to the same main axis and cross-axis principles, but the align-content property affects how the lines themselves (not the items within the lines) are spaced in the cross-axis.

align-content: Aligning Wrapped Lines

The align-content property is used to control the spacing between the lines of wrapped flex items along the cross axis (the perpendicular axis to the main axis). It works when there are multiple lines of flex items due to wrapping.

How align-content Affects Wrapped Lines:

  • flex-start: Aligns the lines to the top (if flex-direction: row), or to the left (if flex-direction: column).

  • flex-end: Aligns the lines to the bottom (if flex-direction: row), or to the right (if flex-direction: column).

  • center: Centers the lines vertically (if flex-direction: row), or horizontally (if flex-direction: column).

  • space-between: Spaces the lines evenly, with the first line at the top and the last line at the bottom, with equal spacing between them.

  • space-around: Spaces the lines with equal space around them.

  • space-evenly: Spaces the lines evenly, with equal spacing between all lines.

  • stretch: The lines stretch to fill the container space (works only if there’s enough room and items aren’t stretched along the cross axis).


How flex-grow and flex-shrink Control Flex Item Sizing

Let's break down how flex-grow and flex-shrink work, how they’re generally used, and how they interact with the max-width, min-width, and other properties.


1. flex-grow (How items expand)

The flex-grow property defines how much a flex item should grow relative to the other items in the flex container when there's extra space available.

  • Default Value: flex-grow: 0

    • If flex-grow is 0, the item will not grow to take up any available space.
  • Value of 1:

    • If flex-grow is 1, the item will grow to take up the available space in proportion to other items. For example, if one item has flex-grow: 1 and another has flex-grow: 2, the second item will grow twice as much as the first one.
  • Higher values:

    • If flex-grow is set to a number greater than 1, the item will grow even more relative to other items. A value of 2, for instance, will make the item take up twice as much space as an item with flex-grow: 1.

2. flex-shrink (How items shrink)

The flex-shrink property defines how much a flex item should shrink relative to the other items in the flex container when there’s not enough space.

  • Default Value: flex-shrink: 1

    • This means that items will shrink if necessary to fit in the container when there’s not enough space. All items will shrink at the same rate unless specified differently.
  • Value of 0:

    • If flex-shrink is 0, the item will not shrink. This can be useful if you want a specific item to maintain its size and not shrink under any circumstances.
  • Higher values:

    • Setting flex-shrink to a value greater than 1 makes the item shrink more aggressively compared to other items.

3. Combined Use of flex-grow and flex-shrink

When both flex-grow and flex-shrink are used together, they define how an item will behave in terms of growth and shrinking in a flex container. Here's how:

  • If there is extra space: The flex-grow property will take precedence, and the items will expand based on the available space.

  • If there is insufficient space: The flex-shrink property will take precedence, and the items will shrink based on the container's size.

Both properties are relative, so they will behave according to the values of other items' flex-grow and flex-shrink.

Example:

Imagine we have a container with 3 items and the following properties:

.container {
  display: flex;
}

.item1 {
  flex-grow: 1;
  flex-shrink: 1;
}

.item2 {
  flex-grow: 2;
  flex-shrink: 1;
}

.item3 {
  flex-grow: 1;
  flex-shrink: 0;
}
  • item1: It will grow and shrink equally, meaning it will take up space if there's extra space and shrink if there’s not enough.

  • item2: It will grow more than item1 (twice as much), and it will shrink if needed (just like item1).

  • item3: It will grow but not shrink at all, so it will maintain its size regardless of the container's available space.


4. flex-basis and the Role of max-width / min-width

The flex-basis property determines the initial size of an item before any growing or shrinking happens. It can be combined with flex-grow and flex-shrink to control the starting size of an item.

  • flex-basis: Sets the initial size of the flex item. It can be set to a specific value (e.g., 200px), auto (the item's natural size), or any other valid CSS length value.

max-width and min-width:

  • max-width: Limits the maximum width a flex item can grow to.

  • min-width: Sets a minimum size the flex item must maintain, even if there is not enough space.

How They Interact:

  • flex-grow and max-width: If an item has a max-width defined, it will not grow beyond that value, even if there's extra space available in the container. The flex-grow property will stop growing the item once it reaches the max-width.

  • flex-shrink and min-width: If an item has a min-width defined, it will not shrink below that size, even if the container is too small. The flex-shrink property will stop shrinking the item once it hits the min-width.

Example with max-width, min-width, and Flex:

.container {
  display: flex;
  width: 500px; /* Width of the container */
}

.item1 {
  flex: 1 1 200px; /* flex-grow: 1, flex-shrink: 1, flex-basis: 200px */
}

.item2 {
  flex: 2 1 200px; /* flex-grow: 2, flex-shrink: 1, flex-basis: 200px */
}

.item3 {
  flex: 0 1 100px; /* flex-grow: 0, flex-shrink: 1, flex-basis: 100px */
  max-width: 150px; /* Item will not grow beyond 150px */
}

.item4 {
  flex: 1 0 150px; /* flex-grow: 1, flex-shrink: 0, flex-basis: 150px */
  min-width: 120px; /* Item will not shrink below 120px */
}

How this would behave:

  1. Item1 and Item2 will grow according to their respective flex-grow values, and shrink if needed based on flex-shrink. Item1 will grow at a slower rate than Item2.

  2. Item3 will not grow beyond 150px due to max-width, even if there is more available space.

  3. Item4 will not shrink below 120px due to the min-width, so it will only shrink if there is space to reduce, but never below 120px.


5. Example Summary with Code

Let’s put everything together in a code snippet to see how flex-grow, flex-shrink, max-width, and min-width interact:

<div class="container">
  <div class="item1">Item 1</div>
  <div class="item2">Item 2</div>
  <div class="item3">Item 3</div>
  <div class="item4">Item 4</div>
</div>
.container {
  display: flex;
  width: 600px; /* container width */
}

.item1 {
  flex: 1 1 200px; /* flex-grow: 1, flex-shrink: 1, flex-basis: 200px */
  background-color: lightblue;
}

.item2 {
  flex: 2 1 200px; /* flex-grow: 2, flex-shrink: 1, flex-basis: 200px */
  background-color: lightgreen;
}

.item3 {
  flex: 0 1 100px; /* flex-grow: 0, flex-shrink: 1, flex-basis: 100px */
  max-width: 150px; /* Cannot grow beyond 150px */
  background-color: lightcoral;
}

.item4 {
  flex: 1 0 150px; /* flex-grow: 1, flex-shrink: 0, flex-basis: 150px */
  min-width: 120px; /* Cannot shrink below 120px */
  background-color: lightgoldenrodyellow;
}

What Happens?

  • Item 1 and Item 2 grow relative to their flex-grow values, with Item 2 growing twice as much as Item 1.

  • Item 3 cannot grow beyond 150px due to the max-width, even though there's space.

  • Item 4 can grow but will not shrink below 120px, due to the min-width.


Conclusion:

  • flex-grow determines how flex items expand when there's available space.

  • flex-shrink controls how items shrink when there’s not enough space.

  • These properties work relatively to other items, and their effects are combined with the flex-basis property to determine the starting size.

  • max-width and min-width constrain the item’s growth and shrinkage, ensuring it never exceeds or shrinks below a specific size.

🧭 Individual Alignment with align-self (on the Cross Axis)

The align-self property allows a single flex item to override the alignment specified by align-items for the container. While align-items applies the cross-axis alignment to all items, align-self gives per-item control on the cross axis.

🔧 Syntax:

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
  • auto: Inherits from align-items (default).

  • flex-start / flex-end / center: Aligns the item individually along the cross axis.

  • stretch: Stretches the item to fill the container’s cross-axis size (if no height is set).

  • baseline: Aligns item based on text baseline.

✅ Use Cases:

  • Fine-tuning the alignment of specific items in a layout.

  • Making one item stand out (e.g., vertically centering just one element in a sidebar list).

  • Aligning items independently in a card or grid-style layout.


🚫 No align-self Equivalent on the Main Axis

Flexbox does not have a direct justify-self equivalent (like Grid does) for the main axis. You can’t use justify-self to individually control horizontal (or main-axis) alignment of flex items. Instead, the main axis alignment is controlled collectively by justify-content on the container.


💡 Workaround: margin-left: auto or margin-right: auto

Even though you can't justify-self, you can cleverly use auto margins to push individual items to one side. This is a powerful Flexbox trick, especially in navigation bars or headers.

✨ Example: Navbar with One Item on the Left and Others on the Right

<nav class="navbar">
  <div class="logo">Logo</div>
  <div class="menu">Home</div>
  <div class="menu">About</div>
  <div class="menu">Contact</div>
</nav>
.navbar {
  display: flex;
  background-color: #333;
  padding: 10px;
}

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

.menu {
  margin-left: 20px;
  color: white;
}

/* This pushes the first .menu item (and others after it) to the right */
.menu:first-of-type {
  margin-left: auto;
}

🎯 This creates the classic layout where:

  • Logo stays on the left

  • All other menu items align to the right

You can also do the same for vertical alignment by using margin-top: auto or margin-bottom: auto in flex-direction: column.


✅ Summary

PropertyAxisPurposeAlternative or Workaround
align-selfCross AxisIndividually aligns item along cross axisDirect, supported
justify-selfMain Axis❌ Not supported in FlexboxUse margin-left/right: auto

So while Flexbox doesn’t support justify-self, the auto margin hack gives you a simple, elegant way to mimic it.

0
Subscribe to my newsletter

Read articles from Sagnik Guru directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sagnik Guru
Sagnik Guru