Position is one of the fundamental property allowing to layout content. By default, HTML elements position and order follow the flow of how they are written in the document. However, CSS position allow to override this, move elements based on their original position, and even to move out of the flow elements, fix them in a specific position.
Static & Relative
static is the default — top/right/bottom/left do nothing. relative offsets an element from its natural position while keeping the original space reserved.
Preview index.html style.css
< div class = "sr-demo" >
< div class = "col" >
< div class = "col-label" >position: static (default)</ div >
< div class = "box b-static" >Box A</ div >
< div class = "box b-flow" >Box B</ div >
< p class = "note" >top/left have no effect</ p >
</ div >
< div class = "col" >
< div class = "col-label" >position: relative</ div >
< div class = "box b-relative" >Box A</ div >
< div class = "box b-flow" >Box B</ div >
< p class = "note" >Box A: top:-12px; left:12px< br >Original space is kept</ p >
</ div >
</ div > .sr-demo {
display : flex ;
gap : 2 rem ;
flex-wrap : wrap ;
}
.col {
flex : 1 ;
min-width : 140 px ;
}
.col-label {
font-size : .7 rem ;
font-weight : 600 ;
text-transform : uppercase ;
letter-spacing : .05 em ;
color : #94a3b8 ;
margin-bottom : 1.5 rem ;
}
.box {
width : 80 px ;
height : 40 px ;
border-radius : 6 px ;
display : flex ;
align-items : center ;
justify-content : center ;
font-size : .75 rem ;
font-weight : 600 ;
color : white ;
font-family : monospace ;
}
.b-static {
background : #a5b4fc ;
position : static ;
}
.b-flow {
background : #e0e7ff ;
color : #1e1b4b ;
}
.b-relative {
background : #6366f1 ;
position : relative ;
top : -12 px ;
left : 12 px ;
}
.b-placeholder {
background : #e0e7ff ;
border : 2 px dashed #a5b4fc ;
color : #6366f1 ;
}
.note {
font-size : .7 rem ;
color : #94a3b8 ;
margin-top : .5 rem ;
}
/* static — default, no special positioning */
.box { position : static ; } /* top/right/bottom/left have no effect */
/* relative — shift from normal position, original space kept */
.box {
position : relative ;
top : -12 px ; /* moves up */
left : 12 px ; /* moves right */
}
/* relative also creates a positioning context for absolute children */
.parent { position : relative ; }
Absolute
Removed from normal flow, placed relative to its nearest non-static ancestor. If no such ancestor exists, it positions relative to the viewport.
Preview index.html style.css
< div class = "abs-parent" >
< span class = "parent-label" >position: relative</ span >
< div class = "abs-child c-tr" >top:8 right:8</ div >
< div class = "abs-child c-bl" >bottom:8 left:8</ div >
< div class = "abs-child c-center" >centered</ div >
</ div > .abs-parent {
position : relative ;
width : 100 % ; height : 200 px ;
background : #f1f5f9 ;
border : 2 px dashed #cbd5e1 ;
border-radius : 8 px ;
}
.parent-label {
padding : .5 rem ;
font-size : .7 rem ;
color : #94a3b8 ;
font-family : monospace ;
}
.abs-child {
position : absolute ;
background : #6366f1 ; color : white ;
padding : .35 rem .75 rem ; border-radius : 6 px ;
font-size : .75 rem ; font-family : monospace ;
}
.c-tr { top : 8 px ; right : 8 px ; }
.c-bl { bottom : 8 px ; left : 8 px ; }
.c-center {
top : 50 % ; left : 50 % ;
transform : translate ( -50 % , -50 % );
}
.parent {
position : relative ; /* creates the positioning context */
width : 400 px ;
height : 200 px ;
}
.child {
position : absolute ;
top : 0 ;
right : 0 ; /* top-right corner of parent */
}
/* centering trick with absolute + transform */
.centered {
position : absolute ;
top : 50 % ;
left : 50 % ;
transform : translate ( -50 % , -50 % );
}
Fixed
Positioned relative to the viewport . Stays in place as you scroll — ideal for navbars, overlays, and floating buttons.
Preview index.html style.css
< div class = "fixed-demo" >
< div class = "fixed-mock" >
position: fixed navbar (simulated)
</ div >
< div class = "fixed-content" >
< p >Scroll content line 1 — navbar stays fixed</ p >
< p >Scroll content line 2 — navbar stays fixed</ p >
< p >Scroll content line 3 — navbar stays fixed</ p >
< p >Scroll content line 4 — navbar stays fixed</ p >
< p >Scroll content line 5 — navbar stays fixed</ p >
< p >Scroll content line 6 — navbar stays fixed</ p >
< p >Scroll content line 7 — navbar stays fixed</ p >
< p >Scroll content line 8 — navbar stays fixed</ p >
< p >Scroll content line 9 — navbar stays fixed</ p >
< p >Scroll content line 10 — navbar stays fixed</ p >
< p >Scroll content line 11 — navbar stays fixed</ p >
< p >Scroll content line 12 — navbar stays fixed</ p >
< p >Scroll content line 13 — navbar stays fixed</ p >
< p >Scroll content line 14 — navbar stays fixed</ p >
< p >Scroll content line 15 — navbar stays fixed</ p >
< p >Scroll content line 16 — navbar stays fixed</ p >
</ div >
< div class = "fixed-fab" >+</ div >
</ div > .fixed-demo {
position : relative ; height : 160 px ;
background : #f1f5f9 ; border-radius : 8 px ;
overflow : hidden ;
}
.fixed-mock {
position : absolute ;
left : 0 ; right : 0 ; top : 0 ;
background : #6366f1 ; color : white ;
padding : .5 rem 1 rem ;
font-size : .8 rem ; font-family : monospace ;
z-index : 10 ;
}
.fixed-content {
position : absolute ; /* should be fixed */
inset : 0 ;
padding : 3 rem 1 rem 1 rem ;
font-size : .8 rem ;
color : #64748b ;
overflow-y : auto ;
box-sizing : border-box ;
}
.fixed-fab {
position : absolute ;
bottom : 12 px ; right : 12 px ;
width : 2.5 rem ; height : 2.5 rem ;
background : #6366f1 ; color : white ;
border-radius : 50 % ;
display : flex ; align-items : center ; justify-content : center ;
font-size : 1.2 rem ;
box-shadow : 0 4 px 12 px rgba ( 99 , 102 , 241 , .4 );
}
.navbar {
position : fixed ;
top : 0 ;
left : 0 ;
right : 0 ; /* full width */
z-index : 100 ;
}
.fab {
position : fixed ;
bottom : 24 px ;
right : 24 px ;
}
.overlay {
position : fixed ;
inset : 0 ; /* shorthand for top:0 right:0 bottom:0 left:0 */
background : rgba ( 0 , 0 , 0 , 0.5 );
}
Sticky
Behaves like relative until it reaches the threshold you define — then sticks like fixed. Scroll inside the demo to see it in action.
Preview index.html style.css
< div class = "scroll-area" >
< div class = "sticky-header" >
Sticky header (position: sticky; top: 0)
</ div >
< div class = "item" >Item 1 — scroll down</ div >
< div class = "item" >Item 2 — scroll down</ div >
< div class = "item" >Item 3 — scroll down</ div >
< div class = "item" >Item 4 — scroll down</ div >
< div class = "item" >Item 5 — scroll down</ div >
< div class = "item" >Item 6 — scroll down</ div >
< div class = "item" >Item 7 — scroll down</ div >
< div class = "item" >Item 8 — scroll down</ div >
< div class = "item" >Item 9 — scroll down</ div >
< div class = "item" >Item 10 — scroll down</ div >
< div class = "item" >Item 11 — scroll down</ div >
< div class = "item" >Item 12 — scroll down</ div >
</ div > .scroll-area {
height : 240 px ;
overflow-y : auto ;
border : 1 px solid #e2e8f0 ;
border-radius : 8 px ;
}
.sticky-header {
position : sticky ;
top : 0 ;
z-index : 1 ;
background : #6366f1 ; color : white ;
padding : .6 rem 1 rem ; font-weight : 600 ;
}
.item {
padding : .75 rem 1 rem ;
border-bottom : 1 px solid #f1f5f9 ;
}
Z-index & Stacking
z-index controls the stacking order. Higher numbers are on top. Each positioned element creates a stacking context — z-index is relative within it.
Preview index.html style.css
< div class = "stack" >
< div class = "layer l1" >z-index: 1</ div >
< div class = "layer l2" >z-index: 2</ div >
< div class = "layer l3" >z-index: 3</ div >
</ div > .stack {
position : relative ;
width : 200 px ; height : 140 px ;
}
.layer {
position : absolute ;
width : 120 px ; height : 80 px ;
border-radius : 8 px ;
display : flex ; align-items : center ; justify-content : center ;
font-weight : 600 ; font-size : .875 rem ;
}
.l1 {
background : #bfdbfe ;
top : 0 ; left : 0 ;
z-index : 1 ;
}
.l2 {
background : #a5f3fc ;
top : 60 px ; left : 60 px ;
z-index : 2 ;
}
.l3 {
background : #bbf7d0 ;
top : 120 px ; left : 120 px ;
z-index : 3 ;
}
/* z-index only works on positioned elements (not static) */
.tooltip { position : absolute ; z-index : 500 ; }
.modal { position : fixed ; z-index : 1000 ; }
.overlay { position : fixed ; z-index : 900 ; }
/* common z-index scale */
--z-base: 1;
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 30;
--z-modal: 40;
--z-toast: 50;