skip to content

Classic Flex Layout Patterns

The layouts interviewers ask you to build on a whiteboard: perfect centering, a sticky footer, a nav bar with one item pushed right, and equal-height cards. The point is knowing the idiomatic flex recipe for each without hesitating.

part ofCSSoverview, primer and where to startread it →
on this pageshow

questions

5

Using CSS Flexbox, how do you center a single child both horizontally and vertically inside its parent, and what does the parent need for the vertical centering to be visible?

level: juniorimportance: must knowfreq 86%

answer

  1. everything goes on the parent
  2. two axes, two properties
  3. the container needs real height
  4. margin: auto splits free space
  5. place-content only half works

basics

~20 s

Set display: flex, justify-content: center and align-items: center on the parent, and give that parent a height, such as min-height: 100vh. Without a height the parent shrink-wraps its child, so there is no vertical free space to center in.

solid answer

~40 s

Three declarations on the **parent** do it: `display: flex`, `justify-content: center` (main axis) and `align-items: center` (cross axis). In the default `flex-direction: row` that centers horizontally and vertically respectively; if I switch to `column` the two properties swap roles, so I think of it as "center on both axes" rather than "one for left-right, one for up-down". The part people forget is that the parent is only as tall as its content by default, so `align-items: center` appears to do nothing — I give the parent real height, typically `min-height: 100vh` for a full-page splash or a fixed height for a card. A one-declaration alternative is `margin: auto` on the child, because auto margins in flex absorb free space on both axes.

code

css · 10 lines
css
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

.hero__card {
  max-width: 32rem;
}

go deeper

for a junior

Be able to write the three declarations from memory on the parent and say which axis each one controls. Mention that the parent needs a height, for example min-height: 100vh, for the vertical centering to show.

for a middle

Explain centering in terms of main and cross axis so the answer survives flex-direction: column, and describe where the free space comes from. Knowing the margin: auto alternative and why it behaves the same for a single child is expected.

for a senior

Show judgment about which container actually owns the height in a real page, and be ready to say why place-content and place-items only half-work in flex. Interviewers listen for whether you debug centering by asking where the free space is.

for a principal

Own the convention: whether centering lives in a reusable utility, a layout primitive component, or ad-hoc rules, and what that costs in stylesheet size and consistency. Be able to argue when grid's place-items is the better default for the codebase.

## What "centering" means to a flex container A flex container lays its children out along a **main axis**, chosen by `flex-direction`. The default is `row`, so in a left-to-right writing mode the main axis runs horizontally. The perpendicular axis is the **cross axis**. Two properties do the positioning: `justify-content` distributes items along the main axis, and `align-items` positions them on the cross axis. That is why the recipe is worth memorising as *axes*, not as *directions*. In a row container `justify-content: center` is horizontal and `align-items: center` is vertical; add `flex-direction: column` and the two silently trade places. Candidates who memorised "justify is horizontal" get caught the moment the container becomes a column. ## The canonical recipe ```css .parent { display: flex; justify-content: center; align-items: center; min-height: 100vh; } ``` All four declarations sit on the parent. Nothing at all goes on the child — a frequent mistake is putting `justify-content` on the element you want centered, where it does nothing unless that element is itself a flex container. ## Why the height is the real answer A block-level box is as tall as its content unless you say otherwise. If `.parent` is a plain `div` wrapping one paragraph, its height *is* the paragraph's height, so after `align-items: center` there is zero leftover cross-axis space and the paragraph looks unchanged. Centering only becomes visible when the container is taller than the item. So the vertical half of the recipe is really "give the container a height": `min-height: 100vh` for a viewport-filling section, a fixed `height` for a fixed-size card, or an inherited height when the parent is itself a stretched flex or grid item. Interviewers ask this precisely because it separates people who copied a snippet from people who understand where the free space comes from. ## The auto-margin alternative ```css .parent { display: flex; min-height: 100vh; } .child { margin: auto; } ``` In a flex container an `auto` margin absorbs free space in the direction it points. With all four margins `auto`, the leftover space is split equally above/below and left/right, centering the child on both axes with a single declaration on the child. For a lone child this is equivalent to the three-property version. The behaviours differ once there are several items: auto margins take their share of the free space *before* `justify-content` gets to distribute what remains, which is exactly the property exploited by nav-bar layouts. ## Two shorthands that only half-work here Both `place-content` and `place-items` look like one-line centering, and in a grid container `place-items: center` genuinely is. In a flex container each of them only does half the job: - `place-content` is shorthand for `align-content` + `justify-content`. `align-content` applies only to **multi-line** flex containers, and the default is `flex-wrap: nowrap`, so with one line it is ignored — `place-content: center` centers horizontally only. - `place-items` is shorthand for `align-items` + `justify-items`, and flex containers ignore `justify-items` entirely, so `place-items: center` centers vertically only (in a row). Knowing why each falls short is a much stronger answer than reciting the three-property recipe. ## Things that are not box centering `text-align: center` centers *inline content* inside a block; it does not move the block itself. `line-height` equal to the container height only ever centers a single line of text and breaks on wrap. `vertical-align` applies to inline-level and table-cell boxes, not to flex items. These are the pre-flexbox workarounds, and reaching for them today reads as out-of-date. ## Practical variations If the child should also be centered but capped in width, keep the flex recipe and give the child `max-width` — the container centers whatever width the child settles at. If several children should be centered as a group, the same recipe works, and `gap` spaces them. If you want the child centered horizontally but pinned to the top, use `align-items: flex-start` and keep `justify-content: center`; the two axes are always controlled independently, which is the whole point of the model.

  • If I change the container to flex-direction: column, do I have to change anything?
    No — the same two declarations still center on both axes, but their roles swap: `justify-content: center` now controls vertical placement and `align-items: center` horizontal. That is why it is safer to say "main axis and cross axis" than "horizontal and vertical" when describing the recipe.
  • Why does align-items: center sometimes make a child visibly shrink?
    Because the default is `align-items: stretch`, which makes the child fill the container's cross size. Switching to `center` removes that stretch, so the child falls back to its content-based size. If you want it centered but still full-width in a column container, keep `align-self: stretch` on the child or set an explicit width.
  • How would you center an element both ways without Flexbox?
    Grid is the shortest: `display: grid; place-items: center` on the parent — in grid, unlike flex, `justify-items` is honoured so the shorthand really does both axes. The older technique is `position: absolute; inset-block-start: 50%; inset-inline-start: 50%; transform: translate(-50%, -50%)`, which still works but takes the element out of flow.

saying these in an interview costs you the question

  • Putting justify-content on the child instead of the container
  • Claiming place-content: center centers a nowrap flex row vertically
  • Forgetting the container needs a height for vertical centering
  • Using text-align: center to move a block-level box
  • Saying justify-content is always the horizontal one

context

open as a page

A row of flex cards renders at equal heights, but each card's action button sits directly under its text, so the buttons don't line up across cards. In CSS, how do you pin every button to the bottom of its own card?

level: middleimportance: should knowfreq 44%

basics

~20 s

Make each card its own column flex container and give the button margin-top: auto. The row's default stretch already makes the cards equal height; the auto margin then pushes the button to the bottom of that stretched height, so buttons align across the row.

open as a page

In a Flexbox nav bar whose children are a logo and several links, how do you push just the last link to the far right while the others stay grouped on the left?

level: middleimportance: should knowfreq 48%

basics

~20 s

Give the last link margin-left: auto. In a flex container an auto margin absorbs all remaining free space in the direction it points, so that item is shoved to the right edge while its siblings stay packed on the left.

open as a page

How would you build a holy-grail page layout — header, footer, fixed-width left and right sidebars and a fluid centre column — with Flexbox, and when would you reach for CSS Grid instead?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Nest two flex containers: an outer column for header, body and footer with min-height: 100vh, and an inner row where each sidebar is flex: 0 0 240px and the centre is flex: 1. Grid is better once the layout is genuinely two-dimensional or must rearrange at breakpoints.

open as a page