Positioning Guide
The Problem
CSS positioning is frequently misused by AI agents. The most common errors include using position: absolute for layout tasks that should use flexbox or grid, forgetting to set position: relative on the containing element, using position: fixed without considering mobile viewport issues, and failing to understand that position: sticky requires a scroll container and a threshold value.
The Solution
CSS position removes or adjusts elements relative to their normal document flow. Each value serves a specific purpose, and choosing the wrong one creates fragile layouts that break across screen sizes.
Code Examples
static (Default)
Elements are in the normal document flow. The top, right, bottom, left, and z-index properties have no effect.
.element {
position: static; /* default, rarely needs to be written explicitly */
}
relative
The element stays in the normal flow but can be offset from its original position. It creates a containing block for absolutely positioned children.
.parent {
position: relative; /* Establishes containing block for children */
}
.badge {
position: relative;
top: -4px; /* Shifts up 4px from its normal position */
}
Use position: relative primarily to establish a containing block for position: absolute children, or for minor visual offsets without affecting layout.
absolute
The element is removed from the document flow and positioned relative to its nearest positioned ancestor (any ancestor with position other than static).
.card {
position: relative; /* Containing block */
}
.card-badge {
position: absolute;
top: -8px;
right: -8px;
}
<div class="card">
<span class="card-badge">New</span>
<p>Card content</p>
</div>
Absolute Centering with inset
The inset shorthand replaces top, right, bottom, left.
.overlay {
position: absolute;
inset: 0; /* top: 0; right: 0; bottom: 0; left: 0 */
}
.modal {
position: absolute;
inset: 0;
margin: auto;
width: fit-content;
height: fit-content;
}
fixed
The element is removed from the document flow and positioned relative to the viewport. It does not move when the page scrolls.
.sticky-header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
/* Prevent content from being hidden behind the fixed header */
body {
padding-top: 60px; /* Match the header height */
}
sticky
The element acts as relative until it crosses a scroll threshold, then behaves as fixed within its containing block.
.table-header {
position: sticky;
top: 0;
background: white;
z-index: 10;
}
<table>
<thead>
<tr class="table-header">
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<!-- rows -->
</tbody>
</table>
Sticky Sidebar
.page {
display: flex;
align-items: flex-start; /* Critical: prevents sidebar from stretching */
}
.sidebar {
position: sticky;
top: 1rem;
width: 250px;
flex-shrink: 0;
}
.main-content {
flex: 1;
min-width: 0;
}
<div class="page">
<aside class="sidebar">Sticky sidebar</aside>
<main class="main-content">Scrollable content</main>
</div>
Why position: sticky Fails
Sticky positioning fails silently in several situations:
No threshold set
/* Broken: no top, bottom, left, or right value */
.sticky-broken {
position: sticky;
}
/* Fixed: threshold tells the browser when to stick */
.sticky-working {
position: sticky;
top: 0;
}
Parent has overflow: hidden or overflow: auto
/* Broken: overflow on parent prevents sticking */
.parent {
overflow: hidden; /* or overflow: auto, overflow: scroll */
}
.parent .sticky-child {
position: sticky;
top: 0;
/* This will not stick */
}
Parent has no scrollable height
The sticky element sticks within its parent. If the parent is only as tall as the sticky element itself, there is nothing to scroll within.
Common AI Mistakes
- Using
position: absolutefor layout. Absolute positioning removes elements from the flow, making layouts fragile. Use flexbox or grid for layout, and reserve absolute positioning for overlays, badges, and decorative elements. - Forgetting
position: relativeon the parent. Without a positioned ancestor, absolutely positioned elements are positioned relative to the initial containing block (typically the viewport), not the intended parent. - Using
position: fixedfor sticky headers on mobile. Fixed positioning on mobile can cause issues with virtual keyboards, address bar resizing, and scroll performance. Test on actual mobile devices. - Not setting a threshold on
position: sticky. A sticky element requires at least one oftop,right,bottom, orleftto be set to a non-auto value. Without a threshold, it will not stick. - Using
z-indexwithout understanding stacking contexts. Settingz-index: 9999does not guarantee an element appears on top. It only controls stacking within the same stacking context. See the Stacking Context guide for details. - Using
top: 0; right: 0; bottom: 0; left: 0instead ofinset: 0. Theinsetshorthand is more concise and readable. - Using absolute positioning with percentage widths for responsive design. Absolutely positioned elements are sized relative to their containing block, not the viewport. This breaks when the containing block changes size unexpectedly.
When to Use
relative
- Establishing a containing block for absolutely positioned children
- Minor visual offsets without affecting layout
- Creating a stacking context (when combined with z-index)
absolute
- Badges, labels, close buttons on cards or modals
- Overlay elements that sit on top of a positioned container
- Tooltip arrows and popovers
- Decorative elements that should not affect document flow
fixed
- Navigation bars that remain visible during scrolling
- "Back to top" buttons
- Cookie consent banners
- Floating action buttons
sticky
- Table headers that stay visible while scrolling the table
- Section headers in long scrollable lists
- Sidebars that follow the user within their container
- "Add to cart" bars on product pages