Normal Flow and Display
Introduction
Before Flexbox and Grid, every page already has a default layout system: normal flow. If you understand how elements flow by default and how display changes that behavior, most layout bugs become much easier to solve. This chapter explains normal flow and the practical use of common display values in real UI work.
Prerequisites
- Basic HTML structure knowledge
- Basic box model and sizing knowledge
- Familiarity with CSS selectors and simple component styling
What Is Normal Flow?
Normal flow is the browser's default layout behavior when no special positioning or advanced layout mode is applied.
In normal flow:
- block-level elements stack vertically
- inline content flows inside lines
- elements occupy space in document order
Example HTML:
<h1>Page Title</h1>
<p>First paragraph.</p>
<p>Second paragraph.</p>By default, these blocks appear top to bottom.
Block vs Inline in Normal Flow
Block-level behavior
Block boxes usually:
- start on a new line
- expand to available inline width
- stack vertically
Common examples: div, p, section, article, h1-h6, ul, li.
Inline behavior
Inline boxes usually:
- stay within text flow
- do not start a new line automatically
- occupy only needed content width
Common examples: span, a, strong, em, code.
The display Property
display defines how an element participates in layout.
Most common values:
blockinlineinline-blocknoneflex(later chapter)grid(later chapter)
Understanding the first four is essential before advanced layouts.
display: block
Forces element to behave like a block box.
a.cta {
display: block;
width: fit-content;
padding: 0.6rem 1rem;
}Useful when:
- you want line breaks around the element
- you want block spacing behavior
- you need easier width/margin control
display: inline
Forces element to behave like inline text content.
h2 {
display: inline;
}Be careful:
- width/height usually do not behave like block boxes
- vertical margin/padding behavior differs from block context
Use inline mostly for small text-level adjustments, not major layout.
display: inline-block
inline-block combines features:
- stays in inline flow (can sit next to text/elements)
- supports width/height/padding like a box
.tag {
display: inline-block;
padding: 0.25rem 0.6rem;
border-radius: 999px;
background: #e2e8f0;
}Useful for:
- badges
- chips
- button-like inline elements
display: none
Removes element from layout and rendering flow.
.is-hidden {
display: none;
}Behavior:
- element does not occupy space
- siblings reflow as if element is absent
Common use:
- conditionally hidden UI sections
- responsive toggles (with caution)
Accessibility note:
display: nonecontent is generally not accessible to assistive technologies while hidden.
visibility: hidden vs display: none
They are not the same:
.ghost {
visibility: hidden;
}visibility: hidden: invisible but still occupies layout spacedisplay: none: removed from layout space
Choose intentionally based on whether layout space should remain reserved.
Natural Width Behavior in Normal Flow
Block elements often fill available width unless constrained:
.panel {
max-width: 720px;
}Inline elements size to content. If you need width control for an inline element, consider inline-block or block.
Inline Formatting Context Basics
Inside text flow:
- text wraps at available width
- inline elements align with text baseline by default
- line-height affects vertical rhythm
This explains common alignment surprises between icons and text. You can adjust with:
vertical-align- line-height tuning
Why Normal Flow Still Matters with Flex/Grid
Even when using Flexbox/Grid:
- child content still has typography flow
- margins/padding still apply
- hidden elements still affect semantics and interaction logic
Normal flow is the foundation beneath advanced layout systems.
Tip
Default First, Then Override
Start with semantic HTML and normal flow behavior. Add layout overrides (flex, grid, positioning) only where needed.
Common Mistakes
| Mistake | Why it hurts | Better approach |
|---|---|---|
Using inline for large layout blocks | Width/height control becomes awkward | Use block or layout containers |
Hiding content with display: none without logic checks | Missing UI/function states | Ensure state handling is explicit |
Using inline-block for full page layout | Hard spacing/alignment management | Use Flexbox/Grid for larger layouts |
| Not understanding reserved space behavior | Unexpected blank gaps | Compare visibility: hidden vs display: none |
Styling all div elements globally | Side effects across page | Use classes and scoped selectors |
Mini Exercise
- Create a heading, paragraph, link, and badge element
- Toggle link between
inline,inline-block, andblock - Add width and padding and observe behavior changes
- Hide one section with
visibility: hidden, then withdisplay: none - Inspect layout differences in DevTools
FAQ
Is block/inline classification outdated?
The web platform has evolved, but this model is still useful and foundational for understanding default behavior.
Should I use inline-block for navigation menus?
You can for small cases, but Flexbox is usually cleaner and more maintainable for navigation layout.
Does display: none remove the element from the DOM?
No. It stays in the DOM tree but is removed from layout and rendering.
Why can't I set width on an inline element reliably?
Inline formatting rules prioritize text flow; width/height do not behave like block boxes there.
How do I debug display problems quickly?
Inspect the element in DevTools, check computed display, and toggle candidate values live to observe layout changes.