Positioning
The position property — static, relative, absolute, fixed, and sticky — and how each changes an element's flow.
2 min de lectura
position controls how an element is placed relative to the normal document flow, and it's a common source of confusion because each value behaves fundamentally differently, not just as variations on a theme.
static: the default
.box {
position: static;
}Every element is position: static unless you say otherwise. Static elements sit exactly where normal document flow puts them, and the top/left/right/bottom properties have no effect on them at all.
relative: nudged, but still in flow
.badge {
position: relative;
top: -4px;
left: 4px;
}position: relative lets you nudge an element from where it would normally sit, using top/left/right/bottom as offsets — but the space it originally occupied in the layout is preserved, so other elements don't move to fill the gap. Its other major role is creating a positioning context: it becomes the reference point for any absolutely positioned child.
absolute: out of flow, positioned against an ancestor
.card {
position: relative;
}
.card .close-button {
position: absolute;
top: 8px;
right: 8px;
}<div class="card">
<button class="close-button">✕</button>
<p>Card content...</p>
</div>position: absolute removes an element from normal flow entirely — other elements act as if it isn't there — and positions it relative to the nearest ancestor that has position set to anything other than static (here, .card's relative). This relative parent + absolute child pattern is extremely common: a close button pinned to a card's corner, a badge on an icon, a dropdown anchored to its trigger.
fixed: pinned to the viewport
.toast {
position: fixed;
bottom: 24px;
right: 24px;
}position: fixed positions relative to the browser viewport itself, and stays in that exact spot even as the page scrolls — the standard technique for a persistent notification, a floating action button, or a header that stays visible.
sticky: relative until it isn't
.section-heading {
position: sticky;
top: 0;
background: white;
}position: sticky behaves like relative until the element would scroll past a threshold (top: 0 here), at which point it "sticks" and behaves like fixed — until its parent container scrolls out of view, at which point it unsticks. It's the mechanism behind sticky table headers and sticky section labels, and it requires no JavaScript scroll listeners at all.
Layering with z-index
.modal-overlay {
position: fixed;
inset: 0;
z-index: 100;
}When positioned elements overlap, z-index decides which one renders on top — higher values win, but only among elements that are already positioned (z-index has no effect on static elements). inset: 0 is shorthand for top: 0; right: 0; bottom: 0; left: 0;, a common way to make a positioned element fill its container exactly.