Absolute & Fixed

Difficulty: Intermediate

position: absolute and position: fixed both remove an element from the normal document flow, meaning surrounding elements behave as if the positioned element does not exist. The key difference lies in their reference point: absolute positions relative to the nearest positioned ancestor, while fixed positions relative to the viewport (the browser window). This distinction has profound implications for layout behavior.

An absolutely positioned element searches up the DOM tree for the nearest ancestor with a position value other than static (i.e., relative, absolute, fixed, or sticky). That ancestor becomes its containing block, and the top, right, bottom, left offsets are measured from that ancestor's padding box. If no positioned ancestor exists, the element positions relative to the initial containing block (the <html> element, which is essentially the full document). This ancestor-search behavior is why position: relative is so commonly used on parent elements.

position: fixed removes the element from the flow and positions it relative to the viewport. No matter how the page scrolls, a fixed element stays in the same position on the screen. This makes it ideal for sticky headers, floating action buttons, cookie consent banners, and modal overlays. Fixed elements ignore all ancestor positioning - they always reference the viewport, with one exception: if an ancestor has a transform, filter, or perspective property, that ancestor becomes the containing block instead of the viewport.

Both absolute and fixed elements can be sized using offsets. Setting top: 0; right: 0; bottom: 0; left: 0 on an absolute element stretches it to fill its containing block entirely. This technique is commonly used for overlay effects, full-coverage backgrounds, and centering with margin: auto. For centering, combine all four offsets at 0, set explicit width and height, and add margin: auto - the browser calculates equal margins on all sides.

The key practical difference in scrolling: absolutely positioned elements scroll with the document (they are part of the document, just positioned within it). Fixed elements do not scroll - they are anchored to the viewport. If you need an element that scrolls with the page but is positioned within a container, use absolute. If you need an element that stays visible regardless of scrolling, use fixed.

Code examples

Absolute Positioning Basics

<style>
  .parent {
    position: relative;
    width: 400px;
    height: 250px;
    background: #f8fafc;
    border: 2px solid #e2e8f0;
    margin: 20px;
  }
  .child-tl {
    position: absolute;
    top: 10px;
    left: 10px;
    background: #3b82f6;
    color: white;
    padding: 8px 16px;
  }
  .child-br {
    position: absolute;
    bottom: 10px;
    right: 10px;
    background: #ef4444;
    color: white;
    padding: 8px 16px;
  }
  .child-center {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    margin: auto;
    width: 120px;
    height: 40px;
    background: #10b981;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
  }
</style>

<div class="parent">
  <div class="child-tl">Top Left</div>
  <div class="child-center">Centered</div>
  <div class="child-br">Bottom Right</div>
</div>

All three children are absolutely positioned within the relative parent. Top-left and bottom-right use corner offsets. The centered element uses the top:0;right:0;bottom:0;left:0;margin:auto technique for perfect centering.

Fixed Position Elements

<style>
  .fixed-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: white;
    border-bottom: 1px solid #e2e8f0;
    display: flex;
    align-items: center;
    padding: 0 20px;
    z-index: 100;
  }
  .fab {
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: #3b82f6;
    color: white;
    border: none;
    font-size: 24px;
    cursor: pointer;
    z-index: 100;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
  .content {
    margin-top: 80px; /* Offset for fixed header */
    padding: 20px;
  }
</style>

<div class="fixed-header">
  <strong>Fixed Header</strong>
</div>
<div class="content">
  <p>Scroll down to see fixed elements stay in place...</p>
  <!-- Long content -->
</div>
<button class="fab">+</button>

The header is fixed to the top of the viewport. The FAB button is fixed to the bottom-right. Both stay visible during scrolling. Content needs margin-top to prevent the fixed header from overlapping it.

Containing Block Lookup

<style>
  .outer {
    position: relative;
    width: 400px;
    height: 300px;
    background: #dbeafe;
    padding: 20px;
    margin: 20px;
  }
  .middle {
    /* No position set (static by default) */
    width: 300px;
    height: 200px;
    background: #fef3c7;
    padding: 20px;
    margin: 20px;
  }
  .inner {
    position: absolute;
    bottom: 10px;
    right: 10px;
    background: #ef4444;
    color: white;
    padding: 8px 16px;
  }
</style>

<div class="outer">
  OUTER (position: relative)
  <div class="middle">
    MIDDLE (position: static)
    <div class="inner">
      INNER (absolute)
    </div>
  </div>
</div>

<!-- INNER skips MIDDLE (static) and positions
     relative to OUTER (the nearest positioned ancestor) -->

The inner element is absolute. It skips the middle div (which is static) and positions relative to the outer div (which has position: relative). If the outer div also lacked positioning, the inner would position relative to the html element.

Full-Screen Overlay with Absolute

<style>
  .modal-container {
    position: relative;
  }
  .overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
  }
  .modal {
    background: white;
    padding: 32px;
    border-radius: 12px;
    width: 90%;
    max-width: 500px;
    position: relative;
  }
  .close-btn {
    position: absolute;
    top: 12px;
    right: 12px;
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
  }
</style>

<div class="overlay">
  <div class="modal">
    <button class="close-btn">&times;</button>
    <h2>Modal Title</h2>
    <p>This overlay uses position: fixed to cover the viewport.
       The close button uses position: absolute within the modal.</p>
  </div>
</div>

The overlay uses position: fixed with all four offsets set to 0, covering the entire viewport. The modal inside is centered using flexbox on the overlay. The close button uses position: absolute within the modal (which has position: relative).

Key points

Concepts covered

position: absolute, position: fixed, Containing Block, Viewport Positioning, Removed from Flow