You set align-content: center on a flex container and nothing moved. Why does align-content so often have no effect, and how is it different from align-items?
answer
- which thing is being aligned
- lines, not items
- nowrap means one line only
- auto height leaves nothing to distribute
basics
~20 salign-content aligns whole flex lines, so it does nothing unless flex-wrap has actually produced more than one line; align-items is what positions items inside their own line. Either way, there must be spare cross-axis space for the effect to be visible.
solid answer
~40 sThe two properties operate on different things. `align-items` aligns each item **within its flex line**; `align-content` aligns **the lines themselves** as a group within the container's cross-axis space. A flex container is single-line by default because `flex-wrap` starts at `nowrap`, and the specification says `align-content` has no effect on a single-line flex container — so the usual cause is simply that there is only one line. The second cause is no spare space: even with wrapping on, a container whose cross size is `auto` is exactly as tall as its lines, so there is nothing to distribute. Turn wrapping on and give the container a cross size, and `align-content` starts behaving like `justify-content` but on the cross axis, including the `space-between`/`space-around`/`space-evenly` values.
code
css · 7 lines.gallery {
display: flex;
flex-wrap: wrap; /* without this, align-content is inert */
height: 400px; /* without this, there is no leftover space */
align-content: center; /* moves the lines as a group */
align-items: flex-start; /* moves each item inside its own line */
}go deeper
Know that align-content is the odd one out: it only matters when items wrap onto several lines. Reaching for align-items when you want to move items is the habit to build.
State both preconditions — more than one flex line, and cross-axis space beyond the lines' total size — and explain the two-level model where align-content places lines and align-items places items inside them.
Show the debugging order: confirm wrapping actually occurred at this width, then check the container's cross size, then look at values. Mention that the stretch default on lines is what produces surprise vertical gaps in wrapped card grids.
Point out that a layout depending on align-content is depending on wrapping happening, which is viewport- and content-dependent; where the arrangement must be deterministic, a grid with declared tracks is the sturdier choice.
## Two levels of alignment Flexbox aligns at two levels, and `align-items` and `align-content` sit at different ones: - **Items within a line** — handled by `align-items` on the container and `align-self` on the item. This applies to every flex container, always. - **Lines within the container** — handled by `align-content`. This only means something when there is more than one line to arrange. When someone says "align-content doesn't work", one of those two conditions is missing. ## Condition one: there must be lines, plural A flex container is single-line unless you say otherwise, because `flex-wrap`'s initial value is `nowrap`. With one line, the specification is explicit: `align-content` has no effect on a single-line flex container. The declaration is not invalid and it is not overridden — it simply has nothing in scope to act on. ```css .cards { display: flex; height: 400px; align-content: center; } /* dead */ .cards { display: flex; height: 400px; flex-wrap: wrap; align-content: center; } /* alive */ ``` This is the answer the interviewer is usually fishing for, and it is worth stating in one sentence before anything else. ## Condition two: there must be leftover cross-axis space Even with multiple lines, alignment can only move things inside space that exists. `align-content` distributes the container's cross-axis space minus the total cross size of all the lines. If the container's cross size is `auto`, it grows to exactly fit its lines and that remainder is zero. Nothing moves. So the practical checklist when `align-content` looks inert is: is wrapping on, did it actually produce a second line at this viewport width, and does the container have a cross size larger than its content. ## What the values do once it is live `align-content` takes the same vocabulary as `justify-content`, applied to lines on the cross axis: `flex-start`, `flex-end`, `center`, `space-between`, `space-around`, `space-evenly`, and `stretch`. Its initial value is `normal`, which behaves as `stretch` in flexbox — the lines grow to divide the leftover cross space equally between them, which is why wrapped rows in a fixed-height container spread out on their own. That default is worth remembering, because it is also why a wrapped layout sometimes shows big unexplained vertical gaps: nobody asked for spacing, the lines simply stretched into the extra height. Setting `align-content: flex-start` collapses them back to the top. ## The interaction people trip over With multiple lines, `align-items` and `align-content` are both live and they compose. `align-content` decides where each line sits and how tall it is; `align-items` decides where an item sits inside its own line. If `align-content` has stretched the lines, an item with the default `stretch` fills that inflated line height, so a card can end up much taller than its content — which reads as a bug until you see the two-level model. A quick way to reason about a wrapped layout: `align-content` is the outer distribution, `align-items` is the inner one. Fix the outer first, then the inner. ## Naming symmetry The naming is more consistent than it first looks once you group the properties by what they target: `justify-*` names the main axis, `align-*` names the cross axis, `*-content` distributes a group inside its container's leftover space, and `*-items` positions individual items. `align-items` and `align-content` are therefore not variants of one idea — they are the item-level and group-level members of the cross-axis family, and only the group-level one depends on wrapping. ## What to say in the interview Lead with the single-line rule, add the auto-height rule as the second cause, and finish by contrasting the two properties in one line: `align-items` moves items inside a line, `align-content` moves the lines. That sequence shows you have debugged it rather than memorised a table.
- What is the initial value of align-content in a flex container, and what does it do?It is `normal`, which behaves as `stretch` in flexbox: the flex lines grow to divide any leftover cross-axis space equally. That default is why a wrapped layout in a fixed-height container shows generous vertical gaps nobody wrote — the lines expanded. `align-content: flex-start` packs them back together.
- With several flex lines, how do align-content and align-items interact?They compose at different levels. `align-content` decides where each line sits and, under stretch, how tall it becomes; `align-items` then places each item inside its own line. An item can therefore look oversized because the line stretched, not because the item's own alignment is wrong — fix the outer distribution first.
saying these in an interview costs you the question
- Uses align-content when they mean align-items
- Thinks align-content works without flex-wrap
- Expects alignment to work in an auto-height container
- Says align-content aligns items along the main axis
- Believes align-content's default is flex-start