ToolPal
Code editor showing CSS on a monitor

CSS Flexbox Generator Guide β€” Build Layouts Visually

πŸ“· Sai Kiran Anagani / Pexels

CSS Flexbox Generator Guide β€” Build Layouts Visually

Learn CSS Flexbox by building layouts visually. Understand flex-direction, justify-content, align-items, and more with a live generator and practical examples.

March 30, 202612 min read

My Flexbox Journey (And Why I Still Look Things Up)

I remember the exact moment I thought I understood flexbox. I had been wrestling with a navigation bar for the better part of an afternoon, floats weren't doing what I wanted, inline-block was adding phantom spacing, and then someone in a Stack Overflow comment said "just use flexbox." So I did. I typed display: flex and everything lined up. Magic.

Then the next day I tried to center something vertically and I was completely lost again.

That's the thing about flexbox β€” the entry point feels easy, but the mental model takes a while to really click. The moment it finally clicked for me was when I stopped thinking in terms of "left, right, top, bottom" and started thinking in terms of axes. Once that switch happened, flexbox became genuinely one of the most satisfying tools in CSS.

This guide is going to walk through how flexbox works, explain every property you'll actually use day-to-day, and share the gotchas that tripped me up (and still trip up people I work with). If you want to experiment visually as you read, check out the CSS Flexbox Generator on ToolBox Hubs β€” it lets you tweak properties and see the result in real time, which honestly is the fastest way to build the mental model.


The Flex Container Model

Everything in flexbox starts with one rule: you have a container and you have items inside it. You set display: flex on the container, and the direct children become flex items. That's the whole hierarchy β€” container and items.

.container {
  display: flex;
}

That one line changes a lot. Your items will now sit in a row by default, they'll stretch to fill the container's height, and they'll shrink if there isn't enough space. Most of the flexbox properties you'll use are set on the container, not on the items (though there are a few important item-level properties we'll get to).

The Two Axes

This is the part that confuses nearly everyone learning flexbox, and I'd argue it's the single most important concept to internalize. Flexbox operates on two axes:

  • Main axis β€” the direction your items flow (row or column)
  • Cross axis β€” perpendicular to the main axis

When flex-direction is row (the default), the main axis runs left to right, and the cross axis runs top to bottom. When you switch to column, those flip. This matters enormously because justify-content and align-items are defined relative to these axes, not relative to absolute directions.

That's the number one stumbling block for everyone learning flexbox β€” the axis confusion between justify-content and align-items. Once you remember that justify always means "along the main axis" and align always means "along the cross axis," everything else becomes predictable.


Every Property You Actually Need

flex-direction

Controls which direction your items flow.

.container {
  display: flex;
  flex-direction: row;         /* default β€” left to right */
  flex-direction: row-reverse; /* right to left */
  flex-direction: column;      /* top to bottom */
  flex-direction: column-reverse; /* bottom to top */
}

column is something I reach for more than I expected when I started. Anytime you want to stack things vertically and control their spacing, flex-direction: column combined with gap is fantastic.

justify-content

Aligns items along the main axis. In a row, that's horizontal. In a column, that's vertical.

.container {
  display: flex;
  justify-content: flex-start;    /* default β€” items at the start */
  justify-content: flex-end;      /* items at the end */
  justify-content: center;        /* items in the middle */
  justify-content: space-between; /* equal space between items, none on edges */
  justify-content: space-around;  /* equal space around each item */
  justify-content: space-evenly;  /* truly equal space everywhere */
}

space-between is the one I use most for navigation bars β€” items spread to both ends with equal gaps between them. center is what you want when you just need something in the middle.

align-items

Aligns items along the cross axis. In a row, that's vertical. In a column, that's horizontal.

.container {
  display: flex;
  align-items: stretch;     /* default β€” items stretch to fill container height */
  align-items: flex-start;  /* items sit at the top */
  align-items: flex-end;    /* items sit at the bottom */
  align-items: center;      /* items centered vertically */
  align-items: baseline;    /* items aligned by text baseline */
}

stretch being the default is actually pretty useful β€” it's why flex items in a row all end up the same height even when they have different amounts of content. But once you want vertical centering, you reach for align-items: center.

flex-wrap

By default, flex items try to fit on one line and will shrink to make that happen. flex-wrap lets you change that behavior.

.container {
  display: flex;
  flex-wrap: nowrap;       /* default β€” items stay on one line */
  flex-wrap: wrap;         /* items wrap to new lines */
  flex-wrap: wrap-reverse; /* items wrap upward */
}

flex-wrap: wrap is essential for responsive card grids. Without it, your items will keep shrinking no matter how small the viewport gets.

gap

Okay, gap isn't technically a flex-only property β€” it came from CSS Grid β€” but it works with flexbox and it's genuinely great. Before gap, we were doing margin hacks. Now:

.container {
  display: flex;
  gap: 16px;          /* same gap in both directions */
  gap: 12px 24px;     /* row-gap column-gap */
}

Use it everywhere. It's simpler than margin and doesn't add space at the edges.

align-content

This one is easy to miss. align-content is like justify-content but for the cross axis, and it only does anything when you have multiple rows (i.e., when flex-wrap: wrap is in play and items have actually wrapped). If all your items are on one line, align-content has no visible effect.

.container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-content: center;
  align-content: space-between;
}

This is probably the most commonly misunderstood flexbox property β€” people set it expecting something to happen and nothing does, because their items aren't wrapping.

Item-Level Properties

A few properties go on the flex items themselves rather than the container.

flex-grow β€” how much an item grows to fill available space (default: 0)

flex-shrink β€” how much an item shrinks when space is tight (default: 1)

flex-basis β€” the item's starting size before growing or shrinking (default: auto)

These three are often combined with the shorthand flex:

.item {
  flex: 1;        /* grow: 1, shrink: 1, basis: 0 β€” equal-width items */
  flex: 0 0 200px; /* fixed width, no grow or shrink */
  flex: 2;        /* this item grows twice as fast as flex: 1 siblings */
}

align-self lets a single item override the container's align-items setting:

.special-item {
  align-self: flex-end; /* this item sticks to the bottom even if siblings don't */
}

Common Patterns

Centering Anything (The Classic)

This is probably the most Googled CSS snippet in history. Centering a div both horizontally and vertically:

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh; /* needs some height to center vertically within */
}

That's it. Two lines (three if you count the height). Before flexbox, vertical centering was genuinely painful. Now it's muscle memory.

Responsive Navigation Bar

A horizontal nav that pushes the logo to the left and nav links to the right:

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
}

And for mobile, you might switch to column:

@media (max-width: 768px) {
  .navbar {
    flex-direction: column;
    gap: 12px;
  }
}

Responsive Card Grid

Cards that sit side by side on desktop and stack on mobile:

.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.card {
  flex: 1 1 300px; /* grow, shrink, min-width of 300px */
  max-width: 400px;
}

The flex: 1 1 300px is the key β€” it says "start at 300px wide, but grow and shrink as needed." Cards will naturally reflow into fewer columns on smaller screens without a single media query.

Classic "footer sticks to the bottom even with little content" pattern:

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main {
  flex: 1; /* main content grows to push footer down */
}

footer {
  /* stays at the bottom */
}

This one is in nearly every project I build.


Flexbox vs CSS Grid: When to Use Which

There's a lot of unnecessary debate about this online. The honest answer is: use both, they're for different things.

Reach for Flexbox when:

  • You have a single row or column of items
  • You want items to wrap naturally (like tags, card lists)
  • You're building a navigation bar, a toolbar, or a button group
  • You need one axis of control with flexible item sizing

Reach for CSS Grid when:

  • You have a two-dimensional layout with rows and columns
  • You're building a page-level layout with header, sidebar, main, footer
  • You want explicit placement of items into specific cells
  • You need consistent row heights across multiple columns

In practice, a real page might use Grid for the overall page layout, Flexbox for the nav, Flexbox for a card's internal layout, and Grid again for a data table. They complement each other well.

If you're still unsure, ask yourself: "am I thinking about one direction or two?" One direction β€” flexbox. Two directions β€” grid.


Common Mistakes and Gotchas

These are the things that have bitten me more than once. Learn from my suffering.

flex-shrink: 0 for Images

By default, flex items can shrink. Images in flex containers will shrink below their natural size, which looks terrible. Fix it:

img {
  flex-shrink: 0;
}

Or use the shorthand:

img {
  flex: 0 0 auto; /* don't grow, don't shrink, use natural size */
}

I've debugged squished avatar images in card components too many times before remembering this.

The min-width: 0 Overflow Issue

This one is subtle and drives people crazy. By default, flex items have min-width: auto, which means they won't shrink below their content size. If you have a flex item containing long text or a wide element, it might overflow its container even when flex: 1 is set.

The fix:

.flex-item {
  min-width: 0; /* allow the item to shrink below content size */
  overflow: hidden; /* or overflow: auto if you want scroll */
}

This is especially common with text that needs to truncate with an ellipsis inside a flex item. You need min-width: 0 or the text won't truncate β€” it'll just overflow.

align-content Only Works with Wrapping

As mentioned above, setting align-content on a single-row flex container does absolutely nothing. You need:

  1. flex-wrap: wrap on the container
  2. Enough items to actually wrap onto multiple lines

If you're setting align-content and seeing no change, check whether your items are actually wrapping. Add a fixed height or shrink the viewport to force wrapping, then align-content will kick in.

Percentage Heights Inside Flex Items

If you try to set height: 100% on a child element inside a flex item, it often doesn't work as expected. The flex item itself needs an explicit height for percentage heights to resolve against. This trips people up when trying to make card images fill their container.

.card {
  display: flex;
  flex-direction: column;
}

.card-image {
  flex: 0 0 200px; /* explicit size instead of percentage */
}

margin: auto is Powerful in Flex Containers

This one is more of a secret weapon than a gotcha, but it surprises people: setting margin-left: auto on a flex item will push it (and everything after it) to the far end of the container. It's how you can do nav layouts with a logo on the left and a login button on the far right without any wrapper elements:

.nav {
  display: flex;
  align-items: center;
}

.nav-login {
  margin-left: auto; /* pushes the login button to the right edge */
}

Building Layouts Visually

Reading about flexbox properties is useful, but the fastest way to really internalize the mental model is to play with them. The CSS Flexbox Generator lets you toggle every property and watch the layout update in real time β€” you can see immediately what happens to your items when you flip justify-content from flex-start to space-between, or what align-self does to a single item.

Seriously, spend 10 minutes clicking through the properties. You'll lock in the mental model faster than hours of reading docs.


Browser Support

One thing you don't need to worry about with flexbox: browser support. Flexbox has been universally supported since around 2015. Every modern browser supports it fully. Even IE 11 had partial support (though honestly, if you're still supporting IE 11, you have larger problems).

You can use flexbox confidently without any vendor prefixes or polyfills. The old -webkit-flex and -ms-flexbox prefixes are long retired. Just write standard flexbox and ship it.


Wrapping Up

Flexbox clicked for me the moment I stopped thinking about it as "a way to make things go left or right" and started thinking about it as a system of axes and item behaviors. The main axis is where your items flow. The cross axis is perpendicular. justify-content controls the main axis. align-items controls the cross axis. Everything else flows from that.

The patterns I reach for daily are:

  • display: flex; justify-content: center; align-items: center for centering
  • justify-content: space-between for navbars and toolbars
  • flex-wrap: wrap with gap for responsive grids
  • flex: 1 for equal-width items or growing content areas
  • flex-direction: column; min-height: 100vh with flex: 1 on main for sticky footers

Watch out for the shrinking image problem, the min-width: 0 overflow issue, and the fact that align-content needs wrapped items to do anything.

Flexbox is genuinely one of those CSS features where once you have the mental model, you feel like you unlocked a superpower. It doesn't replace CSS Grid β€” use both β€” but for single-axis layouts, it's hard to beat. Happy laying out.

Frequently Asked Questions

Share this article

XLinkedIn

Related Posts