CSS · Lesson 23

CSS z-index · Controlling the Stack Order of Elements

11 phases  ·  Build: Stage 1: Setup · The Card Structure

👋 Welcome to Lesson 23

Have you ever noticed how a dropdown menu appears on top of the rest of the page content? Or how a pop-up dialog box sits in front of everything else? Or how a "Back to Top" button floats visibly over images and text without disappearing behind them?

That visual "who is on top" behaviour is controlled by a CSS property called z-index.

In this lesson you will learn exactly what z-index is, why it exists, how it works, what rules control it, and how to use it confidently in real web pages. We will build up from the very basics to a realistic mini-project step by step, with every single concept explained and demonstrated with examples.

By the end of this lesson you will be able to:

  • Understand how browsers stack elements on top of each other by default
  • Use z-index to control which element appears "in front" of another
  • Understand exactly when z-index works and when it does NOT work (and why)
  • Recognise common beginner mistakes and fix them
  • Apply z-index in realistic layouts like tooltips, overlays, modals, and sticky headers

📚 11 phases🏗️ Stage 1: Setup · The Card Structure🌐 GitHub Pages
Phase 1 of 11
Lesson Introduction

Have you ever noticed how a dropdown menu appears on top of the rest of the page content? Or how a pop-up dialog box sits in front of everything else? Or how a "Back to Top" button floats visibly over images and text without disappearing behind them?

That visual "who is on top" behaviour is controlled by a CSS property called z-index.

In this lesson you will learn exactly what z-index is, why it exists, how it works, what rules control it, and how to use it confidently in real web pages. We will build up from the very basics to a realistic mini-project step by step, with every single concept explained and demonstrated with examples.

By the end of this lesson you will be able to:

  • Understand how browsers stack elements on top of each other by default
  • Use z-index to control which element appears "in front" of another
  • Understand exactly when z-index works and when it does NOT work (and why)
  • Recognise common beginner mistakes and fix them
  • Apply z-index in realistic layouts like tooltips, overlays, modals, and sticky headers

✏️ Your Task
Practise what you just learned about Lesson Introduction. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 2 of 11
Prerequisite Concepts

Before we dive into z-index, you need to understand a few foundational ideas. If you already know these, feel free to skim · but even a quick refresh is helpful.

What is CSS Positioning?

By default, HTML elements sit one after another on the page, flowing from top to bottom. This is called normal document flow.

But CSS has a property called position that lets you take elements out of that normal flow and place them wherever you like on the page. The position property has these values:

  • static · The default. The element stays in normal flow. No special positioning.
  • relative · The element stays in normal flow, but you can offset it from its original spot using top, right, bottom, left.
  • absolute · The element is removed from normal flow and positioned relative to its nearest positioned ancestor (or to the <body> if there is none).
  • fixed · The element is removed from normal flow and positioned relative to the browser window. It stays in place even when you scroll.
  • sticky · A mix of relative and fixed. It acts like relative until you scroll past a certain point, then it sticks in place.

Why does this matter for z-index? Because z-index ONLY works on positioned elements · that is, elements with position set to relative, absolute, fixed, or sticky. It does NOT work on position: static elements (the default).

What is the Z-Axis?

Your screen has two visible dimensions:

  • X-axis · going left and right (horizontal)
  • Y-axis · going up and down (vertical)

But there is also a third dimension:

  • Z-axis · going toward you and away from you (depth, or "in front of" vs "behind")

Although your screen is flat, browsers simulate this depth using a stacking order · deciding which element should appear "on top" when two elements occupy the same space on screen.

Think of it like stacking sheets of paper on a desk. The paper on top covers any paper underneath it. z-index lets you choose which "sheet" goes on top.


✏️ Your Task
Practise what you just learned about Prerequisite Concepts. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 3 of 11
Part 1: Conceptual Understanding · What is `z-index`?

The Simple Explanation

z-index is a CSS property that controls the stack order of a positioned element. An element with a higher z-index value will appear in front of an element with a lower z-index value when they overlap.

Syntax:

css
selector {
  position: relative; /* z-index requires a position value other than static */
  z-index: 1;         /* any whole number — positive, zero, or negative */
}

The Real-Life Analogy

Imagine you have a stack of papers on a desk:

  • Paper at the bottom of the stack is at the lowest level → z-index: 1
  • Paper in the middle is → z-index: 2
  • Paper on top, covering everything → z-index: 3

The paper with the highest z-index number is "closest to you" (on top). The one with the lowest number is "furthest from you" (at the bottom).

Default Stacking · What Happens Without z-index

Without z-index, when two positioned elements overlap, the browser stacks them in the order they appear in the HTML. Elements that come later in the HTML sit on top of elements that come earlier.

Example · Default HTML stacking order:

html
<!DOCTYPE html>
<html>
<head>
<style>
  .box {
    width: 200px;
    height: 200px;
    position: absolute;
  }

  .box-one {
    background-color: coral;
    top: 50px;
    left: 50px;
  }

  .box-two {
    background-color: steelblue;
    top: 100px;   /* overlaps box-one */
    left: 100px;
  }
</style>
</head>
<body>

  <div class="box box-one">Box One (coral)</div>
  <div class="box box-two">Box Two (blue)</div>

</body>
</html>

Expected Output:

  • Box One (coral) is drawn first.
  • Box Two (blue) is drawn on top of it, partially covering it.
  • The blue box appears "in front" of the coral box simply because it comes later in the HTML.

Thinking Prompt: What would happen if you swapped the order of the two <div> elements in the HTML? Which box would appear on top?


✏️ Your Task
Practise what you just learned about : Conceptual Understanding · What is z-index?. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 4 of 11
Part 2: Using `z-index` to Control Stack Order

The Basic Rule

To give an element a z-index, you must first give it a position value that is NOT static. Then set z-index to any whole number.

css
.element {
  position: relative; /* or absolute, fixed, or sticky */
  z-index: 10;
}
  • Higher number = in front
  • Lower number = behind
  • Negative numbers are allowed · they place the element behind even normal (non-positioned) content

Simple Example · z-index in action

html
<!DOCTYPE html>
<html>
<head>
<style>
  .box {
    width: 200px;
    height: 200px;
    position: absolute;
  }

  .box-one {
    background-color: coral;
    top: 50px;
    left: 50px;
    z-index: 2;        /* higher number — this will be ON TOP */
  }

  .box-two {
    background-color: steelblue;
    top: 100px;
    left: 100px;
    z-index: 1;        /* lower number — this will be BEHIND */
  }
</style>
</head>
<body>

  <div class="box box-one">Box One (coral) z-index: 2</div>
  <div class="box box-two">Box Two (blue) z-index: 1</div>

</body>
</html>

Expected Output:

  • Even though Box Two comes AFTER Box One in the HTML (and would normally be on top), the z-index values override that default.
  • Box One (coral) now appears ON TOP because its z-index: 2 is greater than z-index: 1.

Key Insight: z-index overrides the default HTML source-order stacking. Higher number = winner.

Example 2 · Three Overlapping Elements

html
<!DOCTYPE html>
<html>
<head>
<style>
  .box {
    width: 150px;
    height: 150px;
    position: absolute;
    color: white;
    font-size: 18px;
    padding: 10px;
  }

  #red {
    background-color: crimson;
    top: 40px;
    left: 40px;
    z-index: 1;
  }

  #green {
    background-color: seagreen;
    top: 80px;
    left: 80px;
    z-index: 3;    /* HIGHEST — will be on top */
  }

  #blue {
    background-color: steelblue;
    top: 120px;
    left: 120px;
    z-index: 2;
  }
</style>
</head>
<body>

  <div id="red">Red (z:1)</div>
  <div id="green">Green (z:3)</div>
  <div id="blue">Blue (z:2)</div>

</body>
</html>

Expected Output:

  • Green box is fully visible on top (z-index: 3 · highest)
  • Blue box is in the middle (z-index: 2)
  • Red box is at the bottom, mostly covered (z-index: 1 · lowest)

Thinking Prompt: What would happen if you changed the green box's z-index from 3 to -1? Try to guess before experimenting.


✏️ Your Task
Practise what you just learned about : Using z-index to Control Stack Order. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 5 of 11
Part 3: The Critical Rule · z-index Only Works with Positioned Elements

This is the most important rule beginners overlook, and it causes a lot of confusion.

The Rule

z-index has no effect on an element with position: static (the default position value).

css
/* This does NOTHING — static is the default */
.box {
  z-index: 999;   /* ignored completely because position is static by default */
}

/* This WORKS */
.box {
  position: relative;   /* now z-index is respected */
  z-index: 999;
}

Why Does This Rule Exist?

CSS's stacking mechanism only activates for elements that have been "taken out of" or "placed in" a specific layer context. Elements with position: static are just in the normal document flow · they don't participate in the z-axis stacking game at all.

Think of it this way: normal flow elements are like furniture sitting on the floor of a room. Positioned elements are like objects you've picked up and are holding at different heights. Only the objects you're holding can be at different heights · the furniture on the floor is just on the floor.

Demonstration of the Rule

html
<!DOCTYPE html>
<html>
<head>
<style>
  .box {
    width: 200px;
    height: 200px;
  }

  .box-a {
    background-color: coral;
    /* position: static is the default — z-index won't work */
    z-index: 999;      /* This is IGNORED */
    margin-bottom: -50px;  /* just to cause overlap for demonstration */
  }

  .box-b {
    background-color: steelblue;
    position: relative;    /* THIS activates z-index */
    z-index: 1;
  }
</style>
</head>
<body>

  <div class="box box-a">Box A (static, z-index: 999 — IGNORED)</div>
  <div class="box box-b">Box B (relative, z-index: 1 — WORKS)</div>

</body>
</html>

Expected Output:

  • Box B (blue) appears ON TOP of Box A (coral) despite Box A having z-index: 999.
  • This is because Box A's z-index is ignored · it has no position value.
  • Box B has position: relative so its z-index: 1 IS respected.

Common Beginner Mistake: Setting a high z-index but forgetting to set a position property · and then wondering why it doesn't work!


✏️ Your Task
Practise what you just learned about : The Critical Rule · z-index Only Works with Positioned Elements. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 6 of 11
Part 4: Stacking Context · The Advanced Rule

What is a Stacking Context?

A stacking context is like a self-contained "arena" where elements compete against each other for position on the z-axis. Elements inside one stacking context cannot overlap elements in a different stacking context based on their individual z-index values · the entire context is treated as a single unit.

This can be confusing, but the analogy makes it clear:

The Folder Analogy:

Imagine you have two physical folders of papers on a desk:

  • Folder A is the bottom folder.
  • Folder B is placed on top of Folder A.

Inside Folder A, you can arrange the papers in any order you want using their own numbering system. Inside Folder B, the same. BUT, no matter how high you number a paper inside Folder A, it can NEVER appear above ANY paper inside Folder B · because the entire Folder A is underneath Folder B.

This is exactly how stacking contexts work in CSS.

What Creates a New Stacking Context?

A new stacking context is created whenever an element has:

  • position set to absolute, relative, fixed, or sticky AND a z-index value that is NOT auto
  • opacity less than 1 (e.g., opacity: 0.9)
  • transform, filter, perspective, or clip-path applied
  • will-change set to certain values
  • Being a flex or grid container child with a z-index that is not auto

For beginners, the most common cause is: a positioned element with a specific z-index value creates a new stacking context for its children.

Stacking Context Example · The Trap

html
<!DOCTYPE html>
<html>
<head>
<style>
  .context-a {
    position: relative;
    z-index: 1;           /* Creates a new stacking context */
    background-color: lightcoral;
    width: 300px;
    height: 200px;
    padding: 10px;
  }

  .context-b {
    position: relative;
    z-index: 2;           /* context-b is ABOVE context-a */
    background-color: lightblue;
    width: 300px;
    height: 200px;
    margin-top: -100px;   /* overlap deliberately */
    padding: 10px;
  }

  .child-of-a {
    position: relative;
    z-index: 9999;        /* VERY high — but trapped inside context-a */
    background-color: gold;
    width: 150px;
    height: 80px;
  }
</style>
</head>
<body>

  <div class="context-a">
    Context A (z-index: 1)
    <div class="child-of-a">Child of A (z-index: 9999)</div>
  </div>

  <div class="context-b">
    Context B (z-index: 2) — I cover everything in Context A
  </div>

</body>
</html>

Expected Output:

  • Context B (blue) covers Context A (coral) completely · including the gold "Child of A" box.
  • Even though the child has z-index: 9999, it CANNOT escape its parent's stacking context.
  • Context A as a whole is at z-index: 1, and Context B is at z-index: 2. So ALL of Context A's children, regardless of their own z-index values, sit below Context B.

Real World Analogy: No matter how important a piece of paper in Folder A is, if Folder B is placed on top of Folder A on the desk, every piece of paper in Folder A is covered.


✏️ Your Task
Practise what you just learned about : Stacking Context · The Advanced Rule. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 7 of 11
Part 5: The `z-index: auto` Value

When you set z-index: auto (or don't set z-index at all on a positioned element), the element does NOT create a new stacking context. It participates in its parent's stacking context instead.

css
.element {
  position: relative;
  z-index: auto;   /* same as not setting z-index — does NOT create a new stacking context */
}

vs.

css
.element {
  position: relative;
  z-index: 0;   /* creates a new stacking context, even though the value is 0 */
}

This is a subtle difference. z-index: 0 and z-index: auto behave similarly for the element itself, but z-index: 0 creates a new stacking context while z-index: auto does not.


✏️ Your Task
Practise what you just learned about : The z-index: auto Value. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 8 of 11
Part 6: Negative z-index Values

You can use negative z-index values to push an element behind its parent or behind normal document flow content.

html
<!DOCTYPE html>
<html>
<head>
<style>
  .container {
    position: relative;
    background-color: lightgrey;
    width: 300px;
    height: 200px;
    padding: 20px;
  }

  .behind {
    position: absolute;
    z-index: -1;           /* pushed BEHIND the parent */
    background-color: tomato;
    width: 250px;
    height: 150px;
    top: 30px;
    left: 30px;
  }

  p {
    position: relative;    /* This text is above z-index: -1 */
    z-index: 0;
  }
</style>
</head>
<body>

  <div class="container">
    <p>This text is in normal flow inside the container.</p>
    <div class="behind">I am behind the container background (z-index: -1)</div>
  </div>

</body>
</html>

Expected Output:

  • The red .behind box is pushed behind the grey container's background.
  • The paragraph text sits in front of everything.
  • The red box is barely visible (or not at all) peeking out from behind the grey container.

Practical Use Case for Negative z-index:

  • Placing a decorative background shape behind the main content
  • Creating a "watermark" effect
  • Building layered backgrounds without extra wrapper elements

✏️ Your Task
Practise what you just learned about : Negative z-index Values. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 9 of 11
Part 7: CSS `z-index` Property Reference

Here is a complete reference of all valid values for the z-index property:

ValueWhat It Does
autoDefault. The element's stack level is 0. Does NOT create a new stacking context.
Any positive integer (e.g., 1, 5, 100)Places the element higher in the stack than elements with lower values. Creates a new stacking context.
0Stack level is 0. Creates a new stacking context.
Any negative integer (e.g., -1, -5)Places the element below elements with a value of 0 or higher.
inheritInherits the z-index value from the parent element.
initialResets to the default value (auto).

✏️ Your Task
Practise what you just learned about : CSS z-index Property Reference. Open your editor, type the examples above by hand, modify them, and observe what changes.
Phase 10 of 11
Part 8: Guided Practice Exercises
🎯 Your Challenge

Exercise 1 · Basic Stack Control (Warm-Up)

Objective: Make the green box appear on top of the red box.

Scenario: You have two overlapping coloured boxes. By default the red one appears on top. Use z-index to reverse this so green is on top.

Starter Code:

✏️ Task
Practise what you just learned about : Guided Practice Exercises. Open your editor, type the examples above by hand, modify them, and observe what changes.
html
<!DOCTYPE html>
<html>
<head>
<style>
  .box {
    width: 200px;
    height: 200px;
    position: absolute;
  }

  #red-box {
    background-color: crimson;
    top: 20px;
    left: 20px;
    /* Add z-index here */
  }

  #green-box {
    background-color: seagreen;
    top: 70px;
    left: 70px;
    /* Add z-index here */
  }
</style>
</head>
<body>
  <div id="red-box">Red Box</div>
  <div id="green-box">Green Box</div>
</body>
</html>

Steps:

  1. Add z-index: 1 to #red-box.
  2. Add z-index: 2 to #green-box.
  3. Save and open in a browser.
  4. Green should now sit on top of red.

Expected Output: Green box fully visible, covering part of the red box.

Solution:

css
#red-box {
  background-color: crimson;
  top: 20px;
  left: 20px;
  z-index: 1;
}

#green-box {
  background-color: seagreen;
  top: 70px;
  left: 70px;
  z-index: 2;  /* higher = on top */
}

Self-Check Questions:

  • What would happen if both boxes had z-index: 1? (The HTML source order would decide · green appears on top since it comes later.)
  • What would happen if you removed position: absolute from both boxes and kept the z-index values? (z-index would stop working · it requires a positioned element.)

Exercise 2 · Tooltip Overlay

Objective: Create a tooltip that appears in front of nearby text and images.

Scenario: You have a word on a page with a tooltip. When you hover over the word, the tooltip box must appear in front of everything else on the page.

Starter Code:

html
<!DOCTYPE html>
<html>
<head>
<style>
  body {
    font-family: Arial, sans-serif;
    padding: 40px;
  }

  .tooltip-container {
    display: inline-block;
    position: relative;   /* needed so the tooltip can be positioned relative to this */
  }

  .tooltip-trigger {
    background-color: steelblue;
    color: white;
    padding: 5px 10px;
    border-radius: 4px;
    cursor: pointer;
  }

  .tooltip-box {
    display: none;           /* hidden by default */
    position: absolute;
    top: -50px;
    left: 0;
    background-color: #333;
    color: white;
    padding: 8px 12px;
    border-radius: 4px;
    white-space: nowrap;
    /* Add z-index here to ensure it appears over everything */
  }

  .tooltip-container:hover .tooltip-box {
    display: block;          /* show on hover */
  }

  .overlap-box {
    background-color: lightcoral;
    padding: 20px;
    margin-top: -10px;       /* deliberately overlapping to test z-index */
    position: relative;
    z-index: 5;
  }
</style>
</head>
<body>

  <div class="overlap-box">
    This red box has z-index: 5 — it might cover the tooltip if z-index is wrong!
  </div>

  <div class="tooltip-container">
    <span class="tooltip-trigger">Hover over me</span>
    <div class="tooltip-box">I am the tooltip!</div>
  </div>

</body>
</html>

Steps:

  1. Hover over the "Hover over me" button.
  2. The tooltip may appear behind the red box.
  3. Add z-index: 10 to .tooltip-box.
  4. Hover again · the tooltip should now appear in front of the red box.

Expected Output: Tooltip box appears clearly in front of the red overlap box.

Solution Addition:

css
.tooltip-box {
  /* ... existing styles ... */
  z-index: 10;   /* higher than the overlap-box's z-index: 5 */
}

Exercise 3 · Background Decoration with Negative z-index

Objective: Place a large decorative circle BEHIND a content card.

Scenario: A profile card has a decorative coloured circle in the background. The circle should sit behind the card text.

html
<!DOCTYPE html>
<html>
<head>
<style>
  .card {
    position: relative;
    width: 280px;
    background-color: white;
    border-radius: 12px;
    padding: 30px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    overflow: hidden;
    margin: 60px auto;
  }

  .card-content {
    position: relative;
    z-index: 1;   /* sits above the decoration */
  }

  .background-circle {
    position: absolute;
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background-color: lightblue;
    top: -60px;
    right: -60px;
    z-index: -1;   /* pushed behind the card content */
  }

  h2 { margin: 0 0 10px 0; }
  p  { color: #555; }
</style>
</head>
<body>

  <div class="card">
    <div class="background-circle"></div>
    <div class="card-content">
      <h2>Jane Doe</h2>
      <p>Web Developer</p>
      <p>Lagos, Nigeria</p>
    </div>
  </div>

</body>
</html>

Expected Output:

  • A white card with text (name, role, location) clearly visible.
  • A soft blue decorative circle visible in the top-right corner, sitting BEHIND the text content.

Self-Check Questions:

  • What happens if you change .background-circle's z-index from -1 to 2? (It would cover the text.)
  • What if you remove the z-index: 1 from .card-content? Would the text still show? (Yes, because the circle is at -1 which is below everything by default.)

Phase 11 of 11
Part 10: Common Beginner Mistakes

Mistake 1 · Setting z-index without a position property

Wrong:

css
.my-element {
  z-index: 999;   /* IGNORED — no position set, defaults to static */
}

Correct:

css
.my-element {
  position: relative;  /* or absolute, fixed, sticky */
  z-index: 999;        /* NOW it works */
}

Why it happens: Beginners set a high z-index and wonder why nothing changes. They forget that z-index has a prerequisite.


Mistake 2 · Confused by stacking contexts (the "trapped child" bug)

The Symptom: You set a child element's z-index to 9999 but it still appears behind another element on the page.

The Cause: The child is inside a parent that has its own stacking context (because the parent has a z-index value). The child is "trapped" inside the parent's context and cannot escape above elements outside that context.

Wrong (assuming child can escape parent):

css
.parent {
  position: relative;
  z-index: 1;
}
.child {
  position: relative;
  z-index: 9999; /* still trapped within the parent's z-index: 1 context */
}
.outside-element {
  position: relative;
  z-index: 2;   /* entire parent (with all its children) is BELOW this */
}

Fix Option 1 · Raise the parent's z-index:

css
.parent {
  z-index: 3;  /* now parent (and all children) is above outside-element */
}

Fix Option 2 · Move the child out of the parent if it needs to be above outside elements.


Mistake 3 · Using extremely high z-index values unnecessarily

Wrong (common pattern):

css
.my-modal { z-index: 9999999; }
.my-tooltip { z-index: 99999; }
.my-dropdown { z-index: 9999; }

Why it's a problem: This becomes very hard to manage. When a new developer joins the project, they set z-index: 99999999 to beat the existing values, and the numbers spiral out of control.

Best Practice · Use a z-index scale:

css
/* Define a clear, manageable scale */
/* z-index: 1-9     → slightly elevated elements */
/* z-index: 10-99   → dropdowns, tooltips */
/* z-index: 100-999 → modals, overlays */
/* z-index: 1000+   → critical UI (cookie banners, chatbots) */

.dropdown   { z-index: 10;  }
.tooltip    { z-index: 20;  }
.modal      { z-index: 100; }
.modal-overlay { z-index: 99; }

Mistake 4 · Forgetting that opacity, transform, and filter create stacking contexts

css
/* This parent has opacity < 1, which creates a NEW stacking context */
.parent {
  opacity: 0.99;   /* Even 0.99 creates a stacking context! */
  /* No z-index set, but stacking context is still created */
}

.child {
  position: absolute;
  z-index: 999;   /* still trapped inside .parent's stacking context */
}

Fix: Be aware that opacity, transform, filter, clip-path, and will-change on a parent can trap children in a stacking context. If the parent doesn't need these on the same element, separate them.


Mistake 5 · Removing position accidentally

css
/* Developer adds z-index */
.header {
  position: fixed;
  z-index: 100;
}

/* Later, someone changes position by mistake */
.header {
  position: static;   /* THIS removes z-index functionality! */
  z-index: 100;       /* now ignored */
}

Fix: Always check that position is set correctly when z-index stops working.


✏️ Your Task
`css /* Define a clear, manageable scale */ /* z-index: 1-9 → slightly elevated elements */ /* z-index: 10-99 → dropdowns, tooltips */ /* z-index: 100-999 → modals, overlays */ /* z-index: 1000+ → critical UI (cookie banners, chatbots) */ .dropdown { z-index: 10; } .tooltip { z-index: 20; } .modal { z-index: 100; } .modal-overlay { z-index: 99; } ` ·
🏗️ Build It — Mini Project
Stage 1: Setup · The Card Structure

In this mini-project you will build a photo gallery card. When a user hovers over an image card, a dark overlay with a caption appears on top of the image. This is a very common design pattern seen on portfolio sites, e-commerce pages, and news sites.

Stage 1: Setup · The Card Structure

Create the basic HTML structure:

starter.html
<!DOCTYPE html>
<html>
<head>
  <title>Image Gallery with z-index Overlay</title>
  <link rel="stylesheet" href="gallery.css">
</head>
<body>

  <div class="gallery">

    <div class="card">
      <img src="https://picsum.photos/seed/nature/300/200" alt="Nature">
      <div class="overlay">
        <p class="caption">Beautiful Nature</p>
      </div>
    </div>

    <div class="card">
      <img src="https://picsum.photos/seed/city/300/200" alt="City">
      <div class="overlay">
        <p class="caption">City Lights</p>
      </div>
    </div>

    <div class="card">
      <img src="https://picsum.photos/seed/ocean/300/200" alt="Ocean">
      <div class="overlay">
        <p class="caption">Ocean Views</p>
      </div>
    </div>

  </div>

</body>
</html>

Lesson 23 complete! 🎉

You covered: