Back to Blog
CSSPositioningLayoutDesign

CSS Positioning Guide

Master CSS positioning with static, relative, absolute, fixed, and sticky positioning.

B
Bootspring Team
Engineering
September 25, 2018
6 min read

CSS positioning controls how elements are placed in the document flow. Here's a comprehensive guide.

Position Static#

1/* Default positioning - normal document flow */ 2.static { 3 position: static; 4 /* top, right, bottom, left have no effect */ 5 /* z-index has no effect */ 6} 7 8/* Element flows normally with siblings */ 9.box { 10 position: static; 11 top: 20px; /* Ignored */ 12 left: 20px; /* Ignored */ 13}

Position Relative#

1/* Positioned relative to its normal position */ 2.relative { 3 position: relative; 4 top: 20px; /* Moves down 20px from normal position */ 5 left: 30px; /* Moves right 30px from normal position */ 6} 7 8/* Original space is preserved */ 9.container { 10 /* Other elements still see .relative in original position */ 11} 12 13/* Creates positioning context for children */ 14.parent { 15 position: relative; 16} 17 18.child { 19 position: absolute; 20 /* Positioned relative to .parent */ 21} 22 23/* Common uses */ 24.badge-container { 25 position: relative; 26} 27 28.badge { 29 position: absolute; 30 top: -10px; 31 right: -10px; 32}

Position Absolute#

1/* Removed from flow, positioned to nearest positioned ancestor */ 2.absolute { 3 position: absolute; 4 top: 0; 5 right: 0; 6} 7 8/* If no positioned ancestor, uses viewport */ 9.no-context { 10 position: absolute; 11 /* Positioned relative to <html> */ 12} 13 14/* Center absolute element */ 15.centered { 16 position: absolute; 17 top: 50%; 18 left: 50%; 19 transform: translate(-50%, -50%); 20} 21 22/* Full width/height */ 23.overlay { 24 position: absolute; 25 inset: 0; /* top: 0; right: 0; bottom: 0; left: 0; */ 26 background: rgba(0, 0, 0, 0.5); 27} 28 29/* Stretch to fill */ 30.stretch { 31 position: absolute; 32 top: 0; 33 bottom: 0; 34 left: 0; 35 right: 0; 36}

Position Fixed#

1/* Positioned relative to viewport, stays on scroll */ 2.fixed { 3 position: fixed; 4 top: 0; 5 left: 0; 6 right: 0; 7} 8 9/* Fixed header */ 10.header { 11 position: fixed; 12 top: 0; 13 left: 0; 14 right: 0; 15 height: 60px; 16 z-index: 100; 17} 18 19/* Account for fixed header */ 20.content { 21 margin-top: 60px; 22} 23 24/* Fixed sidebar */ 25.sidebar { 26 position: fixed; 27 top: 60px; /* Below header */ 28 bottom: 0; 29 left: 0; 30 width: 250px; 31} 32 33/* Back to top button */ 34.back-to-top { 35 position: fixed; 36 bottom: 20px; 37 right: 20px; 38}

Position Sticky#

1/* Hybrid: relative until threshold, then fixed */ 2.sticky { 3 position: sticky; 4 top: 0; 5} 6 7/* Sticky header */ 8.sticky-header { 9 position: sticky; 10 top: 0; 11 background: white; 12 z-index: 10; 13} 14 15/* Sticky with offset */ 16.sticky-nav { 17 position: sticky; 18 top: 60px; /* Below fixed header */ 19} 20 21/* Sticky sidebar */ 22.sidebar { 23 position: sticky; 24 top: 20px; 25 align-self: start; /* Important for flexbox/grid */ 26} 27 28/* Sticky table headers */ 29th { 30 position: sticky; 31 top: 0; 32 background: white; 33} 34 35/* Sticky within scrollable container */ 36.scroll-container { 37 height: 400px; 38 overflow: auto; 39} 40 41.sticky-item { 42 position: sticky; 43 top: 0; 44}

Z-Index#

1/* Stacking order for positioned elements */ 2.behind { 3 position: relative; 4 z-index: 1; 5} 6 7.front { 8 position: relative; 9 z-index: 2; 10} 11 12/* Stacking context */ 13.parent { 14 position: relative; 15 z-index: 1; 16 /* Creates new stacking context */ 17} 18 19.child { 20 position: absolute; 21 z-index: 9999; 22 /* Can't escape parent's stacking context */ 23} 24 25/* Common z-index scale */ 26:root { 27 --z-dropdown: 100; 28 --z-sticky: 200; 29 --z-fixed: 300; 30 --z-modal-backdrop: 400; 31 --z-modal: 500; 32 --z-tooltip: 600; 33} 34 35.modal { 36 z-index: var(--z-modal); 37}

Positioning Context#

1/* Create positioning context for children */ 2.card { 3 position: relative; 4 /* Children with position: absolute will use this */ 5} 6 7.card-badge { 8 position: absolute; 9 top: 10px; 10 right: 10px; 11} 12 13/* Multiple levels */ 14.grandparent { 15 position: relative; 16} 17 18.parent { 19 /* No positioning */ 20} 21 22.child { 23 position: absolute; 24 /* Uses .grandparent, not .parent */ 25} 26 27/* Transform also creates context */ 28.transformed { 29 transform: rotate(0); 30 /* Children positioned relative to this */ 31}

Offset Properties#

1/* Using inset shorthand */ 2.element { 3 position: absolute; 4 inset: 0; /* Same as top: 0; right: 0; bottom: 0; left: 0; */ 5} 6 7.element { 8 inset: 10px; /* All sides */ 9 inset: 10px 20px; /* top/bottom, left/right */ 10 inset: 10px 20px 30px; /* top, left/right, bottom */ 11 inset: 10px 20px 30px 40px; /* top, right, bottom, left */ 12} 13 14/* Logical properties */ 15.element { 16 inset-block: 10px; /* top and bottom */ 17 inset-inline: 20px; /* left and right */ 18 19 inset-block-start: 10px; /* top in LTR */ 20 inset-block-end: 20px; /* bottom in LTR */ 21 inset-inline-start: 30px; /* left in LTR */ 22 inset-inline-end: 40px; /* right in LTR */ 23}

Common Patterns#

1/* Card with overlay */ 2.card { 3 position: relative; 4 overflow: hidden; 5} 6 7.card-overlay { 8 position: absolute; 9 inset: 0; 10 background: rgba(0, 0, 0, 0.5); 11 opacity: 0; 12 transition: opacity 0.3s; 13} 14 15.card:hover .card-overlay { 16 opacity: 1; 17} 18 19/* Aspect ratio container */ 20.aspect-ratio-box { 21 position: relative; 22 width: 100%; 23 padding-top: 56.25%; /* 16:9 */ 24} 25 26.aspect-ratio-content { 27 position: absolute; 28 inset: 0; 29} 30 31/* Icon in input */ 32.input-wrapper { 33 position: relative; 34} 35 36.input-icon { 37 position: absolute; 38 top: 50%; 39 left: 12px; 40 transform: translateY(-50%); 41} 42 43.input-with-icon { 44 padding-left: 40px; 45}
1/* Modal with backdrop */ 2.modal-backdrop { 3 position: fixed; 4 inset: 0; 5 background: rgba(0, 0, 0, 0.5); 6 display: flex; 7 align-items: center; 8 justify-content: center; 9 z-index: 1000; 10} 11 12.modal { 13 position: relative; 14 max-width: 500px; 15 max-height: 90vh; 16 overflow: auto; 17 background: white; 18 border-radius: 8px; 19} 20 21.modal-close { 22 position: absolute; 23 top: 10px; 24 right: 10px; 25}
1/* Dropdown menu */ 2.dropdown { 3 position: relative; 4} 5 6.dropdown-menu { 7 position: absolute; 8 top: 100%; 9 left: 0; 10 min-width: 200px; 11 background: white; 12 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 13 opacity: 0; 14 visibility: hidden; 15 transform: translateY(-10px); 16 transition: all 0.3s; 17} 18 19.dropdown:hover .dropdown-menu, 20.dropdown:focus-within .dropdown-menu { 21 opacity: 1; 22 visibility: visible; 23 transform: translateY(0); 24} 25 26/* Right-aligned dropdown */ 27.dropdown-menu-right { 28 left: auto; 29 right: 0; 30}

Tooltip Pattern#

1/* CSS-only tooltip */ 2.tooltip { 3 position: relative; 4} 5 6.tooltip::after { 7 content: attr(data-tooltip); 8 position: absolute; 9 bottom: 100%; 10 left: 50%; 11 transform: translateX(-50%); 12 padding: 8px 12px; 13 background: #333; 14 color: white; 15 border-radius: 4px; 16 white-space: nowrap; 17 opacity: 0; 18 visibility: hidden; 19 transition: opacity 0.3s; 20 margin-bottom: 8px; 21} 22 23.tooltip:hover::after { 24 opacity: 1; 25 visibility: visible; 26}

Sticky Gotchas#

1/* Sticky needs overflow visible on ancestors */ 2.parent { 3 overflow: hidden; /* Breaks sticky! */ 4} 5 6/* Sticky needs height */ 7.parent { 8 /* Sticky won't work if parent height equals child */ 9} 10 11/* Flexbox/grid needs align-self */ 12.flex-container { 13 display: flex; 14} 15 16.sticky-sidebar { 17 position: sticky; 18 top: 0; 19 align-self: flex-start; /* Required! */ 20}

Best Practices#

Positioning Choice: ✓ relative for positioning context ✓ absolute for overlays/badges ✓ fixed for persistent UI ✓ sticky for scroll-aware elements Z-Index: ✓ Use a scale system ✓ Keep values organized ✓ Understand stacking contexts ✓ Avoid arbitrary large values Performance: ✓ Fixed/sticky create layers ✓ Use transform for animations ✓ will-change for complex cases ✓ Test on mobile Avoid: ✗ Position absolute without context ✗ Magic z-index numbers ✗ Breaking sticky with overflow ✗ Fixed position on mobile keyboards

Conclusion#

CSS positioning gives precise control over element placement. Use relative to create positioning contexts, absolute for overlays and decorations, fixed for persistent headers/modals, and sticky for scroll-aware elements. Master z-index by understanding stacking contexts and using a consistent scale system.

Share this article

Help spread the word about Bootspring