Position Absolute vs Relative in CSS
Contents
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:
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.
.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.
.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.
.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.
.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.
.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.
.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.
.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,leftorright. Without one, it never sticks. - An ancestor has
overflowset.overflow: hidden,autoorscrollon 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(orstartin 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.