—CSS Series · Post 06: Display & Positioning

Display & Positioning — CodeHerWay
CSS Series · Post 06

Display & Positioning
Where Things Actually Go

Half of layout confusion comes from not understanding how elements flow by default. The other half comes from not knowing when to break out of that flow — and how.

CSS Beginner Series: Post 06 ~13 min read

💬 "Why Won't This Just Sit Next to That?"

You have two divs. You want them side by side. You push, you pull, you add margins everywhere — and they still stack vertically like they're ignoring you. Or you set position: absolute on something and it flies to a completely unexpected corner of the screen.

These are display and positioning problems, and they're caused by CSS having a very specific default behavior that most people don't realize exists until it bites them.

🧠 The Default: Normal Flow

By default, HTML elements have a flow. Block elements stack vertically, one per line, filling the available width. Inline elements sit in a line and wrap like text. This is called normal flow.

Once you understand that flow exists and how it works, you can work with it — and you'll know exactly which tools to use when you need to break out of it.

🧱 The display Property

block — Full Width, New Line

Block elements take up the full width available and force a new line before and after themselves. <div>, <p>, <h1><h6>, <section> are block by default.

display: block — each element takes full width
div.card (block)
div.card (block)
div.card (block)

inline — Flows with Text

Inline elements sit in the text flow. They don't start on a new line, and their width shrinks to fit their content. <span>, <a>, <strong>, <em> are inline by default. Crucially: you can't set width or height on inline elements — they ignore those properties.

display: inline — flows in line like text
span span span flows like words in a sentence

inline-block — Best of Both

Inline-block sits in the text flow like inline, but respects width, height, padding, and margin like a block. This used to be the primary way to lay out navigation items and buttons before Flexbox became mainstream.

display: inline-block — side by side, but accepts dimensions
Nav Item
Nav Item
Nav Item

none — Hides the Element

display: none removes the element from the page entirely — it takes up no space and is invisible. This is different from visibility: hidden, which hides the element but preserves its space in the layout.

styles.css
CSS · display values
/* Override default display behavior */ .nav-item { display: inline-block; } /* sit side by side */ .pill { display: inline-block; } /* badge/tag */ .hidden { display: none; } /* gone — no space taken */ .invisible { visibility: hidden; } /* invisible — space preserved */ /* Common pattern: show/hide on mobile */ .mobile-menu { display: none; } .mobile-menu:target { display: block; }

🧱 The position Property

The position property controls how an element is placed in or out of normal flow. It has five values, and understanding the difference between them will solve most of the "why is this in the wrong place" problems you'll encounter.

static — The Default

Every element is position: static by default. This means it sits in normal flow. top, right, bottom, left have no effect on static elements — you have to change position first.

relative — Move from Its Own Spot

A relatively positioned element moves relative to where it would normally be. The original space it occupied is preserved — the element visually shifts, but doesn't push other elements around.

styles.css
CSS · position: relative
.nudged { position: relative; top: 8px; /* moves 8px DOWN from its normal position */ left: 12px; /* moves 12px RIGHT from its normal position */ } /* Most importantly: position: relative makes this element a POSITIONING CONTEXT for any absolute children inside it */

absolute — Pinned to Its Positioned Parent

An absolutely positioned element is removed from normal flow entirely. It gets positioned relative to its nearest ancestor that has position: relative (or absolute, fixed, or sticky). If no positioned ancestor exists, it uses the <body>. This is why things fly to unexpected corners — the parent wasn't set up correctly.

parent — position: relative
Card content here
New
styles.css
CSS · position: absolute
/* Parent must have position: relative to "catch" the child */ .card { position: relative; /* ← this creates the positioning context */ } /* Badge sits at top-right of .card, not of the whole page */ .badge { position: absolute; top: 12px; right: 12px; } /* Absolute elements are removed from flow — they don't push other elements around */
⚠️ The Most Common Absolute Mistake

If your absolutely positioned element is flying to the top corner of the entire page, it's because its parent doesn't have position: relative. Always set the parent first. The child looks for the nearest positioned ancestor — if there isn't one, it climbs all the way up to the body.

fixed — Pinned to the Viewport

A fixed element is removed from flow and positioned relative to the browser viewport. It stays in the same spot even as the user scrolls. Classic uses: sticky navigation bars, floating action buttons, cookie banners.

styles.css
CSS · position: fixed
/* Stays at the top of the viewport as you scroll */ .navbar { position: fixed; top: 0; left: 0; width: 100%; z-index: 100; /* stays on top of everything */ } /* Fixed removes the element from flow — add padding-top to the body equal to navbar height to prevent content overlap */ body { padding-top: 60px; }

sticky — Scrolls Then Sticks

Sticky is a hybrid: the element scrolls normally until it hits a defined offset from the viewport edge, then it sticks in place. The most common use is section headers that stick while their section is in view.

styles.css
CSS · position: sticky
/* Scrolls normally, then sticks when it hits top: 0 */ .section-header { position: sticky; top: 0; background: #0a0a0f; /* needs a background or content shows through */ z-index: 10; } /* sticky only works within its scroll container — the parent must have overflow: scroll or auto, or be the page itself */

z-index — Controlling Stack Order

When positioned elements overlap, z-index controls which one sits on top. Higher number = closer to the viewer. Only works on elements that have a position other than static.

styles.css
CSS · z-index
.modal { position: fixed; z-index: 1000; } /* on top */ .overlay { position: fixed; z-index: 900; } /* below modal */ .navbar { position: fixed; z-index: 100; } /* below overlay */ .tooltip { position: absolute; z-index: 50; } /* above card */ .card { position: relative; z-index: 1; } /* base layer */ /* z-index doesn't work on position: static elements */

Quick Reference

ValueIn flow?Positioned relative toClassic use case
static✓ YesDefault. Everything starts here.
relative✓ YesIts own normal positionMinor nudges; creating context for absolute children
absolute✗ NoNearest positioned ancestorBadges, tooltips, dropdowns, overlays
fixed✗ NoViewportSticky navbars, floating buttons, cookie banners
sticky✓ YesScroll container + thresholdSection headers, in-page navigation
🛠

Mini Build: Card with a Badge + Horizontal Nav

Two builds in one. First: a card with an absolutely positioned badge. Second: a horizontal navigation using inline-block. Both use positioning intentionally.

01

The card with a badge. Parent gets position: relative. Badge gets position: absolute and snaps to the corner.

index.html + styles.css
HTML + CSS
<!-- HTML --> <div class="card"> <span class="badge">New</span> <h3 class="card-title">Post Title</h3> <p class="card-text">Description goes here.</p> </div> /* CSS */ .card { position: relative; /* ← creates the context */ background: #12121a; border-radius: 12px; padding: 24px; max-width: 320px; } .badge { position: absolute; /* ← breaks out of flow */ top: 14px; right: 14px; background: #ff69b4; color: #fff; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; padding: 3px 10px; border-radius: 20px; }
02

The horizontal navigation. Use inline-block on the nav items so they sit side by side while still accepting padding and hover states.

index.html + styles.css
HTML + CSS
<!-- HTML --> <nav class="nav"> <a class="nav-item" href="#">Home</a> <a class="nav-item" href="#">About</a> <a class="nav-item" href="#">Work</a> </nav> /* CSS */ .nav { background: #12121a; padding: 0 24px; } .nav-item { display: inline-block; /* side by side */ padding: 16px 20px; /* clickable area */ color: #9595a8; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; } .nav-item:hover { color: #ff69b4; }
ℹ️ inline-block vs Flexbox

For navigation, most modern projects now use Flexbox instead of inline-block. Flexbox gives you better alignment control and simpler code. But inline-block is worth knowing — it predates Flexbox and you'll see it everywhere in older codebases. Next post covers Flexbox in full.

💛 Layout Is Starting to Make Sense

Once you understand normal flow and how position interacts with it, a huge chunk of CSS confusion disappears. You're no longer fighting the layout system — you're working with it.

  • block elements stack vertically and fill width. inline flows like text. inline-block is the hybrid.
  • display: none removes an element from the page entirely — space and all
  • position: relative makes an element a positioning context for its children
  • position: absolute breaks out of flow — always set the parent to relative first
  • position: fixed sticks to the viewport. sticky scrolls then sticks.
  • z-index only works on positioned elements — not static ones

Next: Flexbox — the modern layout system that makes all the old inline-block tricks obsolete. Centering, spacing, distributing items — done properly, in one property.

🧾 DevFession

I once spent two hours trying to center something using position: absolute with top: 50%; left: 50% and a margin: -50px hack. It almost worked. Almost.

Then I learned Flexbox and did it in two lines. Two. I stared at the screen for a while afterward processing the grief.

Positioning is powerful and you absolutely need to know it — badges, modals, tooltips, sticky headers — all of that needs position. But for centering content and building multi-column layouts, Flexbox is what you actually want. Learn both. Use each for its job.

Previous
Previous

—CSS Series · Post 07: Flexbox

Next
Next

—CSS Series · Post 05: Color