CSS Display — Block, Inline, Inline-Block, None & Visibility
Lesson 19: CSS Display — Block, Inline, Inline-Block, None & Visibility
Lesson Introduction
Welcome to Lesson 19! This lesson is about one of the most fundamental and powerful properties in all of CSS — the display property.
Every single element on a webpage has a display type. It controls how elements sit on the page — whether they stack on top of each other, sit side by side, or disappear from the page entirely.
Understanding display is the key that unlocks almost all layout work in CSS. When something looks wrong on your page — an element wrapping unexpectedly, two things not sitting next to each other, a gap where you don’t want one — the display property is almost always involved.
By the end of this lesson, you will be able to:
- Explain what the
displayproperty does and why it exists - Understand the difference between block and inline elements
- Use
display: block,display: inline, anddisplay: inline-block - Use
display: noneto completely remove elements from the page - Use
visibility: hiddento hide elements while keeping their space - Know when to use
display: nonevsvisibility: hidden - Build a real-world navigation bar using display manipulation
- Apply display changes to show and hide content dynamically
Prerequisite Concepts
What Is an HTML Element?
An HTML element is a piece of content on a webpage wrapped in tags. For example:
<p>This is a paragraph.</p>
<span>This is a span.</span>
<div>This is a div.</div>
Each of these elements has a default display type built into the browser. You didn’t have to write any CSS — the browser already decided whether it stacks vertically or sits inline. The display property lets you override that default.
What Does “Layout” Mean?
Layout is how elements are positioned and sized on the page. When you load a webpage, the browser reads your HTML and CSS from top to bottom, then decides:
- Where does each element start?
- How wide is it?
- Does it force the next element onto a new line?
The display property is the #1 tool that controls all of these decisions.
Part 1: The display Property — What It Is and Why It Exists
The Core Idea
Think of a webpage like a newspaper. Some content is laid out in big full-width blocks (like article headlines — they take the whole row). Other content flows within a line of text (like bold words or hyperlinks — they sit inside a sentence without breaking it).
CSS uses the same two ideas:
- Block — like a paragraph. Takes the full width. Starts on a new line.
- Inline — like a bold word. Only takes as much space as it needs. Sits inside a line.
The display property is how CSS controls this.
Every HTML Element Has a Default Display Value
The browser has built-in defaults for every HTML element. You can see this clearly:
Elements that default to block:
<div>, <p>, <h1> through <h6>, <ul>, <ol>, <li>, <form>, <header>, <footer>, <section>, <article>, <nav>, <main>, <aside>, <blockquote>, <hr>, <table>
Elements that default to inline:
<span>, <a>, <strong>, <em>, <b>, <i>, <u>, <img>, <input>, <button>, <label>, <code>, <abbr>
You can completely change an element’s default behaviour using the display property.
Part 2: display: block
What Is a Block Element?
A block element behaves like a full-width bar. Here is exactly what it does:
- It starts on a new line — nothing can sit to its left or right
- It stretches to fill the full available width (unless you set a specific width)
- It respects
width,height,padding,margin, andborderin all directions
Analogy: Imagine laying bricks in a single column. Each brick takes the full width of the wall and the next brick always goes below the previous one. That is how block elements work.
Quick Visual Demo
<!DOCTYPE html>
<html>
<head>
<style>
.box {
background-color: steelblue;
color: white;
padding: 10px;
margin: 5px 0;
}
</style>
</head>
<body>
<div class="box">Block 1</div>
<div class="box">Block 2</div>
<div class="box">Block 3</div>
</body>
</html>
Expected Visual Output: Three full-width blue bars stacked vertically, each on its own line:
[========== Block 1 ==========]
[========== Block 2 ==========]
[========== Block 3 ==========]
Forcing an Inline Element to Become Block
By default, <a> (links) are inline. You can force them to be block-level with display: block:
<!DOCTYPE html>
<html>
<head>
<style>
a {
display: block;
background-color: #e8f0fe;
padding: 10px 15px;
margin: 5px 0;
text-decoration: none;
color: #333;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</body>
</html>
Expected Visual Output: Three links stacked vertically, each taking the full width — like a vertical menu.
[Home ]
[About ]
[Contact ]
Why is this useful? Navigation menus, buttons that span the full width, and list items in a sidebar are all built this way.
Line-by-Line Explanation
display: block;— This tells the browser: “treat this<a>tag as if it were a<div>.” It now starts on its own line and expands to full width.padding: 10px 15px;— Adds space inside the link so it looks like a proper button/menu item.margin: 5px 0;— Adds a small gap between each link vertically.
Thinking Prompt: What happens if you remove
display: blockfrom these links? They will all collapse onto one line next to each other, as inline elements do by default.
Part 3: display: inline
What Is an Inline Element?
An inline element flows within text. Here is exactly what it does:
- It does NOT start on a new line — it sits next to other inline elements
- It only takes up as much width as its content — no more
- It ignores
widthandheightsettings - It respects horizontal padding and margin but vertical padding/margin is unreliable
Analogy: Think of words in a sentence. The word “hello” does not start a new line — it just sits next to the words before and after it. Inline elements work the same way.
Quick Visual Demo — Default Inline Behaviour
<!DOCTYPE html>
<html>
<head>
<style>
span {
background-color: #ffe57f;
padding: 4px;
}
</style>
</head>
<body>
<p>
This is a sentence with a
<span>highlighted word</span>
right in the middle of it.
</p>
</body>
</html>
Expected Visual Output:
The <span> sits inside the sentence, highlighted in yellow — it does NOT break onto its own line.
This is a sentence with a [highlighted word] right in the middle of it.
Forcing a Block Element to Become Inline
By default, <li> (list items) are block-level. You can make them sit side by side with display: inline:
<!DOCTYPE html>
<html>
<head>
<style>
li {
display: inline;
padding: 0 15px;
list-style: none;
background-color: #3366cc;
color: white;
}
</style>
</head>
<body>
<ul>
<li>Home</li>
<li>Products</li>
<li>Services</li>
<li>Contact</li>
</ul>
</body>
</html>
Expected Visual Output: All four list items appear on the same horizontal line:
[Home] [Products] [Services] [Contact]
Real-world use: This is exactly how horizontal navigation bars are built! Making
<li>itemsdisplay: inlineis a classic and fundamental technique.
The Limitation of display: inline
A key limitation: you cannot control width or height on inline elements. If you set width: 200px on a <span>, it is simply ignored.
span {
display: inline;
width: 200px; /* This will be IGNORED */
height: 50px; /* This will also be IGNORED */
}
This is where display: inline-block saves the day.
Part 4: display: inline-block
The Best of Both Worlds
display: inline-block is a hybrid. It gives you:
- Inline behaviour: Elements sit next to each other on the same line
- Block behaviour: You CAN set
width,height,padding, andmarginin all directions
Analogy: Think of inline-block like stamps in a row. Each stamp has a fixed, controlled size, but they all sit side by side without stacking vertically.
Comparison: inline vs inline-block vs block
| Property | inline |
inline-block |
block |
|---|---|---|---|
| Starts on new line? | No | No | Yes |
| Sits next to others? | Yes | Yes | No |
Respects width/height? |
No | Yes | Yes |
| Respects all margins? | Partially | Yes | Yes |
| Takes full width by default? | No | No | Yes |
Simple Example — Inline Elements With Dimensions
<!DOCTYPE html>
<html>
<head>
<style>
.box {
display: inline-block;
width: 120px;
height: 80px;
background-color: coral;
color: white;
text-align: center;
line-height: 80px; /* vertically centres text */
margin: 5px;
}
</style>
</head>
<body>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
</body>
</html>
Expected Visual Output: Three equal-sized coral coloured squares sitting side by side on the same row:
[ Box 1 ] [ Box 2 ] [ Box 3 ]
(120x80px) (120x80px) (120x80px)
Without display: inline-block, these <div> elements would stack vertically (because <div> is block by default). With inline-block, they sit side by side and still respect their fixed dimensions.
Real-World Example — A Navigation Bar with inline-block
<!DOCTYPE html>
<html>
<head>
<style>
nav ul {
list-style: none;
padding: 0;
margin: 0;
background-color: #222;
}
nav ul li {
display: inline-block;
}
nav ul li a {
display: block;
padding: 14px 20px;
color: white;
text-decoration: none;
}
nav ul li a:hover {
background-color: #555;
}
</style>
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</body>
</html>
Expected Visual Output: A dark horizontal navigation bar with four clickable links side by side. Each link lights up grey on hover.
[Home] [About] [Services] [Contact] (dark background)
Thinking Prompt: Why do we set
display: inline-blockon the<li>ANDdisplay: blockon the<a>inside it? The<li>goes inline so items sit side by side. The<a>goes block so its click area fills the entire<li>space — making the whole box clickable, not just the text.
inline-block for Card Grids
inline-block is also used to create grid-like card layouts:
<!DOCTYPE html>
<html>
<head>
<style>
.card {
display: inline-block;
width: 180px;
padding: 15px;
margin: 10px;
border: 1px solid #ccc;
border-radius: 6px;
vertical-align: top; /* aligns cards by their top edges */
background-color: #f9f9f9;
}
.card h3 {
margin: 0 0 8px 0;
font-size: 16px;
}
.card p {
margin: 0;
font-size: 13px;
color: #666;
}
</style>
</head>
<body>
<div class="card">
<h3>Card A</h3>
<p>Short description for this card.</p>
</div>
<div class="card">
<h3>Card B</h3>
<p>A slightly longer description that wraps over two lines.</p>
</div>
<div class="card">
<h3>Card C</h3>
<p>Another description here.</p>
</div>
</body>
</html>
Expected Visual Output: Three card boxes sitting side by side, each 180px wide, aligned by their top edges.
Note on
vertical-align: top: Wheninline-blockelements have different heights, they align at their bottom edges by default. Addingvertical-align: topaligns them at the top — much better for cards.
Part 5: display: none — Completely Removing Elements
What Does display: none Do?
display: none completely removes an element from the page. It is as if the element does not exist at all:
- It takes up no space
- It is invisible
- Other elements move in to fill the space it would have occupied
- The HTML code is still there in the file — it just is not rendered
Analogy: Imagine you wrote a word on a piece of paper and then used correction fluid (whiteout) to cover it. The underlying word is still there on the paper — but visually it is gone and the words after it have moved to fill the gap.
Simple Example — Hiding a Paragraph
<!DOCTYPE html>
<html>
<head>
<style>
p {
background-color: #dff0d8;
padding: 10px;
margin: 5px 0;
border: 1px solid #ccc;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<p>Paragraph 1 — I am visible.</p>
<p class="hidden">Paragraph 2 — I am HIDDEN! (display: none)</p>
<p>Paragraph 3 — I am visible.</p>
</body>
</html>
Expected Visual Output: Only paragraphs 1 and 3 appear. Paragraph 2 is completely gone — paragraph 3 moves up as if paragraph 2 was never there.
[Paragraph 1 — I am visible. ]
[Paragraph 3 — I am visible. ]
Real-World Use: Toggling Content with JavaScript
The most common real-world use of display: none is toggling content visibility with JavaScript. Here is a complete working example:
<!DOCTYPE html>
<html>
<head>
<style>
#secret-message {
display: none; /* hidden by default */
background-color: #fff3cd;
border: 1px solid #ffc107;
padding: 15px;
margin-top: 10px;
border-radius: 4px;
}
button {
padding: 10px 20px;
background-color: #3366cc;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background-color: #254ea6;
}
</style>
</head>
<body>
<button onclick="toggleMessage()">Show / Hide Message</button>
<div id="secret-message">
<strong>Surprise!</strong> This message was hidden. Now you can see it!
</div>
<script>
function toggleMessage() {
var msg = document.getElementById("secret-message");
if (msg.style.display === "none" || msg.style.display === "") {
msg.style.display = "block";
} else {
msg.style.display = "none";
}
}
</script>
</body>
</html>
Expected Visual Output:
- On page load: Only the button is visible
- After clicking the button: A yellow message box appears below
- After clicking again: The message disappears
Don’t worry if the JavaScript is new to you! The CSS part (
display: none/display: block) is what matters here. JavaScript is just flipping the display value back and forth. This pattern is used on almost every modern website.
display: none vs. display: block Toggling Pattern
This is the core pattern used by accordions, dropdowns, modals, and tabs on real websites:
/* Default: element is hidden */
.panel {
display: none;
}
/* When "active" class is added by JavaScript */
.panel.active {
display: block;
}
Part 6: visibility: hidden — Hiding Without Removing Space
What Does visibility: hidden Do?
visibility: hidden makes an element invisible but it still takes up its original space on the page. Other elements do NOT move to fill its gap.
| Property | Element Visible? | Takes Up Space? |
|---|---|---|
display: none |
No | No — space is removed |
visibility: hidden |
No | Yes — space remains |
Analogy: Imagine a reserved seat at a cinema. display: none is like removing the seat entirely — the row gets shorter. visibility: hidden is like the seat being there but draped with a cloth — you can’t see it, but it still occupies space. Nobody sits in it.
Direct Side-by-Side Comparison
<!DOCTYPE html>
<html>
<head>
<style>
.box {
display: inline-block;
width: 100px;
height: 60px;
background-color: steelblue;
color: white;
text-align: center;
line-height: 60px;
margin: 5px;
}
.display-none {
display: none;
}
.vis-hidden {
visibility: hidden;
}
</style>
</head>
<body>
<h3>With display: none (Box 2 removed):</h3>
<div class="box">Box 1</div>
<div class="box display-none">Box 2</div>
<div class="box">Box 3</div>
<h3>With visibility: hidden (Box 2 invisible but space kept):</h3>
<div class="box">Box 1</div>
<div class="box vis-hidden">Box 2</div>
<div class="box">Box 3</div>
</body>
</html>
Expected Visual Output:
First row — display: none:
[Box 1] [Box 3]
^ gap closed — Box 3 moved left
Second row — visibility: hidden:
[Box 1] [ ] [Box 3]
^ Box 2 is invisible but its space is still reserved
This is the key visual difference between the two techniques.
When to Use Each
Use display: none when:
- You want the element completely gone from the layout
- You are toggling menus, modals, tabs, or accordions
- You want surrounding elements to fill in the space
- You are making a responsive layout where certain elements don’t exist on mobile
Use visibility: hidden when:
- You want to hide an element but preserve the layout spacing around it
- You have a table or grid where removing cells would break alignment
- You want a “placeholder” element that keeps its space but is temporarily invisible
- Animating opacity (combined with
opacity: 0for smooth transitions)
visibility Values
The visibility property has three values:
| Value | Effect |
|---|---|
visible |
The element is visible (this is the default) |
hidden |
The element is invisible but still takes up space |
collapse |
For table rows/columns: removes them without affecting table layout |
.element { visibility: visible; } /* Default — visible */
.element { visibility: hidden; } /* Invisible but space preserved */
Combining display: none with Responsive Design
A very common real-world pattern is hiding navigation menus on mobile:
/* Mobile: hide the desktop nav */
.desktop-nav {
display: none;
}
/* On screens wider than 768px: show the desktop nav */
@media (min-width: 768px) {
.desktop-nav {
display: block;
}
}
This is how websites show a hamburger menu on phones but a full navigation bar on desktops.
Part 7: Other display Values (Quick Overview)
The display property has several more values worth knowing. These will each get their own detailed lessons, but here is a quick introduction so nothing surprises you:
display: flex
Turns an element into a flex container. All its children can be arranged in rows or columns with powerful alignment tools.
.container {
display: flex;
justify-content: space-between; /* distributes children evenly */
}
display: grid
Turns an element into a grid container. Children can be arranged in both rows AND columns simultaneously.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 equal columns */
}
display: table
Makes a non-table element behave like a <table>.
.fake-table {
display: table;
}
display: list-item
Makes an element behave like a <li> — adds a bullet point marker.
span {
display: list-item;
margin-left: 20px;
}
Focus for this lesson:
block,inline,inline-block, andnone. These are the four you will use daily.flexandgridare covered in depth in their own lessons.
Guided Practice Exercises
Exercise 1 — Block vs Inline Observation
Objective: See and feel the difference between block and inline behaviour.
Scenario: You are building a simple recipe page. Ingredients are listed with <span> elements but they need to stack vertically for readability on mobile.
Steps:
- Create an HTML file with five
<span>elements, each containing an ingredient name. - Style them with a light background and padding.
- Notice how they all sit on one line (inline default).
- Now add
display: block;to the span style. - Notice how they now each take their own line.
Starting code:
<!DOCTYPE html>
<html>
<head>
<style>
span.ingredient {
background-color: #e8f5e9;
padding: 6px 12px;
border: 1px solid #a5d6a7;
border-radius: 4px;
margin: 4px;
/* Try adding display: block; here */
}
</style>
</head>
<body>
<h2>Ingredients</h2>
<span class="ingredient">2 cups flour</span>
<span class="ingredient">1 tsp salt</span>
<span class="ingredient">3 eggs</span>
<span class="ingredient">1 cup milk</span>
<span class="ingredient">2 tbsp butter</span>
</body>
</html>
Step A — Expected output (no display: block):
All ingredients on one line (may wrap if the screen is narrow).
Step B — Expected output (with display: block):
[2 cups flour ]
[1 tsp salt ]
[3 eggs ]
[1 cup milk ]
[2 tbsp butter ]
Self-check Questions:
- Why do
<span>elements sit on one line withoutdisplay: block? - What happened to the spacing when you added
display: block? - Can you set
width: 300pxon a<span>with and withoutdisplay: block? What changes?
Exercise 2 — Building a Horizontal Navigation
Objective: Use display: inline to convert a vertical list into a horizontal nav bar.
Scenario: Your website has a list of navigation links. By default the <li> items stack vertically. You want them side by side.
Steps:
- Create an unordered list with 4 navigation links.
- Remove the bullet points with
list-style: none. - Add
display: inlineto the<li>elements. - Style the links to look like nav items.
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
}
ul.nav {
list-style: none;
padding: 0;
margin: 0;
background-color: #2c3e50;
}
ul.nav li {
display: inline; /* KEY CHANGE: list items go horizontal */
}
ul.nav li a {
display: inline-block;
padding: 14px 22px;
color: #ecf0f1;
text-decoration: none;
font-size: 14px;
}
ul.nav li a:hover {
background-color: #34495e;
}
</style>
</head>
<body>
<ul class="nav">
<li><a href="#">Home</a></li>
<li><a href="#">Portfolio</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Contact</a></li>
</ul>
</body>
</html>
Expected Visual Output: A dark horizontal navigation bar with four links side by side.
[Home] [Portfolio] [Blog] [Contact] (dark background)
Self-check Questions:
- What happens if you remove
display: inlinefrom the<li>elements? - Why did we use
display: inline-blockon the<a>tags instead ofdisplay: inline? - What would happen if you gave
<a>a width setting but it wasdisplay: inline?
Exercise 3 — Show and Hide a Panel
Objective: Use display: none and display: block to toggle a content panel.
Scenario: You are building an FAQ section. Each answer should be hidden by default and revealed when clicked.
Steps:
- Create a question heading and an answer paragraph.
- Set the answer to
display: noneinitially. - Add a button that toggles the answer’s visibility using JavaScript.
Solution:
<!DOCTYPE html>
<html>
<head>
<style>
.faq-item {
border: 1px solid #ddd;
border-radius: 6px;
margin: 10px 0;
overflow: hidden;
}
.faq-question {
background-color: #f7f7f7;
padding: 14px 16px;
cursor: pointer;
font-weight: bold;
display: flex;
justify-content: space-between;
}
.faq-question:hover {
background-color: #eaeaea;
}
.faq-answer {
display: none; /* hidden by default */
padding: 14px 16px;
background-color: #fff;
color: #444;
border-top: 1px solid #ddd;
line-height: 1.6;
}
</style>
</head>
<body>
<h2>Frequently Asked Questions</h2>
<div class="faq-item">
<div class="faq-question" onclick="toggleAnswer(this)">
What is CSS? <span>+</span>
</div>
<div class="faq-answer">
CSS stands for Cascading Style Sheets. It is used to control the
visual appearance of HTML elements — things like colour, font size,
spacing, and layout.
</div>
</div>
<div class="faq-item">
<div class="faq-question" onclick="toggleAnswer(this)">
Why is the display property important? <span>+</span>
</div>
<div class="faq-answer">
The display property controls how elements are arranged on the page.
It determines whether an element takes a full row (block), sits inline
with text, or is removed from the layout entirely.
</div>
</div>
<script>
function toggleAnswer(questionElement) {
var answer = questionElement.nextElementSibling;
if (answer.style.display === "block") {
answer.style.display = "none";
} else {
answer.style.display = "block";
}
}
</script>
</body>
</html>
Expected Visual Output:
- On load: Two FAQ question bars visible; answers hidden
- After clicking a question: Its answer slides open below
- After clicking again: Answer hides
Self-check Questions:
- What property starts each answer as invisible?
- If you replaced
display: nonewithvisibility: hidden, would the answers still appear to “collapse”? What would change?
What-if challenge: Can you make both answers open at the same time? (Yes — each button controls its own sibling answer independently.)
Mini Project: “Interactive Profile Page with Show/Hide Sections”
Project Goal
Build a profile page that uses all the display techniques from this lesson:
- A horizontal nav bar using
display: inline-block - Profile cards using
display: inline-block - Collapsible “bio” sections using
display: none/display: blocktoggling - A footer using
display: blockelements
Stage 1 — Horizontal Navigation
<!DOCTYPE html>
<html>
<head>
<title>My Profile</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; background: #f4f4f4; color: #333; }
/* Navigation */
nav {
background-color: #1a1a2e;
}
nav ul {
list-style: none;
padding: 0;
margin: 0;
}
nav ul li {
display: inline-block; /* Horizontal layout */
}
nav ul li a {
display: block;
padding: 16px 24px;
color: #eee;
text-decoration: none;
font-size: 14px;
letter-spacing: 0.5px;
}
nav ul li a:hover {
background-color: #16213e;
color: #4fc3f7;
}
</style>
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">Skills</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</body>
</html>
Milestone Output: A dark professional navigation bar with four horizontally aligned links.
Stage 2 — Profile Cards Using inline-block
Add inside <body> after the nav:
<section style="padding: 40px; text-align: center;">
<h1 style="margin-bottom: 30px;">Meet the Team</h1>
<div class="profile-card">
<div class="avatar" style="background-color: #4fc3f7;"></div>
<h3>Alex Kim</h3>
<p>Lead Developer</p>
<button onclick="toggleBio('bio1')">View Bio</button>
<p class="bio" id="bio1">
Alex has 8 years of experience building scalable web applications.
Passionate about clean code and great user experiences.
</p>
</div>
<div class="profile-card">
<div class="avatar" style="background-color: #f48fb1;"></div>
<h3>Jordan Lee</h3>
<p>UI/UX Designer</p>
<button onclick="toggleBio('bio2')">View Bio</button>
<p class="bio" id="bio2">
Jordan creates intuitive, beautiful interfaces. Believes that
great design is invisible — it just works.
</p>
</div>
<div class="profile-card">
<div class="avatar" style="background-color: #a5d6a7;"></div>
<h3>Morgan Chen</h3>
<p>Data Scientist</p>
<button onclick="toggleBio('bio3')">View Bio</button>
<p class="bio" id="bio3">
Morgan transforms raw data into meaningful insights that drive
product decisions and business strategy.
</p>
</div>
</section>
Add the card styles:
.profile-card {
display: inline-block; /* Cards sit side by side */
vertical-align: top;
width: 220px;
background-color: white;
border: 1px solid #ddd;
border-radius: 10px;
padding: 20px;
margin: 10px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.profile-card .avatar {
width: 70px;
height: 70px;
border-radius: 50%;
margin: 0 auto 12px;
}
.profile-card h3 {
margin: 0 0 4px;
font-size: 16px;
}
.profile-card p {
color: #777;
font-size: 13px;
margin: 0 0 10px;
}
.profile-card button {
padding: 7px 14px;
background-color: #1a1a2e;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
margin-bottom: 10px;
}
.profile-card button:hover {
background-color: #16213e;
}
.bio {
display: none; /* Hidden by default */
font-size: 12px;
color: #555;
line-height: 1.5;
text-align: left;
background-color: #f9f9f9;
padding: 10px;
border-radius: 4px;
margin-top: 8px;
}
Stage 3 — The Toggle Script
Add before </body>:
<script>
function toggleBio(id) {
var bio = document.getElementById(id);
if (bio.style.display === "block") {
bio.style.display = "none";
} else {
bio.style.display = "block";
}
}
</script>
Stage 4 — Complete Final Code
<!DOCTYPE html>
<html>
<head>
<title>Team Profile Page</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; background: #f4f4f4; color: #333; }
nav { background-color: #1a1a2e; }
nav ul { list-style: none; }
nav ul li { display: inline-block; }
nav ul li a {
display: block;
padding: 16px 24px;
color: #eee;
text-decoration: none;
font-size: 14px;
}
nav ul li a:hover { background-color: #16213e; color: #4fc3f7; }
section { padding: 40px; text-align: center; }
section h1 { margin-bottom: 30px; font-size: 24px; }
.profile-card {
display: inline-block;
vertical-align: top;
width: 220px;
background-color: white;
border: 1px solid #ddd;
border-radius: 10px;
padding: 20px;
margin: 10px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.profile-card .avatar {
width: 70px;
height: 70px;
border-radius: 50%;
margin: 0 auto 12px;
}
.profile-card h3 { margin: 0 0 4px; font-size: 16px; }
.profile-card > p { color: #777; font-size: 13px; margin: 0 0 10px; }
.profile-card button {
padding: 7px 14px;
background-color: #1a1a2e;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
margin-bottom: 10px;
}
.profile-card button:hover { background-color: #16213e; }
.bio {
display: none;
font-size: 12px;
color: #555;
line-height: 1.5;
text-align: left;
background-color: #f9f9f9;
padding: 10px;
border-radius: 4px;
margin-top: 8px;
}
footer {
display: block;
background-color: #1a1a2e;
color: #aaa;
text-align: center;
padding: 20px;
font-size: 13px;
margin-top: 30px;
}
</style>
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Projects</a></li>
<li><a href="#">Skills</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<section>
<h1>Meet the Team</h1>
<div class="profile-card">
<div class="avatar" style="background-color: #4fc3f7;"></div>
<h3>Alex Kim</h3>
<p>Lead Developer</p>
<button onclick="toggleBio('bio1')">View Bio</button>
<p class="bio" id="bio1">
Alex has 8 years of experience building scalable web applications.
Passionate about clean code and great user experiences.
</p>
</div>
<div class="profile-card">
<div class="avatar" style="background-color: #f48fb1;"></div>
<h3>Jordan Lee</h3>
<p>UI/UX Designer</p>
<button onclick="toggleBio('bio2')">View Bio</button>
<p class="bio" id="bio2">
Jordan creates intuitive, beautiful interfaces. Believes that
great design is invisible — it just works.
</p>
</div>
<div class="profile-card">
<div class="avatar" style="background-color: #a5d6a7;"></div>
<h3>Morgan Chen</h3>
<p>Data Scientist</p>
<button onclick="toggleBio('bio3')">View Bio</button>
<p class="bio" id="bio3">
Morgan transforms raw data into meaningful insights that drive
product decisions and business strategy.
</p>
</div>
</section>
<footer>
© 2025 Team Profile Page. All rights reserved.
</footer>
<script>
function toggleBio(id) {
var bio = document.getElementById(id);
if (bio.style.display === "block") {
bio.style.display = "none";
} else {
bio.style.display = "block";
}
}
</script>
</body>
</html>
Final Output: A complete team profile page with a dark horizontal navigation bar, three profile cards side by side, expandable bio sections, and a footer.
Reflection Questions:
- The nav bar uses
display: inline-blockon<li>— why not justdisplay: inline? - What happens visually when you click “View Bio” on one card and then another?
- Change
.biofromdisplay: nonetovisibility: hidden. How does the card layout change? - Why does the footer use
display: blockexplicitly even though<footer>is already block by default?
Optional Extensions:
- Change the “View Bio” button text to “Hide Bio” when the bio is open, and back to “View Bio” when closed
- Add
transition: all 0.3s ease;to.bio— does anything change? (Hint: transitions don’t work ondisplay. This is a common limitation.) - Use
visibility: hiddenandopacity: 0together with a CSS transition for a smooth fade effect instead
Common Beginner Mistakes
Mistake 1: Setting width or height on a pure inline element
Wrong:
span {
display: inline;
width: 200px; /* IGNORED on inline elements */
height: 50px; /* IGNORED on inline elements */
}
Fix: Use display: inline-block if you need dimensions:
span {
display: inline-block; /* Now width and height work */
width: 200px;
height: 50px;
}
Mistake 2: Confusing display: none with visibility: hidden
Wrong thinking: “Both hide the element, so they are the same.”
Reality: They are very different:
/* Removes element completely — other content moves in */
.gone { display: none; }
/* Invisible but the SPACE is still there — other content stays put */
.invisible { visibility: hidden; }
Mistake 3: Forgetting that <li> items have default display: list-item
li {
display: inline; /* Works, but also removes the bullet point */
}
When you change <li> to display: inline, the bullet marker disappears automatically. If you want the bullet to stay, you cannot use display: inline. Use list-style: none explicitly when you do not want bullets.
Mistake 4: Not removing bullet points when making horizontal nav
Wrong (looks messy — bullets appear):
li {
display: inline;
/* Forgot to remove bullets! */
}
Correct:
ul {
list-style: none; /* Removes bullets from the whole list */
padding: 0;
margin: 0;
}
li {
display: inline;
}
Mistake 5: Using display: none to “style” something instead of CSS
Wrong approach: Hiding all elements and only showing one — instead of simply writing CSS for the one you want:
/* Don't do this when CSS can solve the visual problem */
.red-version { display: none; }
.blue-version { display: block; }
display: none is for dynamic behaviour (toggling with JavaScript) or responsive design, not for choosing between two static designs.
Mistake 6: Expecting display: none to remove something from screen readers
Wrong assumption: “display: none hides content from everyone.”
Reality: display: none does remove content from screen readers too. But if you want content to be visually hidden but still accessible to screen readers, use this pattern instead:
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
}
This is an accessibility technique used for things like icon button labels that sighted users don’t need to see but screen-reader users do.
Mistake 7: The inline-block whitespace gap
When you write inline-block elements in separate lines of HTML, a small whitespace gap appears between them. This is because the space (or newline) between HTML tags is rendered as a text space character.
HTML that causes a gap:
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
The gap appears because the newline between </div> and <div> is treated as a space.
Quick fixes:
/* Fix 1: Set font-size to 0 on the parent */
.parent {
font-size: 0;
}
.box {
display: inline-block;
font-size: 16px; /* Reset font size on children */
}
/* Fix 2: Use negative margin (less clean) */
.box {
display: inline-block;
margin-right: -4px;
}
Note: Flexbox (
display: flex) does not have this whitespace gap problem, which is one reason modern layouts prefer it overinline-blockfor complex grids.
Reflection Questions
- What is the fundamental difference between
display: blockanddisplay: inline? - Why would you use
display: inline-blockinstead of justdisplay: inline? - An element has
display: none. Does it still exist in the HTML? Can JavaScript still find it? - You have a table with 5 columns. You hide one column with
display: none— the other columns shift left. You hide it withvisibility: hidden— the columns stay in place. Why? - If you want a horizontal navigation bar using
<li>items, which display value do you set on the<li>—inlineorblock? Why? - Why does
display: noneremove content from screen readers, and what is the alternative if you want to hide something only visually? - You set
width: 300pxon a<span>. Nothing happens. What do you need to change and why?
Completion Checklist
- I understand that every HTML element has a default display value
- I can list at least 5 elements that default to
blockand 5 that default toinline - I understand what
display: blockdoes — full width, new line, respects all dimensions - I understand what
display: inlinedoes — flows in text, no forced new line, ignores width/height - I understand what
display: inline-blockdoes — sits inline but respects all dimensions - I can use
display: inlineto convert<li>items into a horizontal navigation - I can use
display: inline-blockto create side-by-side cards with controlled sizes - I understand that
display: nonecompletely removes an element from the layout - I understand that
visibility: hiddenhides an element but preserves its space - I can explain the exact difference between
display: noneandvisibility: hidden - I have completed all three guided exercises
- I have built the team profile page mini project
- I understand why removing focus outlines with
display: noneimpacts accessibility - I know about the
inline-blockwhitespace gap and at least one way to fix it
Lesson Summary
All Key Display Values at a Glance
| Value | Starts New Line? | Respects Width/Height? | Takes Up Space When Hidden? |
|---|---|---|---|
block |
Yes | Yes | Yes |
inline |
No | No | Yes |
inline-block |
No | Yes | Yes |
none |
— | — | No |
display: none vs visibility: hidden
display: none |
visibility: hidden |
|
|---|---|---|
| Visible? | No | No |
| Takes up space? | No | Yes |
| Other elements move to fill gap? | Yes | No |
| Screen reader? | Removed | Removed |
The Display Override Pattern
/* Making block elements go inline */
li { display: inline; } /* For horizontal nav */
h1 { display: inline; } /* For inline headings */
/* Making inline elements go block */
a { display: block; } /* For full-width links */
span { display: block; } /* For stacked spans */
img { display: block; } /* For centred images */
/* The hybrid: inline but with dimensions */
div { display: inline-block; } /* For side-by-side cards */
li { display: inline-block; } /* For nav items with padding */
The Toggle Pattern (for JavaScript)
/* Default: hidden */
.panel { display: none; }
/* When activated */
.panel.active { display: block; }
Real-World Applications
- Navigation bars:
display: inlineordisplay: inline-blockon<li>elements - Card grids:
display: inline-blockon card containers - Dropdowns and modals:
display: nonetoggled todisplay: block - Responsive design:
display: noneto hide content on mobile/desktop - Form layouts:
display: blockon labels and inputs for vertical stacking - Horizontal menus from vertical lists:
display: inlineon<li>elements - Accessibility labels: Screen-reader-only classes using
position: absoluteinstead ofdisplay: none
You have completed Lesson 19: CSS Display. In the next lesson, you will explore CSS Max-Width — controlling how wide elements can grow on large screens.