CSS Position

static, relative, absolute, fixed, sticky — when and how to use each

Position Values at a Glance

ValueIn Flow?Positioned Relative ToUse Case
staticYesN/A (default)Normal flow
relativeYesIts own normal positionNudging, anchor for absolutes
absoluteNoClosest positioned ancestorOverlays, tooltips, badges
fixedNoViewportSticky headers, FABs
stickyYes (until stuck)Scroll containerScroll-aware headers, sidebars

position: relative

The element stays in normal flow but can be offset from its original position using top, right, bottom, left. The space it originally occupied is preserved.

.nudged { position: relative; top: -10px; /* moves UP 10px from where it would be */ left: 20px; /* moves RIGHT 20px */ }
Normal
Relative (shifted)
Original spot

Most common use: setting position: relative on a parent so that absolute-positioned children reference it.

position: absolute

Removes the element from document flow. It positions relative to the closest ancestor that has position: relative, absolute, or fixed. If no positioned ancestor exists, it falls back to the viewport.

.parent { position: relative; /* this becomes the reference point */ } .badge { position: absolute; top: -8px; right: -8px; }
Card
3

Golden rule: always pair position: absolute on the child with position: relative on the parent.

position: fixed

Like absolute, but positioned relative to the viewport. It stays in the same spot even when scrolling. Removed from document flow.

.fixed-header { position: fixed; top: 0; left: 0; width: 100%; z-index: 100; }

Use for persistent navigation, floating action buttons, and cookie banners. Remember to add padding or margin to the body so content is not hidden behind the fixed element.

position: sticky

A hybrid: behaves like relative until the user scrolls past a threshold, then it “sticks” like fixed. Unlike fixed, it stays inside its parent — when the parent scrolls out, the sticky element goes with it.

.sticky-nav { position: sticky; top: 0; /* sticks when it reaches the top */ z-index: 10; background: white; }

Gotcha: sticky requires the parent to be taller than the sticky element. It will not work if the parent has overflow: hidden or overflow: auto.

Common Patterns

Overlay / Modal Backdrop

.overlay { position: fixed; inset: 0; /* shorthand for top:0 right:0 bottom:0 left:0 */ background: rgba(0, 0, 0, 0.5); z-index: 999; }

Tooltip Positioned Above Element

.tooltip-wrapper { position: relative; } .tooltip { position: absolute; bottom: 100%; /* sits directly above the wrapper */ left: 50%; transform: translateX(-50%); white-space: nowrap; }

Sticky Table Header

thead th { position: sticky; top: 0; background: white; z-index: 1; }

Frequently Asked Questions

What is the difference between relative and absolute positioning?
relative keeps the element in the document flow and offsets it from its normal spot. absolute removes it from the flow entirely and positions it relative to the nearest positioned ancestor. If no ancestor is positioned, it uses the viewport.
When should I use sticky vs fixed?
Use sticky when you want an element to scroll normally, then stick at a threshold — it stays within its parent. Use fixed when you want the element to always be visible at the same viewport position, regardless of scrolling.
Why is my position absolute not working?
Most likely: the parent does not have position: relative. Without a positioned ancestor, absolute elements reference the viewport. Add position: relative to the parent and make sure you set top/left/right/bottom offsets.

Related Tools