CSS Reference Guide

All TopicsPlayground

Display & Positioning

Understand how CSS determines where elements appear on the page — from normal document flow through every positioning scheme to z-index stacking contexts and overflow control.

LayoutDisplayPositionz-indexOverflowCentering

Normal Flow

Before any positioning is applied, the browser lays out elements according to normal flow. There are two key behaviors:

CSS
/* Block elements (default display: block) */
div, p, h1, section, article, header, footer, main, nav, ul, ol

/* Inline elements (default display: inline) */
span, a, strong, em, code, img, br, input
Live Example — Normal Flow
Block element 1 (full width)
Block element 2 (stacks below)
Block 3 with inline span and another inline flowing horizontally inside it.

display: block

A block-level element takes up the full width of its parent, starts on a new line, and respects all box-model properties (width, height, margin, padding).

CSS
.block-demo {
  display: block;
  width: 200px;
  height: 60px;
  margin: 10px 0;
  padding: 10px;
  background: #646cff;
}
Live Example — display: block
Block A — takes full width, stacks vertically
Block B — width: 60%, still on own line
Block C — width: 40%

Even with a set width, each block starts on a new line.

display: inline

Inline elements flow within text. They do not start on a new line, and they ignore width, height, and vertical margin/padding.

CSS
.inline-demo {
  display: inline;
  width: 200px;    /* IGNORED */
  height: 60px;   /* IGNORED */
  margin-top: 20px; /* IGNORED */
  padding: 5px 10px; /* horizontal works, vertical doesn't push */
}
Live Example — display: inline
Text before Inline A Inline B Inline C text after — all flow on the same line and wrap with the text.

Width and height are ignored. Vertical margin is ignored. Only horizontal padding/margin works.

display: inline-block

The best of both worlds: flows inline like text, but respects width, height, and all box-model properties like a block.

CSS
.inline-block-demo {
  display: inline-block;
  width: 120px;     /* WORKS */
  height: 60px;     /* WORKS */
  margin: 10px;     /* ALL directions WORK */
  padding: 10px;    /* ALL directions WORK */
  vertical-align: top;
}
Live Example — block vs inline vs inline-block Comparison

display: block

Block A (150px)
Block B (150px)

display: inline (width/height ignored)

Inline A Inline B ← width: 150px set but ignored

display: inline-block (best of both)

Inline-block A
Inline-block B
← side-by-side WITH width/height

display: none vs visibility: hidden

Both hide elements, but they behave very differently in terms of layout impact.

CSS
/* Completely removed from layout */
.gone {
  display: none;
}

/* Hidden but still takes up space */
.invisible {
  visibility: hidden;
}
Live Example — display: none vs visibility: hidden
display: none
Box 1
Box 2 (display: none)
Box 3 — jumps up! No gap.
visibility: hidden
Box 1
Box 2 (visibility: hidden)
Box 3 — gap preserved!
Key Differences

display: none removes the element from the document flow entirely (no space, no events). visibility: hidden hides it visually but it still occupies its space in the layout. Screen readers also skip display: none elements.

position: static

The default positioning. The element follows normal flow. top, right, bottom, left, and z-index have no effect.

CSS
.static {
  position: static; /* default, rarely written explicitly */
  top: 50px;          /* IGNORED */
  left: 100px;        /* IGNORED */
}

position: relative

The element stays in normal flow (its original space is preserved), but you can offset it with top/right/bottom/left relative to its original position. It also establishes a containing block for absolutely positioned children.

CSS
.relative {
  position: relative;
  top: 20px;    /* moves DOWN 20px from original spot */
  left: 30px;   /* moves RIGHT 30px from original spot */
}
Live Example — position: relative
Static box (normal position)
Relative: top: 15px; left: 40px
Static box — notice the gap where the relative box was originally

The original space is preserved (gap remains). The box is shifted visually from its original position.

position: absolute

The element is removed from normal flow (takes up no space). It positions itself relative to its nearest positioned ancestor (one with position: relative/absolute/fixed/sticky). If none exists, it positions relative to the initial containing block (the viewport).

CSS
/* The classic pattern: absolute inside relative */
.parent {
  position: relative; /* establishes containing block */
}

.child {
  position: absolute;
  top: 10px;
  right: 10px;
}
Live Example — Absolute Inside Relative
Parent: position: relative
top: 10px; right: 10px
bottom: 10px; left: 10px
Centered (50% + translate)
top: 10px; left: 10px
bottom: 10px; right: 10px
Forgetting position: relative on the Parent

If the parent doesn't have position: relative (or another positioning), the absolute child will position itself relative to the viewport or the nearest positioned ancestor further up the tree. Always set position: relative on the intended parent container.

position: fixed

The element is removed from normal flow and positioned relative to the viewport. It stays in place even when the page is scrolled. Commonly used for sticky headers, floating buttons, and modals.

CSS
/* Fixed header */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
}

/* Floating action button */
.fab {
  position: fixed;
  bottom: 20px;
  right: 20px;
}
Live Example — position: fixed (simulated)
Fixed navbar (position: fixed; top: 0)

Content would scroll beneath the fixed navbar.

The navbar stays pinned to the top of the viewport regardless of scroll position.

+

In a real page, the blue bar and the green button would stay fixed on screen while you scroll.

Fixed + Transform = Broken

If any ancestor has a transform, perspective, or filter property, it creates a new containing block for fixed elements. The element will no longer be fixed relative to the viewport, but to that ancestor instead.

position: sticky

A hybrid of relative and fixed. The element scrolls with the page normally until it hits a specified offset (e.g., top: 0), then "sticks" in place until its parent scrolls out of view.

CSS
.sticky-header {
  position: sticky;
  top: 0;
  background: #0a0a1a;
  z-index: 10;
}

/* Sticky sidebar */
.sidebar {
  position: sticky;
  top: 80px;   /* sticks 80px from top */
  align-self: start;
}
Live Example — position: sticky

Scroll down inside this container to see sticky headers in action.

Section A (sticky: top: 0)

Item A1 — Lorem ipsum dolor sit amet

Item A2 — consectetur adipiscing elit

Item A3 — sed do eiusmod tempor

Item A4 — incididunt ut labore

Section B (sticky: top: 0)

Item B1 — Ut enim ad minim veniam

Item B2 — quis nostrud exercitation

Item B3 — ullamco laboris nisi

Item B4 — ut aliquip ex ea commodo

Section C (sticky: top: 0)

Item C1 — Duis aute irure dolor

Item C2 — in reprehenderit in voluptate

Item C3 — velit esse cillum dolore

Item C4 — eu fugiat nulla pariatur

Scroll inside the box above. Each section header sticks at the top, then gets pushed away by the next one.

Sticky Requirements

For sticky to work: (1) you must set at least one offset (top, bottom, etc.), (2) the parent must have enough scrollable content, and (3) no ancestor can have overflow: hidden or overflow: auto (unless it is the scroll container itself).

top / right / bottom / left / inset

These offset properties only work on positioned elements (not static). The inset shorthand sets all four at once.

CSS
/* Individual properties */
.box {
  position: absolute;
  top: 10px;
  right: 20px;
  bottom: 10px;
  left: 20px;
}

/* inset shorthand (same as above) */
.box {
  position: absolute;
  inset: 10px 20px;
}

/* Full-bleed overlay */
.overlay {
  position: absolute;
  inset: 0;  /* shorthand for top:0 right:0 bottom:0 left:0 */
}
Live Example — inset Shorthand
inset: 15px (15px from all edges)

z-index & Stacking Contexts

z-index controls the stacking order of positioned elements. Higher values appear in front. It only works on elements with a position value other than static.

CSS
.behind  { position: relative; z-index: 1; }
.middle  { position: relative; z-index: 10; }
.infront { position: relative; z-index: 100; }

/* Things that create a new stacking context: */
/* - position + z-index (not auto) */
/* - opacity < 1 */
/* - transform, filter, perspective */
/* - isolation: isolate */
Live Example — z-index Stacking
z-index: 1 (back)
z-index: 10 (middle)
z-index: 100 (front)

Stacking Context

A stacking context is like a self-contained z-index universe. Children's z-index values only compete against siblings within the same stacking context, never against elements in a parent or sibling context.

CSS
/* Parent creates a stacking context with z-index: 1 */
.parent {
  position: relative;
  z-index: 1;
}

/* This child has z-index: 9999, but it can NEVER
   appear above a sibling of .parent with z-index: 2
   because parent's context caps it at 1 */
.child {
  position: absolute;
  z-index: 9999;
}
z-index Only Works on Positioned Elements

Setting z-index: 999 on a position: static element does absolutely nothing. The element must have position: relative, absolute, fixed, or sticky for z-index to take effect.

overflow

Controls what happens when content is larger than its container.

CSS
.a { overflow: visible; }  /* default: content spills out */
.b { overflow: hidden; }   /* clips content, no scrollbar */
.c { overflow: scroll; }   /* always shows scrollbar */
.d { overflow: auto; }     /* scrollbar only when needed */

/* Per-axis control */
.e { overflow-x: auto; overflow-y: hidden; }
Live Example — overflow Values
overflow: visible (default)
This content overflows its container because it's taller than the 80px height. The default behavior is visible, meaning content spills out beyond the border and overlaps anything below it.
overflow: hidden
This content overflows its container because it's taller than the 80px height. With overflow: hidden, the extra content is clipped and invisible. No scrollbar appears.
overflow: scroll
This content overflows its container because it's taller than the 80px height. With overflow: scroll, a scrollbar always appears even if the content fits.
overflow: auto
This content overflows its container because it's taller than the 80px height. With overflow: auto, a scrollbar only appears when the content actually overflows.

Centering Techniques Overview

Centering elements is one of the most common CSS tasks. Here is a summary of the most reliable methods.

Horizontal Centering

CSS
/* Block element with known width */
.center-block {
  width: 300px;
  margin: 0 auto;
}

/* Inline/inline-block content */
.center-text {
  text-align: center;
}

Vertical + Horizontal Centering

CSS
/* Method 1: Flexbox (most common) */
.flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* Method 2: Grid (simplest) */
.grid-center {
  display: grid;
  place-items: center;
}

/* Method 3: Absolute + Transform */
.abs-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Method 4: Absolute + inset + margin */
.inset-center {
  position: absolute;
  inset: 0;
  margin: auto;
  width: fit-content;
  height: fit-content;
}
Live Example — Four Centering Methods
Flexbox center
Grid place-items
Absolute + transform
Absolute + inset + margin
Preferred Centering Method

In modern CSS, display: grid; place-items: center; is the simplest way to center anything both horizontally and vertically. It works with any content size and requires just two lines of CSS.

Common Gotchas

Absolute Positioning Removes from Flow

An absolutely positioned element is completely removed from the document flow. Surrounding elements will not know it exists, potentially causing overlaps. Always account for the space the element should have occupied.

Sticky Needs a Scrollable Ancestor

position: sticky does nothing if: (1) no offset is set, (2) the parent has overflow: hidden, or (3) the parent doesn't have enough content to scroll. All three conditions must be met for sticky to activate.

Inline Elements and Whitespace

inline and inline-block elements respect whitespace in your HTML. Two <div> elements on separate lines will have a small gap between them. Fix with font-size: 0 on the parent, or use Flexbox instead.

z-index War

Avoid escalating z-index values (100, 1000, 99999). Instead, use a consistent scale defined in CSS custom properties: --z-dropdown: 100; --z-modal: 200; --z-tooltip: 300;.

overflow: hidden Clips Sticky Children

Setting overflow: hidden on a parent element will break position: sticky on its children. The sticky element needs an overflow-visible ancestor as its scrolling container.

Collapsing Parent with Absolute Children

If all children are position: absolute, the parent collapses to zero height because absolute elements are removed from the flow. Set an explicit height or min-height on the parent.

Pro Tips

Use inset: 0 for Full Overlays

Instead of writing top: 0; right: 0; bottom: 0; left: 0;, use the shorthand inset: 0. It's cleaner and supported in all modern browsers.

Isolation for Stacking Contexts

Use isolation: isolate on a parent element to create a new stacking context without changing any other visual property. This prevents z-index conflicts from leaking out.

Prefer Flexbox/Grid Over Position for Layout

position: absolute/fixed should be reserved for overlays, tooltips, modals, and decorative elements. For page layout, always use Flexbox or Grid — they handle responsive behavior and source order much better.

Sticky + Scroll Margin

When using sticky headers with anchor links, add scroll-margin-top to your section targets so the sticky header doesn't overlap the anchor scroll target: section { scroll-margin-top: 80px; }.

Debugging Stacking Contexts

Browser DevTools (Firefox in particular) have a stacking context inspector. Use it when z-index seems "broken" — the issue is almost always a stacking context boundary you didn't expect.

Container Queries vs Position

In modern CSS, you can use @container queries to make layout decisions based on the parent's size rather than the viewport. This reduces the need for complex positioned layouts in responsive designs.

PreviousColors & Backgrounds