Position Absolute vs Relative in CSS

By Marko Denic
Contents
  1. position: relative
  2. position: absolute
  3. Relative parent, absolute child
  4. Absolute vs relative at a glance
  5. All CSS position values
  6. position: static
  7. position: fixed
  8. position: sticky
  9. Sticky header with CSS
  10. Why is position: sticky not working?
  11. FAQ

position: relative moves an element relative to where it would normally be, and the space it took up stays reserved. position: absolute takes the element out of the page flow and places it relative to its nearest positioned ancestor: the closest parent whose position is anything other than static. If there is none, it’s placed relative to the page.

Demo:

static
relativetop: 16px; left: 24px;
static
absolutebottom: 12px; right: 12px;

The dashed outline is where the relative box would normally be. It moved, but its space is still kept, so the static box below doesn’t move up. The absolute box takes up no space at all: it’s pinned to the corner of .pos-demo, the nearest parent with position: relative.

position: relative

The element stays in the normal flow. top, right, bottom and left shift it visually from its original spot, and nothing around it moves. Without offsets it looks exactly like a static element, but it now works as the positioning context for absolutely positioned children, and z-index applies to it.

css
.box {
  position: relative;
  top: 10px;  /* 10px down from its normal spot */
  left: 20px; /* 20px to the right */
}

position: absolute

The element is removed from the flow: other elements act as if it isn’t there, and it shrinks to fit its content. Its offsets are measured from the edges of the nearest positioned ancestor.

css
.box {
  position: absolute;
  top: 0;
  right: 0; /* top-right corner of the nearest positioned ancestor */
}

Relative parent, absolute child

This is how you’ll use them together most of the time: position: relative on the parent creates the positioning context, and position: absolute on the child places it inside that parent. Badges, tooltips, close buttons, icons inside inputs and image overlays all work this way.

css
.avatar {
  position: relative; /* the positioning context */
}

.avatar__badge {
  position: absolute;
  top: -4px;
  right: -4px; /* pinned to the avatar's top-right corner */
}

Absolute vs relative at a glance

relative absolute
Stays in the page flow Yes No
Keeps its original space Yes No
Offsets are measured from Its own normal position The nearest positioned ancestor
Width Same as a static element Shrinks to fit its content
Typical use Small nudges, a context for absolute children Badges, tooltips, overlays, icons

All CSS position values

The position property has five values. relative and absolute are covered above; here are the other three.

Value In the page flow Positioned relative to
static (default) Yes Not positioned; offsets are ignored
relative Yes Its own normal position
absolute No The nearest positioned ancestor
fixed No The browser window (viewport)
sticky Yes Its scroll container, once you scroll past the threshold

position: static

The default for every element. It sits in the normal flow, and top, right, bottom, left and z-index have no effect. You only write it to undo another position value.

css
.box {
  position: static; /* default: offsets are ignored */
}

position: fixed

Like absolute, the element is removed from the flow, but it’s positioned relative to the browser window, so it stays in place while the page scrolls. Chat buttons, cookie banners and “back to top” buttons use it.

Gotcha: if any ancestor has a transform, filter or perspective, the fixed element is positioned relative to that ancestor instead of the window.

css
.chat-button {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 100;
}

position: sticky

A sticky element behaves like relative until you scroll it to a threshold, like top: 0. Then it sticks there, like fixed, until its parent scrolls out of view. Unlike fixed, it keeps its space in the layout, so nothing jumps. Scroll the demo below: each letter sticks until the next section pushes it away.

css
.section-title {
  position: sticky;
  top: 0; /* required: where it sticks */
}

Demo:

A

Alice

Amir

Anna

Arturo

B

Bea

Ben

Bogdan

Bruno

C

Carla

Chen

Chloe

Cyrus

Sticky header with CSS

The most common use of sticky: a header that stays at the top while the page scrolls. With fixed, you’d have to add padding to the page so the header doesn’t cover the content; sticky keeps its space, so you don’t.

css
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;       /* stays above the content scrolling under it */
  background: #fff;  /* otherwise content shows through */
}

Why is position: sticky not working?

  • No threshold. Sticky needs top, bottom, left or right. Without one, it never sticks.
  • An ancestor has overflow set. overflow: hidden, auto or scroll on any parent makes that parent the scroll container, so the element sticks inside it, often invisibly. Look for it on wrappers.
  • The parent is too short. A sticky element can’t leave its parent. If the parent is only as tall as the sticky element, there’s no room to stick.
  • It’s stretched in a flex or grid container. Items stretch to the container’s height by default, so there’s nothing left to scroll. Add align-self: flex-start (or start in grid).

FAQ

Why is my absolute element positioned relative to the whole page?

None of its parents is positioned. Add position: relative to the parent you want it placed inside.

Does position: relative do anything without top or left?

Nothing you can see. It still makes the element a positioning context for absolute children and lets z-index work on it.

How do I center an absolutely positioned element?

Use inset: 0; margin: auto; with a set width and height, or top: 50%; left: 50%; transform: translate(-50%, -50%);. See how to center a div for all the options.

What is the default position in CSS?

static. Every element starts as static, which is why top, left and z-index do nothing until you change it.

What’s the difference between position fixed and sticky?

fixed is always positioned relative to the window and takes no space in the layout. sticky stays in the flow and only sticks while its parent is on screen.

Is position: absolute bad for responsive layouts?

For whole page layouts, yes: use flexbox or grid instead. For small decorative or overlay elements inside a component, it’s the right tool.

Related: animated border (an absolutely positioned pseudo-element), CSS glass effect, , CSS flexbox, CSS calc() and CSS tips you won’t see in most tutorials.