Skip to main content
  • Created:
  • Updated:
  • Author:
    Takeshi Takatsudo

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>
Positioning: relative + absolute (Badge on Card)

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 */
}
Positioning: Fixed Element (Floating Button)

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>
Positioning: Sticky Header (Scroll to See)
.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: absolute for 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: relative on 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: fixed for 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 of top, right, bottom, or left to be set to a non-auto value. Without a threshold, it will not stick.
  • Using z-index without understanding stacking contexts. Setting z-index: 9999 does 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: 0 instead of inset: 0. The inset shorthand 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

References