skip to content

In Flexbox, how can you tell whether a CSS property belongs on the flex container or on a flex item, and what happens if you declare it on the wrong one?

level: juniorimportance: must knowfreq 58%

answer

  1. two owners, one rule
  2. statements about all versus about one
  3. the align-items and align-self pairing
  4. no errors, just no effect
  5. a nested container muddies the picture

basics

~20 s

Container properties set up the layout itself: display, flex-direction, flex-wrap, flex-flow, justify-content, align-items, align-content and gap. Item properties describe one box's own participation: order, flex-grow, flex-shrink, flex-basis, the flex shorthand and align-self. Declared on the wrong box, they are silently ignored.

solid answer

~50 s

The split follows the question each property answers. If it describes the layout as a whole — which axis, whether lines wrap, how the group is distributed and spaced — it goes on the container: `display`, `flex-direction`, `flex-wrap`, `flex-flow`, `justify-content`, `align-items`, `align-content`, `gap`. If it describes one box's own share of that layout — how much it grows or shrinks, what it starts from, where it sits on the cross axis, where it appears in the sequence — it goes on the item: `flex-grow`, `flex-shrink`, `flex-basis`, the `flex` shorthand, `align-self`, `order`. Put one in the wrong place and nothing happens: CSS has no errors, the declaration simply does not apply, and browser devtools mark it as an inactive property. The confusing case is a flex item that is itself `display: flex` — then container properties on it are perfectly valid, but they govern *its* children, not itself.

code

css · 13 lines
css
.row {
  display: flex;
  align-items: flex-start; /* default for every item */
}

.row > .logo {
  align-self: center;      /* this one box overrides it */
  flex: 0 0 auto;
}

.row > .search {
  flex: 1 1 auto;          /* this one box takes the slack */
}

go deeper

for a junior

Be ready to sort the common properties into the two groups on the spot and to name align-items versus align-self as the container default and its per-item override.

for a middle

Explain why the split exists — the container owns the layout, the item owns its own share — and why a misplaced declaration fails silently rather than erroring.

for a senior

Show the debugging habit: when a flex rule looks ignored, verify which box it is on and whether the element is a direct child, using the devtools inactive-property hint instead of escalating specificity.

for a principal

Frame it as an authoring-contract question: components should document which of their classes is the container and which are items, so consumers do not scatter container declarations onto items and then reach for !important when nothing happens.

## The rule behind the two lists Flexbox properties divide into two groups, and the division is not arbitrary. A flex container owns the **layout**: which axis items run along, whether they wrap onto more lines, how the group as a whole is distributed and spaced. A flex item owns **its own participation** in that layout: how much of the free space it takes, what size it starts negotiating from, where it sits across the axis, where it falls in the visual sequence. So before writing a declaration, ask: *is this a statement about all of them, or about this one?* | Declared on the container | Declared on the item | | --- | --- | | `display: flex` / `inline-flex` | `flex-grow` | | `flex-direction` | `flex-shrink` | | `flex-wrap` | `flex-basis` | | `flex-flow` (the two combined) | `flex` (the three combined) | | `justify-content` | `align-self` | | `align-items` | `order` | | `align-content` | | | `gap`, `row-gap`, `column-gap` | | One pairing is worth memorising because it catches people out: `align-items` is the container's default for all items, and `align-self` is the per-item override of that default. Same axis, two different owners. There is deliberately no `justify-self` in Flexbox, because main-axis position is a property of how the whole line is distributed, not of one box. ## What happens when you get it wrong Nothing — and that is exactly what makes it hard to debug. CSS does not raise errors. A declaration that does not apply to the box it is written on is simply ignored: `justify-content` on an item does not move that item, and `flex-grow` on the container does nothing unless that container is itself a flex item of something else. The stylesheet still parses, the rule still shows up in devtools, and the page just looks wrong. Modern browser devtools help here: they flag declarations that have no effect on the selected element, usually by dimming or striking through the property with a note explaining why. When a flex declaration seems to be ignored, checking whether the panel considers it active is faster than adding `!important`. ```css /* container: statements about the whole layout */ .toolbar { display: flex; flex-direction: row; justify-content: space-between; } /* item: statements about this one box */ .toolbar .search { flex-grow: 1; align-self: stretch; } ``` ## The case that looks like an exception A flex item can itself be a flex container. When it is, container properties on it are entirely legitimate — they just apply one level down. So `justify-content` written on `.card` does nothing to where `.card` sits inside `.row`, but if `.card` is `display: flex` it governs `.card`'s own children. People who have seen this working conclude that `justify-content` "sometimes works on items", which is the wrong lesson: the property never describes the box it is written on, always the box's children. ## Properties on neither list that still matter Several ordinary properties on an item feed the flex algorithm without being flex properties: - `width`, `height`, `min-*` and `max-*` on an item are inputs to sizing. Which of them counts as the main size depends on `flex-direction`, and min/max constraints clamp the result after growing and shrinking have been computed. - `margin: auto` on an item absorbs free space along whichever axis it is set on, before main-axis distribution runs. It is an item-level tool that is not part of the `flex` shorthand at all. - `position: relative` on an item behaves normally; the item is still a flex item and is then offset from its flex-computed position. A useful sanity check for the whole model: the *container* never knows anything about individual items beyond the defaults it hands them, and an *item* never knows anything about its siblings beyond the free space left over. Every flexbox property fits into one of those two sentences. ## Getting the vocabulary right in an interview Interviewers use this question as a quick probe for whether you have actually built with Flexbox or only read about it. Say the rule first — layout-wide versus per-box — then give a few examples on each side and the `align-items`/`align-self` pairing. Finish with the silent-failure point, because it is the practical part: nothing errors, so you diagnose by asking which box the declaration is on, not by escalating specificity.

  • Why does justify-content sometimes appear to work when it is written on a flex item?
    Because that item is itself a flex or grid container. The declaration is not positioning the item inside its parent — it is distributing the item's own children one level down. The property always describes a box's children, never the box it sits on.
  • Flexbox has align-items and align-self but no justify-self. Why not?
    Because main-axis position is a property of how the whole line is distributed, not of an individual box: items are packed along the main axis as a group, so there is nothing for a single item to opt out of. The nearest per-item tool is an auto margin, which absorbs free space on the side you set it on.
  • A flex declaration has no visible effect. What do you check before touching specificity?
    Which box it is on. Confirm the parent is actually a flex container, that the styled element is a direct child of it, and that a container property has not been written on an item or vice versa. Devtools mark inactive declarations, which usually settles it in seconds.

saying these in an interview costs you the question

  • Puts justify-content on the item to move that item
  • Expects an ignored declaration to raise some kind of error
  • Thinks flex-grow on the container grows the container
  • Cannot distinguish align-items from align-self
  • Believes display: flex affects all descendants, not just children

context