Chapter 9: CSS Display, Visibility, Float & Inline-Block
Understanding element rendering behaviors, document flow layout modes, element visibility distinctions, and legacy float clearing mechanisms is vital for comprehending CSS layout mechanics.
9.1 The Display Property: block, inline, inline-block & none
Every HTML element has a default outer and inner display value determined by the HTML specification. The CSS display property overrides these defaults.
| Display Value | Line Break Behavior | Width & Height Control | Margin & Padding Behavior |
|---|---|---|---|
display: block |
Forces a new line before and after (occupies 100% parent width). | Full control (accepts explicit width and height). |
Vertical and horizontal margins/padding fully respected. |
display: inline |
Flows inline with surrounding text (no new line). | Ignored (width/height equal content size only). | Horizontal padding/margins apply; vertical margins/padding ignored! |
display: inline-block |
Flows inline alongside text/other inline elements. | Full control (accepts custom width and height). |
All vertical and horizontal margins/padding fully respected. |
display: none |
Removes element completely from visual layout. | N/A (element not rendered). | Element collapses completely; takes up 0 space in document flow. |
<!DOCTYPE html>
<html>
<head>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
h3 { margin-top: 0; color: #818cf8; }
.label { font-size: 11px; color: #64748b; font-family: monospace; margin: 14px 0 4px; display: block; }
.note { font-size: 12px; color: #64748b; margin-top: 6px; }
/* block — full width, stacks vertically */
.demo-block {
display: block;
background: rgba(99,102,241,0.2);
border: 2px solid #6366f1;
padding: 10px 16px;
border-radius: 6px;
width: 60%; /* block respects explicit width */
margin-bottom: 6px;
}
/* inline — flows with text, ignores width/height */
.demo-inline {
display: inline;
background: rgba(16,185,129,0.2);
border: 2px solid #10b981;
padding: 4px 10px;
border-radius: 4px;
/* width and height set here are IGNORED */
width: 200px; height: 50px;
}
/* inline-block — flows inline, respects width/height */
.demo-inline-block {
display: inline-block;
background: rgba(245,158,11,0.2);
border: 2px solid #f59e0b;
padding: 10px 18px;
border-radius: 6px;
width: 160px;
height: 60px;
vertical-align: middle;
margin-right: 6px;
text-align: center;
font-size: 13px;
}
/* none — removed from layout completely */
.demo-none { display: none; }
</style>
</head>
<body>
<h3>display Property Comparison</h3>
<span class="label">display: block — each takes its own full-width row</span>
<div class="demo-block">Block element #1 (width: 60%)</div>
<div class="demo-block">Block element #2 — stacks below #1</div>
<span class="label">display: inline — flows within text, ignores width/height (200px width + 50px height set but ignored!)</span>
<p>
This is paragraph text with an
<span class="demo-inline">inline span</span>
that flows inside the line, and
<span class="demo-inline">another one</span>
right here too.
</p>
<span class="label">display: inline-block — flows inline but respects width (160px) and height (60px)</span>
<div>
<div class="demo-inline-block">inline-block #1</div>
<div class="demo-inline-block">inline-block #2</div>
<div class="demo-inline-block">inline-block #3</div>
</div>
<span class="label">display: none — completely removed from layout (element below takes its space)</span>
<div class="demo-block">Visible element before the hidden one</div>
<div class="demo-none">This element is HIDDEN — you cannot see this!</div>
<div class="demo-block">Visible element directly after — no gap where the hidden element was!</div>
</body>
</html>
9.2 Hiding Elements: display: none vs visibility: hidden vs opacity: 0
When hiding elements on a web page, developers can choose between three distinct techniques depending on whether layout space should be preserved or accessibility events retained.
| Feature Comparison | display: none; |
visibility: hidden; |
opacity: 0; |
|---|---|---|---|
| Layout Space Occupied? | No (0 space, DOM layout collapses) | Yes (Invisible blank gap remains) | Yes (Invisible transparent gap remains) |
| User Click Events? | Disabled | Disabled | Active (Element clickable unless disabled!) |
| CSS Transitions? | Cannot be animated smoothly | Animates visibility toggle | Fully animates opacity (0 ⇉ 1) |
| Screen Reader Access? | Ignored by screen readers | Ignored by screen readers | Read aloud by screen readers |
When to Use Which?
- Use
display: nonefor tab panels, collapsible menus, or modal windows that should disappear completely. - Use
opacity: 0combined withpointer-events: nonefor smooth fade-in / fade-out hover animations!
<!DOCTYPE html>
<html>
<head>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
h3 { margin-top: 0; color: #38bdf8; }
.row { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; margin-bottom: 10px; }
.box {
background: rgba(99,102,241,0.2); border: 2px solid #6366f1;
border-radius: 8px; padding: 16px; font-size: 13px; font-family: monospace;
min-width: 120px; text-align: center;
}
.gap-marker { background: rgba(239,68,68,0.15); border: 2px dashed #ef4444; border-radius: 8px; padding: 16px; font-size: 11px; color: #ef4444; text-align: center; min-width: 100px; }
.label-row { font-size: 12px; color: #64748b; margin: 12px 0 4px; }
/* The three hiding techniques */
.hide-display { display: none; } /* No space occupied */
.hide-visibility { visibility: hidden; } /* Space preserved, invisible */
.hide-opacity { opacity: 0; pointer-events: none; } /* Space preserved, transparent */
/* Fade demo on hover */
.fade-box {
background: rgba(16,185,129,0.2); border: 2px solid #10b981; border-radius: 8px; padding: 14px;
opacity: 1; transition: opacity 0.4s ease; cursor: pointer; font-size: 13px; display: inline-block;
}
.fade-box:hover { opacity: 0; }
</style>
</head>
<body>
<h3>Hiding Elements — display vs visibility vs opacity</h3>
<div class="label-row">display: none — zero layout space (the gap below collapses):</div>
<div class="row">
<div class="box">Box A</div>
<div class="box hide-display">HIDDEN (display:none)</div>
<div class="box">Box C — moved left! No gap.</div>
</div>
<div class="label-row">visibility: hidden — layout space preserved (blank gap remains):</div>
<div class="row">
<div class="box">Box A</div>
<div class="gap-marker">← space preserved but invisible (visibility:hidden)</div>
<div class="box">Box C — gap still exists!</div>
</div>
<div class="label-row">opacity: 0 — layout space preserved + transition animatable:</div>
<div class="row">
<div class="box">Box A</div>
<div class="gap-marker" style="border-color:#f59e0b;color:#f59e0b;">← transparent gap (opacity:0 + pointer-events:none)</div>
<div class="box">Box C — gap still exists!</div>
</div>
<div class="label-row">Hover me to see opacity fade animation:</div>
<div class="fade-box">Hover to fade out! (opacity: 0 via :hover + transition)</div>
</body>
</html>
9.3 CSS Floats (float: left | right) & Clearing (clear)
The float property takes an element out of normal flow and places it along the left or right edge of its containing box, allowing text to wrap around it (originally designed for magazine-style image wrapping).
<!DOCTYPE html>
<html>
<head>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
h3 { margin-top: 0; color: #f59e0b; }
.article { background: #1e293b; border-radius: 10px; padding: 16px; margin-bottom: 16px; overflow: hidden; }
.article p { font-size: 14px; color: #94a3b8; margin: 0; line-height: 1.7; }
/* Float left — text wraps to the right */
.article-img-left {
float: left;
width: 100px; height: 80px;
background: linear-gradient(135deg, #4f46e5, #06b6d4);
border-radius: 8px;
margin-right: 16px;
margin-bottom: 8px;
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: #fff; text-align: center;
}
/* Float right — text wraps to the left */
.article-img-right {
float: right;
width: 100px; height: 80px;
background: linear-gradient(135deg, #10b981, #059669);
border-radius: 8px;
margin-left: 16px;
margin-bottom: 8px;
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: #fff; text-align: center;
}
/* clear: both — stops elements from sitting beside floats */
.footer-section {
clear: both;
background: rgba(239,68,68,0.12);
border: 1px dashed #ef4444;
border-radius: 6px;
padding: 10px 14px;
font-size: 12px; color: #f87171;
margin-top: 8px;
}
</style>
</head>
<body>
<h3>CSS float: left / right — Text Wrapping</h3>
<div class="article">
<div class="article-img-left">float: left</div>
<p>This paragraph text flows around the floated box on the left side. The float property takes the element out of normal flow and positions it on the left edge, allowing text to wrap alongside it — just like in a magazine layout with an embedded image.</p>
<div class="footer-section">clear: both — this section stops beside the float and starts below it</div>
</div>
<div class="article">
<div class="article-img-right">float: right</div>
<p>This paragraph text flows around the floated box on the right side. Setting float: right pushes the element to the right edge of its container while text fills in from the left side around it.</p>
<div class="footer-section">clear: both — clears both left and right floats</div>
</div>
</body>
</html>
9.4 The Clearfix Micro-Hack & Modern display: flow-root
When a parent container contains only floated child elements, the parent collapses to a height of 0px because floated elements are removed from normal flow calculation!
Method 1: The Modern Micro-Clearfix Hack (::after)
Attaching a pseudo-element with clear: both forces the parent to expand around floated children:
<!DOCTYPE html>
<html>
<head>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
h3 { margin-top: 0; color: #6366f1; }
/* WITHOUT clearfix — parent collapses */
.parent-no-clear {
background: rgba(239,68,68,0.15);
border: 2px dashed #ef4444;
border-radius: 8px;
padding: 8px;
margin-bottom: 12px;
}
.parent-no-clear p { font-size: 11px; color: #f87171; margin: 0 0 4px; }
/* WITH clearfix ::after hack */
.clearfix::after { content: ""; display: table; clear: both; }
.parent-clearfix {
background: rgba(99,102,241,0.15);
border: 2px solid #6366f1;
border-radius: 8px;
padding: 8px;
}
.parent-clearfix p { font-size: 11px; color: #818cf8; margin: 0 0 4px; }
/* Floated children */
.float-child {
float: left;
width: 80px; height: 60px;
background: linear-gradient(135deg, #4f46e5, #06b6d4);
border-radius: 6px;
margin: 4px;
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 700; color: #fff;
}
.after-marker {
background: #1e293b; border-radius: 6px; padding: 8px 12px;
font-size: 12px; color: #64748b; margin-top: 6px;
}
</style>
</head>
<body>
<h3>Clearfix Hack Demo</h3>
<p style="font-size:13px;color:#94a3b8;">Without clearfix — parent height collapses to 0:</p>
<div class="parent-no-clear">
<p>Parent (NO clearfix) — height should wrap around floated children but collapses!</p>
<div class="float-child">Float 1</div>
<div class="float-child">Float 2</div>
<div class="float-child">Float 3</div>
</div>
<div class="after-marker">↑ Parent above has no visible border bottom — it collapsed!</div>
<p style="font-size:13px;color:#94a3b8;margin-top:14px;">With .clearfix::after — parent correctly encloses all floated children:</p>
<div class="parent-clearfix clearfix">
<p>Parent (WITH clearfix) — ::after pseudo-element clears floats inside</p>
<div class="float-child">Float 1</div>
<div class="float-child">Float 2</div>
<div class="float-child">Float 3</div>
</div>
<div class="after-marker">↑ Parent above fully wraps around its floated children — clearfix works!</div>
</body>
</html>
Method 2: Modern display: flow-root (Recommended)
The modern CSS3 display: flow-root property establishes a new Block Formatting Context (BFC) that automatically encloses all internal floated elements without pseudo-elements!
<!DOCTYPE html>
<html>
<head>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
h3 { margin-top: 0; color: #10b981; }
/* display: flow-root automatically clears all internal floats */
.container-box {
display: flow-root; /* Establishes Block Formatting Context — encloses floats! */
background: rgba(16,185,129,0.15);
border: 2px solid #10b981;
border-radius: 10px;
padding: 16px;
}
.float-child {
float: left;
width: 90px; height: 70px;
background: linear-gradient(135deg, #10b981, #059669);
border-radius: 8px;
margin: 4px 12px 4px 0;
display: flex; align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: #fff;
}
.note { font-size: 12px; color: #34d399; margin: 0; }
</style>
</head>
<body>
<h3>display: flow-root — Modern Clearfix</h3>
<p style="font-size:13px;color:#94a3b8;">No ::after hack needed — just one property on the parent:</p>
<div class="container-box">
<div class="float-child">Float 1</div>
<div class="float-child">Float 2</div>
<div class="float-child">Float 3</div>
<p class="note">display: flow-root automatically wraps around all floated children — no clearfix hack needed!</p>
</div>
</body>
</html>
9.5 Interactive Sandbox — Display & Clearfix Layouts
Test inline-block spacing, float text wraps, and display: flow-root parent height behavior live in the playground below: