Where does an element with position: absolute render if you leave top, right, bottom and left at their default value of auto?
answer
- auto is not zero
- where it would have been
- hypothetical flow position
- each axis resolves independently
- position kept, space is not
basics
~20 sIt renders at its static position — the spot where its box would have started in normal flow — but out of flow, so it reserves no space and later siblings move up. Each axis is independent: an auto inset keeps the static position on that axis only.
solid answer
~40 sWith every inset left at `auto`, an absolutely positioned box stays visually where it would have been in normal flow. That location is called its static position: the browser works out where the box would have started had it been in flow, then places the out-of-flow box there. Crucially it is only the *position* that carries over — the box no longer occupies space, so following siblings close up and the parent's height ignores it, and `width: auto` becomes shrink-to-fit. The rule applies per axis, which is what makes it useful: setting `top: 100%` and leaving `left` and `right` auto drops a tooltip below its trigger while keeping it horizontally aligned to where it naturally sat.
code
css · 8 lines.trigger {
position: relative;
}
.trigger .tooltip {
position: absolute;
top: 100%;
}go deeper
Remember that an absolutely positioned element with no offsets does not jump anywhere — it stays where it was, but stops taking up space. That single fact explains most of the confusion around it.
Explain the static position as the hypothetical normal-flow location, note that each axis resolves independently, and connect it to the out-of-flow consequences: shrink-to-fit width and a parent that no longer counts the box.
Use it deliberately — dropdowns and tooltips anchored by top: 100% with auto horizontal insets, and overlays that need to sit exactly where their content already was without hardcoding coordinates.
Frame the tradeoff for a component library: relying on the static position keeps markup order meaningful and avoids magic coordinates, but it couples a component's appearance to its position in the parent's flow, which needs to be a documented contract.
## "auto" does not mean zero The initial value of `top`, `right`, `bottom` and `left` is `auto`, and a common assumption is that `auto` behaves like `0` — that an absolutely positioned element with no insets jumps to the top-left corner of its containing block. It does not. It stays where normal flow would have put it. ## The static position The spec calls this the **static position**: the position the box's edge would have had if its `position` had been `static`, with everything else unchanged. When an inset is `auto`, the used value is derived so that the box lands on that hypothetical edge. So layout proceeds roughly like this: the browser knows where in the parent's flow this box's turn came up, records that point, then takes the box out of flow and places it at the recorded point. Nothing else in the flow accounts for it afterwards. The important word is *position*. Everything else about being out of flow still applies: - The box reserves no space, so the next sibling moves up into where it visually still sits, and the two overlap. - The parent's content height does not include it, so a parent whose only child is absolutely positioned collapses. - `width: auto` switches from fill-the-parent to shrink-to-fit, so the box narrows to its content even though it did not move. That combination is exactly why the pattern is often described as "take it out of flow but leave it where it is" — useful when you want to overlay something on the position it already occupied. ## Per-axis, not all-or-nothing Horizontal and vertical insets resolve independently, and this is where the behaviour earns its keep: ```css .trigger { position: relative; } .trigger .tooltip { position: absolute; top: 100%; /* vertical: measured from the containing block */ /* left and right stay auto: horizontal static position kept */ } ``` The tooltip drops below the trigger vertically while its left edge stays where the box would naturally have started. Add `left: 0` and you have pinned it to the containing block's padding edge instead — which is often the same place, which is why the distinction goes unnoticed until the trigger is not at the start of the line. ## Mixing auto with a value on the same axis On a single axis you can have both, one or neither inset set to a value, and the resolution differs: - **Both `auto`** — static position, as described. - **One value, one `auto`** — the box is placed from the specified edge, and the `auto` side simply falls where the box's size puts it. - **Both values, `width`/`height` auto** — the box stretches between them, filling the containing block minus the insets. ## The related shorthand `inset` is the shorthand that sets all four physical insets at once, following the same one-to-four value pattern as `margin`: `inset: 0` is all four sides, `inset: 0 auto` is a vertical/horizontal pair. Writing `inset: auto` explicitly is the same as leaving them alone. There are flow-relative variants too — `inset-block`, `inset-inline`, and longhands such as `inset-block-start` — which map to physical sides according to the writing mode. ## Where it goes wrong Two failure shapes come up. The first is the overlap surprise: someone adds `position: absolute` to an element to "lift it above" a sibling, sets no insets, and is confused that the sibling now sits underneath it — the box did not move, the sibling did. The second is the collapsed parent: an element that used to give its parent height stops doing so the moment it goes out of flow, and the parent shrinks even though nothing about the child's appearance changed. Both are the same underlying fact stated twice — the static position preserves *where*, never *whether the box counts*. ## Interview framing This is usually asked as a small puzzle: "I set `position: absolute` and nothing moved — is that a bug?" The answer is no, and the reason is the static position; the follow-on question is almost always what the layout around it did instead, which is where the out-of-flow consequences come in.
- Someone adds position: absolute to an element and reports that nothing moved — what do you tell them?That it did move, in the sense that matters: it left the flow. With all insets `auto` the box keeps its static position, so it looks unchanged, but it no longer reserves space. The visible symptoms will be the next sibling sliding up underneath it and the parent losing that much height.
- How does setting left: 0 differ from leaving left at auto when top is already set?`left: 0` measures from the containing block's left padding edge, while `auto` keeps the box at the horizontal static position it would have had in flow. They coincide when the box would have started at the containing block's edge anyway, which is why the difference only shows up for elements that were indented, centred or mid-line.
saying these in an interview costs you the question
- Assumes auto insets behave like top: 0 and left: 0
- Says the element jumps to the containing block's corner
- Thinks keeping its position means keeping its space in flow
- Believes all four insets must be set for absolute positioning to work
- Expects width: auto to still fill the parent once out of flow