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}Modal Pattern#
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}Dropdown Pattern#
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.