CSS Positioning Basics

Understanding how to position elements with static, relative, absolute, fixed, and sticky positioning

CSS Positioning Basics

CSS positioning defines how elements are placed within a web page. Understanding positioning is essential for creating complex layouts, overlays, navigation bars, and precisely placed elements.

Every element has a position property that controls how it's positioned in the document flow.

Position Types Overview

PositionDescription
staticDefault positioning, follows normal document flow
relativePositioned relative to its normal position
absolutePositioned relative to closest positioned ancestor
fixedPositioned relative to viewport, stays in place when scrolling
stickyRelative until scroll threshold, then becomes fixed

Static Positioning

Static is the default position for all elements. Elements appear in the normal document flow, one after another.

<!DOCTYPE html>
<html>
<head>
<style>
div {
    border: 1px solid black;
    padding: 10px;
    margin: 10px;
    background-color: lightblue;
}
</style>
</head>
<body>
    <div>Box 1</div>
    <div>Box 2</div>
    <div>Box 3</div>
</body>
</html>
Static positioning example

Key characteristics:

  • Elements stack vertically (for block elements) or horizontally (for inline elements)
  • top, right, bottom, left properties have no effect
  • This is how elements behave by default

You rarely need to explicitly set position: static since it's the default.

Relative Positioning

Relative positioning moves an element relative to where it would normally appear, without affecting the layout of surrounding elements.

<!DOCTYPE html>
<html>
<head>
<style>
div {
    border: 1px solid black;
    padding: 10px;
    margin: 10px;
    background-color: lightblue;
}

.relative {
    position: relative;
    top: 20px;
    left: 30px;
    background-color: lightcoral;
}
</style>
</head>
<body>
    <div>Box 1</div>
    <div class="relative">Box 2 (Relative)</div>
    <div>Box 3</div>
</body>
</html>
Relative positioning example

Box 2 is shifted 20px down and 30px right from its normal position.

Important details:

  • The element's original space is preserved in the layout
  • Other elements don't move to fill the gap
  • The element appears shifted visually, but the layout acts as if it's still in its original position
  • Uses top, right, bottom, left to shift position

Offset properties:

  • top: 20px - Moves element 20px down
  • left: 30px - Moves element 30px to the right
  • bottom: 10px - Moves element 10px up
  • right: 15px - Moves element 15px to the left

Common use case: Slightly adjusting element positions without disrupting layout.

Absolute Positioning

Absolute positioning removes the element from the normal document flow and positions it relative to its closest positioned ancestor (any parent with position other than static).

<!DOCTYPE html>
<html>
<head>
<style>
.container {
    position: relative;
    width: 300px;
    height: 200px;
    border: 2px solid black;
    margin: 20px auto;
    background-color: lightgray;
}

.absolute {
    position: absolute;
    top: 50px;
    left: 50px;
    background-color: pink;
    padding: 10px;
    border: 1px solid red;
}
</style>
</head>
<body>
    <div class="container">
        <p>Container with Relative Positioning</p>
        <div class="absolute">Absolutely Positioned Element</div>
    </div>
</body>
</html>
Absolute positioning example

The pink box is positioned 50px from the top and 50px from the left of the .container element.

Key characteristics:

  • Element is removed from document flow - other elements act as if it doesn't exist
  • No space is reserved for it in the layout
  • Positioned relative to the nearest ancestor with position: relative, absolute, fixed, or sticky
  • If no positioned ancestor exists, it's positioned relative to the <body>

Common pattern - Positioned parent:

.parent {
    position: relative;  /* Creates positioning context */
}

.child {
    position: absolute;  /* Positioned within parent */
    top: 0;
    right: 0;
}

This is the most common pattern - set a parent to position: relative (which doesn't move it) to create a positioning context for absolute children.

Use cases:

  • Tooltips and dropdowns
  • Overlays and modals
  • Icons positioned within containers
  • Image badges or labels

Fixed Positioning

Fixed positioning removes the element from the document flow and positions it relative to the viewport (browser window). It stays in place even when scrolling.

<!DOCTYPE html>
<html>
<head>
<style>
.fixed {
    position: fixed;
    top: 10px;
    right: 10px;
    background-color: lightgreen;
    padding: 20px;
    border: 2px solid black;
    z-index: 1000;
}

.content {
    height: 2000px;
    padding: 20px;
}
</style>
</head>
<body>
    <div class="fixed">Fixed Box - Scroll to see me stay!</div>
    <div class="content">
        <h2>Fixed Positioning Example</h2>
        <p>Scroll down and notice the green box stays in the same viewport position.</p>
        <p>This content simulates a long page...</p>
    </div>
</body>
</html>

Key characteristics:

  • Always positioned relative to the viewport, not any parent element
  • Stays in place while scrolling
  • Removed from document flow (no space reserved)
  • top, right, bottom, left are relative to the viewport edges

Common use cases:

  • Navigation bars that stay visible while scrolling
  • "Back to top" buttons
  • Chat widgets
  • Cookie consent banners
  • Floating action buttons

Important note: Fixed elements are positioned relative to the viewport, so position: relative on a parent has no effect.

Sticky Positioning

Sticky positioning is a hybrid between relative and fixed. The element behaves as relative until you scroll to a specified threshold, then it becomes fixed.

<!DOCTYPE html>
<html>
<head>
<style>
.spacer {
    height: 300px;
    background: lightgray;
    padding: 20px;
}

.sticky {
    position: sticky;
    top: 10px;
    background: yellow;
    padding: 10px;
    border: 2px solid orange;
}
</style>
</head>
<body>
    <div class="spacer">
        <h2>Scroll down to see sticky behavior</h2>
        <p>The yellow box below will stick when it reaches 10px from the top of the viewport.</p>
    </div>

    <div class="sticky">I become sticky when you scroll!</div>

    <div class="spacer">
        <p>Keep scrolling...</p>
        <p>The sticky element stays fixed at the top until you scroll back up or reach the end of its container.</p>
    </div>
</body>
</html>

How it works:

  1. Element scrolls normally (like relative) until...
  2. It reaches the specified threshold (top: 10px)
  3. Then it "sticks" in place (like fixed)
  4. When you scroll back up, it unsticks and returns to relative behavior

Key characteristics:

  • Switches between relative and fixed behavior based on scroll position
  • Must specify at least one of: top, right, bottom, or left
  • Sticks within its parent container only (won't stick beyond parent's boundaries)
  • Maintains its space in the document flow

Common use cases:

  • Table headers that stick while scrolling table data
  • Section headings in long articles
  • Navigation menus that stick after scrolling past the hero section
  • Sidebar elements that stick until you reach the end of content

The z-index Property

When elements overlap (common with absolute, fixed, or relative positioning), z-index controls which element appears on top.

<!DOCTYPE html>
<html>
<head>
<style>
.box {
    width: 100px;
    height: 100px;
    position: absolute;
    border: 2px solid black;
}

.box1 {
    background-color: red;
    top: 50px;
    left: 50px;
    z-index: 1;
}

.box2 {
    background-color: blue;
    top: 80px;
    left: 80px;
    z-index: 2;
}

.box3 {
    background-color: green;
    top: 110px;
    left: 110px;
    z-index: 3;
}
</style>
</head>
<body>
    <div class="box box1">Z: 1</div>
    <div class="box box2">Z: 2</div>
    <div class="box box3">Z: 3</div>
</body>
</html>

How z-index works:

  • Higher numbers appear on top
  • Only works on positioned elements (not static)
  • Negative values are allowed
  • Default value is auto (order depends on HTML structure)

Common z-index values:

.modal-backdrop { z-index: 1000; }
.modal { z-index: 1001; }
.dropdown { z-index: 100; }
.navbar { z-index: 10; }

Positioning Offset Properties

All positioned elements (except static) can use these properties:

.positioned {
    position: absolute;
    top: 20px;     /* Distance from top edge */
    right: 30px;   /* Distance from right edge */
    bottom: 10px;  /* Distance from bottom edge */
    left: 15px;    /* Distance from left edge */
}

Important rules:

  • top and bottom can conflict - typically use one or the other
  • left and right can conflict - typically use one or the other
  • Values can be px, %, em, rem, etc.
  • Negative values pull the element in the opposite direction

Centering with Absolute Positioning

A common pattern for centering absolutely positioned elements:

<!DOCTYPE html>
<html>
<head>
<style>
.container {
    position: relative;
    width: 400px;
    height: 300px;
    border: 2px solid black;
    background-color: lightgray;
}

.centered {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: white;
    padding: 20px;
    border: 1px solid black;
}
</style>
</head>
<body>
    <div class="container">
        <div class="centered">Perfectly Centered!</div>
    </div>
</body>
</html>

How this works:

  • top: 50%; left: 50% positions the top-left corner at the center
  • transform: translate(-50%, -50%) shifts the element back by half its own width and height
  • Result: the element's center aligns with the container's center

Quick Reference

PositionDocument FlowPositioned Relative ToScrolls?
staticIn flowNormal positionYes
relativeIn flowIts normal positionYes
absoluteOut of flowNearest positioned ancestorYes
fixedOut of flowViewportNo
stickyIn flowVaries (relative → fixed)Varies

Best Practices

Use relative for small adjustments:

.icon {
    position: relative;
    top: 2px;  /* Slight vertical alignment */
}

Use absolute for overlays:

.badge {
    position: absolute;
    top: -5px;
    right: -5px;
}

Use fixed for persistent UI:

.navbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
}

Use sticky for scrolling context:

.table-header {
    position: sticky;
    top: 0;
}

Always set a positioning context: When using absolute, set the parent to position: relative to control where the element is positioned:

.parent {
    position: relative;  /* Positioning context */
}

.child {
    position: absolute;  /* Positioned within parent */
}

Consider z-index hierarchy: Plan your z-index values to avoid conflicts. Use a scale like 10, 100, 1000 to leave room for adjustments.