Position Values

ValueIn Flow?Positioned?Relative to
staticYesNoN/A — normal flow
relativeYesYesIts normal position
absoluteNoYesNearest positioned ancestor
fixedNoYesViewport
stickyYes (until threshold)Yes (after threshold)Scroll container

Offset Properties

Only work when position is not static:

/* All four offsets */
top: 0;
right: 0;
bottom: 0;
left: 0;

/* Common patterns */
.overlay { position: fixed; inset: 0; }        /* inset: top right bottom left shorthand */
.badge { position: absolute; top: -8px; right: -8px; }
.sticky-nav { position: sticky; top: 0; }

The Containing Block

An absolute element is positioned relative to its nearest positioned ancestor (position other than static). This is one of the most common sources of confusion in CSS:

/* Pattern: position relative on parent to contain absolute children */
.card {
  position: relative;  /* ← this makes it the containing block */
}
.card .badge {
  position: absolute;
  top: 12px;
  right: 12px;
  /* positions relative to .card, not the page */
}
⚠️ transform creates a containing block too. If an ancestor has any transform applied, even transform: none in some browsers, it becomes the containing block for absolutely positioned descendants — even if it's not position: relative. This can break fixed positioning.

How position: sticky Works

/* Sticks to top of viewport when scrolled to */
.nav {
  position: sticky;
  top: 0;  /* required — defines where it sticks */
  z-index: 100;
}

/* Sticks to bottom (less common) */
.bottom-bar {
  position: sticky;
  bottom: 0;
}

Common reasons sticky doesn't work: