AlgoDaily

CSS Flexbox

Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.

Why Flexbox Now

From styled boxes to intentional layout

In CSS Fundamentals, you built the core model: selectors, cascade, box model, units, naming, and debugging. Flexbox is where those pieces start behaving like a layout system instead of isolated style rules.

Flexbox matters because many interface problems are one-dimensional:

  • A nav bar spreading links across a row
  • A media object with an avatar beside text
  • A card footer where one button hugs the end
  • A row of reality-show contestant cards that should align even when names are chaotic

At staff level, the value is not memorizing every property. It is being able to look at a layout bug and ask: Which element owns the layout contract: the parent or the child?

In Flexbox, the parent becomes the flex container, and its direct children become flex items.

Why Flexbox Now

One Dimensional Contract

Flexbox solves one axis at a time

Flexbox is best understood as a contract between a container and its direct children.

.deck {
  display: flex;
}

That single declaration changes how .deck lays out its children.

.flex-container
┌─────────────────────────────┐
│ [item]   [item]   [item]    │
└─────────────────────────────┘

The most important mental model:

  • Main axis: the direction items primarily flow
  • Cross axis: the perpendicular direction

By default, flex-direction: row, so the main axis runs left-to-right in typical English-language layouts.

When you switch to flex-direction: column, you are not merely stacking things. You are redefining which axis properties like justify-content and align-items apply to.

One Dimensional Contract

Axes Drive Meaning

justify-content and align-items are axis-relative

A common Flexbox bug comes from treating properties as if they always mean “horizontal” or “vertical.” They do not.

  • justify-content distributes space along the main axis
  • align-items aligns items along the cross axis

So this:

.toolbar {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

means: spread items across the row, then center them vertically.

But if you change to:

.toolbar {
  flex-direction: column;
}

then justify-content now works vertically, and align-items works horizontally.

That axis switch is the “plot twist” in many Flexbox debugging sessions.

```javascript
const flexDirections = {
  row: {
    mainAxis: "horizontal",
    crossAxis: "vertical",
    justifyContentAffects: "left/right distribution",
    alignItemsAffects: "up/down alignment"
  },
  column: {
    mainAxis: "vertical",
    crossAxis: "horizontal",
    justifyContentAffects: "up/down distribution",
    alignItemsAffects: "left/right alignment"
  }
};

for (const [direction, meaning] of Object.entries(flexDirections)) {
  console.log(`flex-direction: ${direction}`);
  console.log(`  main axis: ${meaning.mainAxis}`);
  console.log(`  cross axis: ${meaning.crossAxis}`);
  console.log(`  justify-content: ${meaning.justifyContentAffects}`);
  console.log(`  align-items: ${meaning.alignItemsAffects}`);
}
```

Axis Check

A container has this CSS:

.cast-list {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

Which direction does justify-content affect?

Alignment And Space

Alignment is about leftover space

Flexbox shines when content sizes are uneven. Think of a row of game inventory items: some labels are short, some wrap, and one action button should stay visually aligned.

Important container properties:

  • justify-content: distributes leftover space on the main axis
  • align-items: aligns all items on the cross axis
  • align-self: lets one item opt out of align-items
  • gap: creates spacing between flex items without margin hacks

Example:

.card-footer {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.card-footer .primary-action {
  margin-left: auto;
}

margin-left: auto consumes available inline space before the button, pushing it to the end. This is one of those small Flexbox moves that shows up constantly in production UI work.

Prefer gap for spacing between siblings. It expresses layout intent more directly than sprinkling margins onto every child.

Alignment And Space

Flexible Item Sizing

flex controls how items negotiate space

Container properties decide the overall layout. Item properties decide how each child participates.

The key shorthand is:

.item {
  flex: <grow> <shrink> <basis>;
}

For example:

.sidebar { flex: 0 0 240px; }
.content { flex: 1 1 auto; }

Read that as:

  • Sidebar: do not grow, do not shrink, start at 240px
  • Content: grow to consume leftover space, shrink if needed, start from its natural size

The browser's real algorithm has nuance, but the staff-level intuition is this:

  1. Start with each item's basis
  2. Compare total basis to container size
  3. If there is extra space, distribute by flex-grow
  4. If there is not enough space, reduce by flex-shrink

This is layout as negotiation, not absolute positioning.

```javascript
function distributeGrowSpace(containerWidth, items) {
  const totalBasis = items.reduce((sum, item) => sum + item.basis, 0);
  const freeSpace = containerWidth - totalBasis;
  const totalGrow = items.reduce((sum, item) => sum + item.grow, 0);

  console.log(`Container: ${containerWidth}px`);
  console.log(`Total basis: ${totalBasis}px`);
  console.log(`Free space: ${freeSpace}px`);

  return items.map((item) => {
    const extra = totalGrow > 0 ? (freeSpace * item.grow) / totalGrow : 0;
    return {
      name: item.name,
      finalWidth: item.basis + extra
    };
  });
}

const layout = distributeGrowSpace(900, [
  { name: "sidebar", basis: 240, grow: 0 },
  { name: "main", basis: 300, grow: 1 },
  { name: "details", basis: 180, grow: 1 }
]);

console.log(layout);
```

Container Declaration

Fill in the missing CSS declaration.

.toolbar {
  ________;
  align-items: center;
  gap: 1rem;
}

What declaration turns .toolbar into a flex container?

Wrap And Order

Flexbox can wrap, but source order still matters

By default, flex items try to stay on one line:

.shelf {
  display: flex;
  flex-wrap: nowrap;
}

You can allow wrapping:

.shelf {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

This is useful for rows of chips, tags, small cards, or action buttons where a single line may not have enough room.

Flexbox also has order, which visually rearranges items:

.featured {
  order: -1;
}

Use it carefully. Visual order and DOM order can diverge, which affects keyboard navigation, screen readers, and maintainability. From DOM Manipulation, you already know the document tree is not just an implementation detail; it is the structure assistive tech and event flow often depend on.

If the intended reading or interaction order changes, prefer changing the actual markup order rather than relying on visual reordering.

```javascript
function describeFlexList({ wrap, featuredFirst }) {
  const css = [
    ".shelf {",
    "  display: flex;",
    `  flex-wrap: ${wrap ? "wrap" : "nowrap"};`,
    "  gap: 1rem;",
    "}",
    featuredFirst ? ".featured { order: -1; }" : "/* DOM order and visual order match. */"
  ].join("\n");

  console.log(css);
}

describeFlexList({ wrap: true, featuredFirst: false });
describeFlexList({ wrap: true, featuredFirst: true });
```

Order Reality

True or false: using the Flexbox order property changes the actual DOM order of elements.

Debug Flex Layouts

A practical Flexbox debugging loop

When a Flexbox layout behaves oddly, do not randomly toggle properties. Use the same detective mindset from CSS Fundamentals.

Ask these questions in order:

  1. Is the right parent the flex container?
    display: flex affects direct children only.

  2. What is the main axis?
    Check flex-direction before interpreting justify-content.

  3. Where is the leftover space?
    Alignment properties only matter when there is space to distribute.

  4. Are item sizes fighting the container?
    Inspect flex, min-width, max-width, and content that refuses to shrink.

  5. Is spacing intentional?
    Prefer gap for sibling spacing. Watch for legacy margins still applying.

  6. Did visual order diverge from source order?
    Be cautious with order when interaction or accessibility matters.

Flexbox is the right tool when you are arranging items along one primary axis. Next, CSS Grid will give you a different mental model for two-dimensional layout.

Debug Flex Layouts

Open interactive view →