Matheion

MA-WEB1 · Module 13

Layout: flow, positioning, and floats

Topics: Normal flow · display · position · Floats

Overview

Session 13 — Layout: normal flow, display, positioning, and floats

You will learn how pages lay out by default (normal flow), how display switches flow behaviour (block, inline, inline-block, none), how position lifts boxes out of flow (relative, absolute, fixed, plus z-index), and the float tool for wrapping text around images. You will turn the café's vertical nav into a horizontal bar.

Plan: ideas → worked layouts → bridge → short drills → reveal.

Time: about 60–70 minutes if you draw the flow of every snippet before reading the reveal.

Concepts

Session 13 — Layout: normal flow, display, positioning, and floats

The one-paragraph story

Block elements stack; inline elements flow — that is normal flow, and it is the layout every page starts from. Three CSS tools then rearrange boxes: display changes an element's flow behaviour (block ↔ inline ↔ none); position lifts a box out of flow (relative, absolute, fixed) and places it precisely; and float — the old way of pushing an image to the side and wrapping text around it — survives for a handful of legitimate uses. The modern layout engines, flexbox and grid, arrive in Session 14; this session builds the mental foundation of flow that both of them override. Along the way you will turn the café's vertical nav list into a horizontal bar.


Normal flow: block vs inline

Remember the two families from Session 2? Normal flow is their behaviour:

  • Block elements (headings, paragraphs, divs) stack vertically, each starting on a new line and filling its container's width.
  • Inline elements (span, em, a, img) flow horizontally inside a line, wrapping when the line runs out.
<h2>Menu</h2>
<p>Coffee and <span>pastries</span>.</p>

The h2 gets its own line; the paragraph takes the next line; the span stays inline inside the paragraph's text. This default — no CSS layout at all — is what Sessions 1–12 have been producing.


display: the flow switch

display changes an element's flow type:

nav ul {
  display: flex;      /* horizontal row, Session 14 */
}
span.blocky {
  display: block;     /* the span now stacks like a div */
}
.hidden {
  display: none;      /* removed from layout entirely */
}

The values you will use:

  • block — stack and fill the line.
  • inline — flow within text.
  • inline-block — a hybrid: flows inline (sits beside text) but takes width/height and box-model layers like a block.
  • none — the element and its children are not rendered at all; the space collapses (contrast with visibility: hidden, which keeps the space).
  • flex / grid — the modern layout modes (Session 14).

display: none is how things disappear: a confirmation hidden after it is shown, an element you want out of the layout without deleting the markup.


position: lifting boxes out of flow

Four values, each placing the box differently:

static — the default: normal flow, and top/left etc. are ignored.

relative — the box stays in flow (its space is preserved) but is nudged from its normal spot:

.badge {
  position: relative;
  top: -4px;      /* up 4 px from where it would sit */
}

absolute — the box is removed from flow entirely (other content ignores it) and positioned relative to its nearest positioned ancestor (the nearest ancestor with position set to anything but static); if none exists, relative to the page:

.card { position: relative; }
.card .tag {
  position: absolute;
  top: 8px;
  right: 8px;
}

The pattern: a relative container anchors its absolutely-positioned children. The .tag badge pins to the card's top-right corner. This is the standard "badge on a card" recipe.

fixed — the box is removed from flow and positioned relative to the viewport (the visible window). It stays put while the page scrolls — the classic sticky header or "back to top" button:

header {
  position: fixed;
  top: 0;
  width: 100%;
}

z-index controls which box draws on top when positioned boxes overlap: higher number on top (z-index: 10 beats z-index: 1). It only applies to positioned elements (or flex/grid items).


float: the older tool

float pushes a box to one side and wraps following content around it:

img.portrait {
  float: right;
  margin: 0 0 10px 10px;
}

The floated image sits right; the paragraphs after it flow up around its left edge. Historically floats built whole columns (float left, float right, width 50%). Session 14's flexbox and grid replace nearly all of that — but floats remain the right tool for wrapping text around an image, and you will meet them in real sites. The clear property ends a float's reach: clear: both forces the next element below any floated boxes instead of wrapping beside them.


From vertical to horizontal: the nav bar

The simplest layout win uses display: inline-block (or the Session 14 flexbox):

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
nav li {
  display: inline-block;
  margin-right: 16px;
}
nav a {
  text-decoration: none;
  color: #1f3a5f;
}

The bulletless, padding-free list from Session 12 becomes a horizontal row of links: each li is inline-block, so they sit side by side while keeping their box-model spacing. This is the café's top navigation — the same markup as Session 4, now horizontal.


The page skeleton in flow

<body>
  <header>…nav…</header>
  <main>…</main>
  <aside>…hours…</aside>
  <footer>…</footer>
</body>

By default these four regions stack vertically — header, then main, then aside, then footer. That is correct and readable. Making main and aside sit side by side is what flexbox (Session 14) does; before flexbox, floats or fixed widths did it. The habit: build the vertical version first — it is the accessible, mobile-friendly default — then lay it out horizontally only when the design asks.


Pitfalls to watch for

  • absolute positioning needs a positioned ancestor — without one it anchors to the page and drifts from its visual container; set position: relative on the container.
  • absolute/fixed elements leave no space — following content moves underneath them.
  • display: none removes the box entirely — visibility: hidden keeps the space but shows nothing.
  • Floats take elements out of flow — the parent can collapse to zero height unless cleared.
  • position values are not interchangeable — absolute is positioned to an ancestor, fixed to the viewport.

Examples

Session 13 — Worked examples

Example A — Normal flow, by default

<h2>Our story</h2>
<p>We opened in 2016 with <span>one espresso machine</span>.</p>
<p>Now the roastery fills the pier.</p>

Rendered layout: the h2 on its own line; the first paragraph below it; the second paragraph below that; the span flowing inside the first paragraph's text. Nothing is positioned — this is pure block/inline flow, the canvas every later layout tool modifies.


Example B — A badge pinned to a card

.card {
  position: relative;
}
.card .tag {
  position: absolute;
  top: 8px;
  right: 8px;
  background-color: #c62828;
  color: #ffffff;
  padding: 4px 8px;
  border-radius: 4px;
}
<div class="card">
  <img src="images/thumb-pastry.jpg" alt="Cardamom twist">
  <p class="card-title">Cardamom twist</p>
  <span class="tag">New</span>
</div>

The .card is relative — its normal flow position is preserved. The .tag is absolute: it leaves flow (nothing reserves space for it) and anchors to the nearest positioned ancestor, the card. top: 8px; right: 8px pins it to the card's top-right corner, wherever the card sits. If .card were static, the tag would anchor to the page instead.


Example C — A fixed header

header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background-color: #faf7f2;
  padding: 12px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

The header pins to the top of the viewport and stays while the page scrolls. Note the consequence: the header is out of flow, so the page content starts under it — that is why body usually gets top padding equal to the header's height. position: fixed is relative to the viewport, not any ancestor.


Example D — Text wrapping around a floated image

img.portrait {
  float: right;
  margin: 0 0 10px 10px;
}
<p>…long paragraph about the pier roastery…</p>
<img class="portrait" src="images/roastery.jpg" alt="The roastery on the pier">
<p>…more text that wraps beside the photo…</p>

The image floats right; the following paragraph flows up around its left side. This text-wrapping is float's remaining natural job — modern layouts build columns with flexbox/grid instead.


Example E — The horizontal nav bar

nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
nav li {
  display: inline-block;
  margin-right: 16px;
}
nav a {
  text-decoration: none;
  color: #1f3a5f;
  font-weight: bold;
}

The Session 4 nav markup — a ul of three links — becomes a horizontal bar: bullets and indentation gone (Session 12), each li an inline-block so the items sit side by side with 16 px gaps. The links lose their underline and take the café's blue. This is the site's header navigation, ready for flexbox to refine in Session 14.


Example F — Clearing a float

.footer-note {
  clear: both;
}

If a floated image reaches into the footer's space, clear: both on the footer pushes it below the float instead of wrapping beside it. When floats get chaotic, clear is the emergency brake — and the reason Session 14 exists.

Practice check — layout flow and positioning

Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.

  1. 1.In normal flow, block elements:

  2. 2.`position: absolute` positions a box relative to:

  3. 3.An element with `position: fixed` is positioned relative to the:

  4. 4.`display: none` and `visibility: hidden` differ in that:

  5. 5.The modern replacement for building columns with floats is: