skip to content

How does a child with position: absolute behave inside a display: flex container — is it still a flex item?

level: middleimportance: nice to knowfreq 27%

answer

  1. out of flow, so not an item
  2. it takes up no space at all
  3. flex and order do nothing to it
  4. insets auto means static position
  5. the container is not automatically the containing block

basics

~20 s

No. An absolutely positioned child is out of flow, so it is not a flex item: it takes no space, is ignored by free-space distribution, and flex-grow, flex-shrink, flex-basis and order do nothing to it. Alignment still sets its static position.

solid answer

~50 s

Absolute positioning takes the child out of flow, so flex layout skips it entirely — it is not counted when free space is distributed, it does not push siblings, and the flex properties plus `order` have no effect on it. What still applies is its **static position**: with all inset properties left at `auto`, the browser places it where it would have gone if it were the sole flex item in the container, so `justify-content` on the container and `align-self` on the child do shift it. The moment you set `top`, `left`, or the other insets, they win for that axis and the alignment no longer matters. Its containing block is the nearest positioned ancestor's padding box, which is the flex container only if the container itself is positioned — otherwise the offsets resolve against something further up, which is the mistake people usually make.

code

css · 13 lines
css
.card {
  display: flex;
  justify-content: space-between;
  position: relative; /* required: otherwise offsets escape upward */
  padding: 1rem;
}

/* Not a flex item: takes no space, ignored by justify-content. */
.card > .badge {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
}

go deeper

for a junior

Know that an absolutely positioned child stops being a flex item, takes no space, and needs position: relative on the container for its offsets to anchor where you expect.

for a middle

Explain that out-of-flow means the flex properties and order do nothing, and that with all insets auto the box sits at its static position, computed as if it were the sole flex item so alignment still applies.

for a senior

Be precise about containing blocks: nearest positioned ancestor's padding box, and that transforms or filters can create one unexpectedly. Explain why overlays built this way never disturb the surrounding layout.

for a principal

Own the layering strategy: when an overlay belongs in the flow at all, when it should move to the top layer instead of an absolutely positioned sibling, and how the team keeps positioned-ancestor assumptions from breaking as components are nested.

## Out of flow means out of flex Flex layout operates on a container's **in-flow** children. `position: absolute` removes a box from normal flow, so an absolutely positioned child of a flex container is not a flex item at all. Concretely: - It contributes nothing to the main-axis free space, so `justify-content: space-between` distributes space among the remaining, in-flow children only. - `flex-grow`, `flex-shrink`, `flex-basis`, and the `flex` shorthand are inert on it — those properties only apply to flex items. - `order` does nothing, because there is no flex line to be ordered within. - It does not stretch the flex line, so it cannot make its siblings taller. This is exactly what you want for an overlay: a badge on a card, a close button in a corner, a focus ring, a dropdown anchored to a toolbar. ## The part that surprises people: the static position If every inset (`top`, `right`, `bottom`, `left`, or the logical equivalents) is `auto`, the box is placed at its **static position** — where it would have been in flow. CSS Flexbox defines that specifically: the static position of an absolutely positioned child of a flex container is determined as if it were the sole flex item in that container. So the container's alignment properties do still position it: ```css .toolbar { display: flex; justify-content: space-between; position: relative; /* makes this the containing block */ } .toolbar > .badge { position: absolute; align-self: center; /* affects the static position */ } ``` That is why a badge with no offsets can appear centred rather than pinned to the top-left corner, which looks like flex layout "still applying" — it is only the static position being computed by the alignment rules. Set any inset and that axis is resolved from the containing block instead, and the alignment contribution for that axis disappears. ## The containing block trap Offsets resolve against the box's containing block: for `position: absolute`, the **padding box of the nearest ancestor with a position other than `static`** (a transform, filter, or `container-type` can also establish one). Making an element `display: flex` does **not** make it a containing block for absolutely positioned descendants. A `.badge` with `top: 0; right: 0` inside a non-positioned flex container will pin itself to some outer ancestor — often the viewport-sized shell — and appear in the wrong corner entirely. The fix is `position: relative` on the flex container. ## Sizing when insets are set If you specify opposing insets, for example `left: 0; right: 0`, and leave `width: auto`, the box is stretched to span its containing block — the usual absolute-positioning behaviour, unchanged by the parent being a flex container. If only one inset is set, the box is shrink-to-fit sized. None of this involves `flex-basis`, which is another way of saying the flex machinery is genuinely not involved. ## A related detail worth knowing Padding on the flex container does still matter: the static position is computed inside the container's content box, and `position: absolute` offsets resolve against the containing block's **padding** box. So a container with padding places a statically positioned overlay inside the padding and an inset-positioned one at the padding edge — a small inconsistency that explains a stubborn few pixels of difference. Also note that `position: fixed` behaves the same way with respect to flex layout — out of flow, not a flex item — but its containing block is the viewport unless an ancestor has a transform, filter, or similar property that makes it the containing block for fixed descendants. ## How to answer this in an interview Lead with the categorical statement — out of flow, therefore not a flex item, therefore the flex properties and `order` do nothing. Then add the nuance that earns the point: the static position is still computed by the container's alignment properties as if the box were the sole flex item, and the containing block is the nearest positioned ancestor, not automatically the flex container. Those two facts explain nearly every real bug in this area.

  • If the child has no top/left/right/bottom set at all, where does it end up?
    At its static position, which the Flexbox specification defines as the place it would occupy if it were the sole flex item in the container. That means the container's `justify-content` and the child's `align-self` still shift it. Setting any inset overrides the static position for that axis and resolves it against the containing block instead.
  • Does display: flex on the parent make it the containing block for that absolutely positioned child?
    No. The containing block for an absolutely positioned box is the padding box of the nearest ancestor whose position is not `static`, or an ancestor that establishes one through a transform, filter, or similar property. A flex container with `position: static` is skipped, so the offsets resolve against something further up the tree. Add `position: relative`.
  • Does the absolutely positioned child affect the flex line's cross size?
    No. Because it is out of flow it is not measured when the line's cross size is computed, so it cannot make its siblings taller and it is not stretched by `align-items: stretch`. That is the property that makes it useful for overlays: it can be any size without disturbing the layout around it.

saying these in an interview costs you the question

  • Saying flex-grow or order still applies to an absolutely positioned child
  • Assuming display: flex makes the container the containing block
  • Expecting the child to still occupy space in the flex line
  • Believing justify-content is ignored even when no insets are set
  • Thinking align-items: stretch will stretch an out-of-flow child

context