Topics Covered in This HTML & CSS Tutorial:
Master the CSS Box-shadow Property, Control Element Stacking with Position and Z-index, Create Inset Shadows for Depth, Add Professional Drop Shadows to Text with CSS Text-shadow, Layer Multiple Text-shadows for Advanced Outline Effects
Exercise Preview

Exercise Overview
In this hands-on exercise, you'll master the art of creating visual depth using CSS shadows—essential skills for modern web design. You'll implement box-shadow and text-shadow properties to transform flat designs into compelling, professional interfaces. Additionally, you'll learn to manipulate element stacking order using relative positioning and the z-index property, giving you precise control over how elements layer in three-dimensional space. These techniques are fundamental for creating the polished, depth-rich designs that users expect in 2026.
Getting Started
- We'll be switching to a new folder of prepared files for this exercise. In your code editor, close all open files to avoid confusion and maintain a clean workspace.
- For this exercise we'll be working with the Box-Shadow and Text-Shadow folder located in Desktop > Class Files > Advanced HTML CSS Class. Open that folder in your code editor if it supports folder-based workflows (like Visual Studio Code, Sublime Text, or WebStorm).
- Open index.html from the Box-Shadow and Text-Shadow folder to examine the project structure.
Preview index.html in Chrome (we'll be leveraging its powerful DevTools for real-time experimentation).
You'll see the portfolio website of John Schmidt, a fictional but accomplished artist. The site is functionally complete but visually flat—our mission is to add sophisticated drop shadows that elevate the design's professional appeal.
- Notice the four large featured art images on the page. These need visual prominence through strategic shadow placement. Hover over them to see the pointer cursor, indicating each image is wrapped in a clickable link. The markup structure includes each link wrapped in a div tag with a class of category, giving us multiple styling options.
Keep the page open in Chrome—we'll return frequently to test our changes and use DevTools for fine-tuning.
Environment Setup
Close All Files
Close all open files in your code editor to avoid confusion when switching to new project files.
Open Project Folder
Navigate to Desktop > Class Files > Advanced HTML CSS Class and open the Box-Shadow and Text-Shadow folder.
Launch Files
Open index.html in your code editor and preview it in Chrome to access DevTools for testing.
Using the CSS Box-Shadow Property
The CSS3 box-shadow property revolutionizes how we add depth to web interfaces. With a single declaration, you can create everything from subtle material design effects to dramatic artistic shadows. Understanding its syntax and behavior is crucial for modern web development.
- Return to your code editor and maintain focus on clean, organized workflow.
- Open main.css from the css folder (within the Box-Shadow and Text-Shadow directory).
In the .category a rule, add the bold code below to create your first box shadow:
.category a { box-shadow: 2px 6px 4px #000; margin: 30px 0; display: block; text-decoration: none; }- Understanding the syntax is essential: the first value (2px) sets the horizontal offset, the second (6px) controls vertical offset, the third (4px) defines blur radius, and the fourth (#000) specifies color. This foundational knowledge will serve you throughout your career as these patterns repeat across many CSS properties.
- Save the file and reload the page in Chrome. You'll notice the shadow is quite prominent—deliberately so, to demonstrate the effect clearly before we refine it.
- Let's open Chrome DevTools for real-time experimentation. CTRL–click (Mac) or Right–click (Windows) on any featured art image and select Inspect. DevTools remains one of the most powerful features for front-end development, allowing instant feedback on design changes.
- An
<img>tag should be highlighted. In the Elements panel, click the parent line:<a href="#">to select the link element that contains our box-shadow. In the Styles panel, locate the .category a rule with our box-shadow property:
- Click on the first px value (horizontal offset) and change it to -2px.
- Change the second value (vertical offset) to -6px.
The shadow now projects toward the top-left. This demonstrates a fundamental principle: positive values place shadows toward bottom-right, while negative values project toward top-left. This directional control is essential for creating consistent lighting effects across your interface.
Let's create a more sophisticated, modern shadow effect. Modify the values to create a subtle drop shadow:
box-shadow: 0 2px 20px #000;This creates a directly downward shadow with significant blur, mimicking natural lighting conditions.
For comparison, create a sharp, minimal shadow by reducing the blur:
box-shadow: 0 2px 2px #000;Notice how dramatically the blur radius affects the shadow's character—from soft and natural to sharp and graphic.
Experiment with color by changing to a bright red:
box-shadow: 0 2px 2px #f00;While dramatic, this illustrates an important limitation: hex colors are completely opaque. For realistic shadows, we need transparency to blend naturally with any background color.
- Return to main.css in your code editor to implement our refined shadow.
Replace the experimental values with a professional, production-ready shadow:
.category a { box-shadow: 0 12px 18px rgba(0,0,0,.3); margin: 30px 0; display: block; text-decoration: none; }RGBA color notation provides alpha transparency (0 = fully transparent, 1 = fully opaque). Our 30% transparent black (0.3) creates natural-looking shadows that work beautifully over any background color—a hallmark of professional web design.
- Save and reload to see the refined shadow. This subtle, soft effect provides visual hierarchy without overwhelming the content—exactly what modern UI design demands.
- Now we'll add visual separation between the header sections. The gray band containing "John Schmidt" needs a shadow to create depth against the navigation below. This header section uses the class logo-wrapper.
- Leave Chrome open for testing and switch back to main.css.
Add a shadow to the existing .logo-wrapper rule:
.logo-wrapper { background: #444; box-shadow: 0 2px 15px rgba(0,0,0,.8);Code Omitted To Save Space
}Pro Tip: Modern code editors with Emmet support (Visual Studio Code, Sublime Text, Atom) let you type bxsh and press Tab for instant box-shadow snippets. Delete any unwanted parts like inset and tab through the placeholders for rapid development.
Our zero horizontal offset creates a straight downward shadow, while the 80% opacity ensures visibility against the dark navigation background.
Save and reload—but you'll notice the shadow isn't visible! This introduces a crucial concept about element stacking order that every front-end developer must understand.
The box-shadow property follows a specific order: horizontal offset, vertical offset, blur radius, and color. Positive values place shadows bottom-right, negative values place them top-left.
Shadow Value Effects
| Feature | Positive Values | Negative Values |
|---|---|---|
| Horizontal Offset | Shadow to the right | Shadow to the left |
| Vertical Offset | Shadow below element | Shadow above element |
| Visual Impact | Bottom-right shadow | Top-left shadow |
Changing an Element's Default Stack Order
HTML elements follow a default stacking order that determines their front-to-back arrangement along the z-axis. Understanding and controlling this three-dimensional layering is essential for sophisticated interface design, especially when working with shadows, overlays, and interactive elements.
- Switch to index.html to examine the markup structure and understand why our shadow disappeared.
Locate the header tag and observe that
<div class="logo-wrapper">and<nav>are sibling elements. In the default stacking context, later elements in the HTML appear in front of earlier ones—hence our navigation is covering the logo-wrapper's shadow.The solution involves changing the positioning context, which affects stacking behavior.
- Return to main.css for the fix.
Add relative positioning to the .logo-wrapper rule:
.logo-wrapper { background: #444; box-shadow: 0 2px 15px rgba(0,0,0,.8); position: relative;Code Omitted To Save Space
}Important: We use relative positioning because it maintains the element in normal document flow while creating a new stacking context. Fixed positioning would remove it from document flow and prevent natural scrolling, while absolute positioning would break the layout structure.
Save and reload to see the shadow successfully appear.
Key Concept: Elements with position values other than static (the default) create new stacking contexts and appear in front of statically positioned elements. This fundamental principle explains why our simple position change resolved the stacking issue.
For complex layering scenarios with multiple positioned elements, the z-index property provides precise numerical control over stacking order—as we'll demonstrate next.
Relative positioning differs from default static positioning in stacking behavior. Elements with relative position can control their stacking order, while static elements cannot use z-index.
CSS Positioning Options
Static (Default)
Normal document flow positioning. Cannot use z-index property for stacking control.
Relative
Maintains document flow but enables z-index control. Best for keeping elements in normal flow while managing stacking.
Fixed/Absolute
Removes from document flow. Fixed stays in viewport, absolute positions relative to parent container.
Inset Shadows & Z-Index
Inset shadows create the illusion of depth going into the element rather than projecting outward. Combined with z-index control, they enable sophisticated layering effects that are essential for modern interface design.
- In Chrome, CTRL–click (Mac) or Right–click (Windows) on any featured art image and select Inspect.
- With the
<img>tag selected, click the parent<a href="#">in the Elements panel to select the link element. In the Styles panel, locate the .category a rule and modify the box-shadow value:
- Click on the box-shadow value
- Add inset at the beginning: inset 0 12px 18px rgba(0,0,0,.3)
- The shadow disappears because the image inside covers the inset effect!
This demonstrates why understanding element relationships and stacking is crucial for advanced CSS effects.
- In the Elements panel, click the img tag nested inside the selected link to target the image element specifically.
- Locate the img rule in the Styles panel.
- Click after the vertical-align: bottom; property to create a new line for additional properties.
- Type
z-index: -1;to push the image backward in the stacking order. The shadow still isn't visible because z-index only works with positioned elements. Add position: relative; and watch the inset shadow appear!
Z-index Logic:
- Higher positive numbers bring elements to the front (z-index: 20 appears over z-index: 10)
- Negative numbers push elements backward
- Z-index only affects elements with position values other than static
This was purely experimental—we won't implement these changes in our actual CSS file.
Creating Inset Shadow Effects
Add Inset Keyword
Prepend 'inset' to box-shadow values to create inner shadows instead of outer drop shadows.
Manage Element Stacking
Use z-index with negative values to push elements backward in stacking order when needed.
Enable Z-Index Control
Set position to relative or absolute to enable z-index functionality on elements.
Z-index only works with positioned elements (relative, absolute, fixed). Higher positive numbers move elements forward, negative numbers push them backward.
Adding Drop Shadows to Text with CSS Text-Shadow
Text shadows add sophisticated typography effects that can transform ordinary text into striking design elements. When used strategically, they enhance readability and create visual hierarchy that guides user attention.
- Return to main.css to enhance the "John Schmidt" header text with professional text shadow effects.
The target text is an anchor tag within the .logo-wrapper. Add text-shadow to the existing .logo-wrapper a rule:
.logo-wrapper a { display: inline-block; text-shadow: 4px 4px #000; }- Save and reload to see the basic black text shadow applied.
- Right-click the "John Schmidt" text and choose Inspect to experiment with different shadow styles.
- Click any blank area on the page to deselect the text for clearer visualization.
In the Styles panel, modify the text-shadow for a sharp, graphic effect:
text-shadow: 4px 4px 0 #000;The zero blur radius creates a crisp, offset duplicate of the text—perfect for bold, graphic design treatments.
Box-Shadow vs Text-Shadow
| Feature | Box-Shadow | Text-Shadow |
|---|---|---|
| Target | Element containers | Text content only |
| Blur Control | Optional blur radius | Optional blur radius |
| Positioning | Can use inset effects | External shadows only |
| Layering | Single shadow per element | Multiple shadows supported |
Layering Multiple Text-Shadows for a Detached Outline Effect
Advanced text shadow techniques involve layering multiple shadows to create complex visual effects. This approach enables everything from glowing text to sophisticated outline effects that appear detached from the original letterforms.
We'll create a stylized outline that appears to float separately from the text—a technique popular in modern logo design and attention-grabbing headlines. This requires strategic layering of shadows in specific colors and positions.
- Switch to main.css to implement our advanced shadow effect.
- First, identify the background color of the logo-wrapper (#444) since our masking technique requires matching this exact color for the illusion to work.
Modify the .logo-wrapper a rule with an improved shadow:
.logo-wrapper a { display: inline-block; text-shadow: 4px 4px 0 #666; }Critical: The zero blur radius is essential for crisp edges. The #666 gray provides better contrast than pure black without being overwhelming.
Now add the masking shadow. Text shadows stack with the first shadow on top, so our background-colored shadow must come first:
.logo-wrapper a { display: inline-block; text-shadow: 2px 2px 0 #444, 4px 4px 0 #666; }Technical Note: The comma separates multiple shadows. The first shadow (2px 2px 0 #444) matches the background color and partially covers the second shadow (4px 4px 0 #666), creating a 2-pixel gap that simulates a floating outline.
- Save and reload to see the detached outline effect—the text appears to have a shadow floating independently nearby.
- Test the hover interaction by moving your cursor over the "John Schmidt" text. We'll enhance this with a dynamic shadow shift.
- Return to main.css to add interactive behavior.
- Copy the entire .logo-wrapper a rule for modification.
Paste below the original and modify for the hover state:
.logo-wrapper a { display: inline-block; text-shadow: 2px 2px 0 #444, 4px 4px 0 #666; } .logo-wrapper a:hover { text-shadow: -2px -2px 0 #444, -4px -4px 0 #666; }Remove the display property from the hover rule since it's inherited from the base state. The negative values shift the shadow to the opposite direction, creating a dynamic lighting effect that responds to user interaction.
- Save and reload to test the interactive shadow shift.
Hover over the text to see the dramatic shadow transition—a sophisticated effect that adds personality and interactivity to the design.
CSS Box Shadow Reference
Box-shadow accepts up to 6 values in specific order: inset horizontal-offset vertical-offset blur-radius spread-radius color
Inset (optional): Creates an inner shadow within the element instead of an external drop shadow. Can be positioned first or last in the declaration. All other values must maintain their prescribed order.
Horizontal offset (required): Positive values project the shadow rightward, negative values leftward. This controls the apparent horizontal direction of your light source.
Vertical offset (required): Positive values project shadows downward (below the element), negative values upward (above the element). Essential for establishing consistent lighting direction across your interface.
Blur radius (optional): Higher values create softer, more diffused shadows. Zero produces sharp-edged shadows. Typical values range from 0px (graphic/sharp) to 20px+ (soft/natural).
Spread radius (optional): Positioned between blur and color. Positive values expand the shadow beyond the element's dimensions, negative values shrink it. Default is 0 (shadow matches element size).
Color (required in practice): Accepts any CSS color format—hex, RGB, RGBA, HSL, HSLA, or named colors. RGBA with alpha transparency typically produces the most realistic results.
Box-Shadow Property Values
CSS Text Shadow Reference
Text-shadow requires offset values and optionally accepts blur radius and color: horizontal-offset vertical-offset blur-radius color
The offset values are mandatory and use length units (px, em, rem): horizontal offset moves shadows right (positive) or left (negative), while vertical offset moves shadows down (positive) or up (negative). These create the basic shadow positioning.
The blur radius (optional) follows the offset values and controls shadow softness. Larger values create more diffused effects, while zero produces sharp text duplicates. Omitting blur radius defaults to zero.
The color value can precede or follow the offset and blur values, providing flexibility in declaration syntax. Multiple shadows are comma-separated, with the first shadow rendering on top of subsequent shadows in the stacking order.
Text-Shadow Implementation Checklist
Required parameters that determine shadow direction and distance
Controls shadow sharpness - 0 for hard edges, higher values for softer shadows
Supports hex, RGB, RGBA, HSL, or HSLA color values
Create complex effects by stacking multiple text-shadow declarations
Color can be specified before or after offset and blur values