Phase 2 — CSS
Lesson 0005 • Beginner

CSS in Action

Lesson 4 gave you the mental models — selectors, box model, specificity. This lesson fills the gaps with the practical CSS properties you'll use on every single project: display, positioning, hover effects, transitions, shadows, backgrounds, and CSS variables.

1. The display Property — The Most Misunderstood CSS Concept

Every HTML element has a default display value. This single property controls how an element behaves in the page flow. If you don't understand display, you'll be confused by CSS forever.

Value Behavior Default For
block Takes full width. Starts on a new line. You can set width/height. <div>, <p>, <h1>–<h6>, <section>, <header>, <ul>
inline Takes only the width it needs. Does NOT start a new line. You cannot set width/height. <span>, <a>, <strong>, <em>, <code>
inline-block Sits inline (no new line), BUT you can set width/height/padding/margin. <img>, <button>, <input>
none Element is completely removed from the page. Not visible, takes no space. Used with JavaScript to show/hide elements

Why This Matters

Ever wondered why setting width on an <a> or <span> does nothing? Because they're inline by default — inline elements ignore width and height. The fix: display: inline-block or display: block. This single concept solves 50% of beginner CSS frustrations.

display.css
/* Make links behave like blocks (clickable buttons) */
nav a {
  display: inline-block;
  padding: 0.5rem 1rem;
  background-color: #8b5cf6;
  color: white;
  border-radius: 8px;
}

/* Hide an element completely */
.hidden {
  display: none;
}

Source: MDN — The display property

🛝 Try It: Display Playground

The three boxes below are <span> elements (inline by default). Try changing their display to inline-block or block. See how width and padding start working.

2. Pseudo-Classes — Styling States & Positions

Pseudo-classes let you style elements based on their state (is the user hovering? is the input focused?) or position (first child? every other row?). They start with a colon :.

State-based Pseudo-Classes

Pseudo-class Triggers When Common Use
:hover Mouse is over the element Buttons, links, cards
:focus Element has keyboard focus (tab or click into input) Form inputs, buttons
:active Element is being clicked (mouse down) Button press effect
:visited Link has been clicked before Links
:disabled Form element has disabled attribute Grayed-out buttons/inputs
hover-focus.css
.btn {
  background-color: #8b5cf6;
  color: white;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}

/* When the user hovers */
.btn:hover {
  background-color: #7c3aed;
}

/* When the user clicks (mouse down) */
.btn:active {
  transform: scale(0.98);
}

/* When input has keyboard focus */
input:focus {
  outline: none;
  border-color: #8b5cf6;
  box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
}

Position-based Pseudo-Classes

Pseudo-class Selects Example
:first-child The first child of its parent li:first-child { font-weight: bold; }
:last-child The last child of its parent li:last-child { border-bottom: none; }
:nth-child(n) The nth child (or pattern like odd, even, 3n) tr:nth-child(even) { background: #f5f5f7; }
💡 The cursor Property Always set cursor: pointer on clickable elements that aren't links (buttons, cards, custom toggles). Users need visual feedback that something is clickable. Without it, your UI feels broken.

Source: MDN — Pseudo-classes

🛝 Try It: Hover Effects

Hover over the button below. Try changing the hover color, adding transform: scale(1.05), or changing the border-radius on hover.

3. CSS Transitions — Making Changes Smooth

Without transitions, hover effects are instant — the color snaps from purple to dark purple in 0ms. That feels cheap. Transitions add smooth animation between states.

transition.css
.btn {
  background-color: #8b5cf6;
  color: white;
  padding: 0.75rem 1.5rem;
  border-radius: 8px;
  transition: all 0.2s ease;  /* ← THE MAGIC LINE */
}

.btn:hover {
  background-color: #7c3aed;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
}

Transition Syntax

transition-property
Which property to animate (all, background-color, transform, etc.)
transition-duration
How long the animation takes (0.2s, 0.3s, 150ms)
transition-timing-function
ease (default), ease-in, ease-out, ease-in-out, linear
💡 The Shorthand transition: all 0.2s ease; is the shorthand for all three. Use 0.2s–0.3s for interactive elements. Longer durations feel sluggish. Put the transition on the base state, not on :hover.

Source: MDN — Using CSS Transitions

🛝 Try It: Smooth Transitions

This card has a transition on hover. Try changing the duration (e.g., 0.5s), adding transform: translateY(-4px) on hover, or changing the box-shadow size.

4. box-shadow & text-shadow

Shadows add depth and make elements feel like they float above the page. Every modern card, button, and modal uses box-shadow.

shadows.css
/*  x-offset  y-offset  blur  spread  color */
.card {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

/* Subtle shadow (resting state) */
.card-subtle {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}

/* Elevated shadow (hover / modal) */
.card-elevated {
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}

/* Colored shadow (accent glow) */
.btn-glow {
  box-shadow: 0 4px 16px rgba(139, 92, 246, 0.3);
}

/* Text shadow */
.hero-title {
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

Source: MDN — box-shadow

5. Background Properties & Gradients

Backgrounds can be solid colors, images, or gradients. Professional sites use gradients heavily — hero sections, buttons, cards.

Property Example Use
background-color #f0ebff Solid fill
background-image url('hero.jpg') Image backgrounds
background-size cover / contain cover = fills the area, may crop. contain = fits inside, may leave gaps.
background-position center / top right Where the image anchors
background-repeat no-repeat Prevent image tiling

Gradients

gradients.css
/* Linear gradient (top to bottom) */
.hero {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
}

/* Subtle gradient (almost flat) */
.section {
  background: linear-gradient(180deg, #fbfbfb, #f0f0f0);
}

/* Background image with overlay */
.hero-image {
  background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)),
                     url('hero.jpg');
  background-size: cover;
  background-position: center;
}

Source: MDN — linear-gradient()

🛝 Try It: Gradient Playground

Edit the gradient angle and colors. Try 45deg, 90deg, or to right. Experiment with three-color gradients.

6. CSS Positioning — Breaking Out of the Flow

By default, elements flow top-to-bottom (block) or left-to-right (inline). Positioning lets you place elements outside this normal flow.

Position Behavior Common Use
static Default. Normal document flow. top/left/right/bottom have no effect. Everything by default
relative Still in the flow, but can be offset with top/left. Creates a positioning context for children. Parent container for absolute children
absolute Removed from flow. Positioned relative to the nearest relative/absolute/fixed ancestor. Badges, tooltips, dropdown menus, overlays
fixed Removed from flow. Stays in the same spot even when scrolling. Positioned relative to the viewport. Sticky navigation bars, floating chat buttons
sticky Acts like relative until you scroll past it, then acts like fixed. Table headers, section headings that stick on scroll

The relative + absolute Combo

This is the most important positioning pattern. Set the parent to position: relative. Set the child to position: absolute. Now the child is positioned relative to the parent — not the page. This is how you put badges on cards, icons inside input fields, and close buttons on modals.

positioning.css
/* Badge on a card: relative parent + absolute child */
.card {
  position: relative;  /* creates positioning context */
  padding: 1.5rem;
}

.badge {
  position: absolute;
  top: -8px;
  right: -8px;
  background: #ff453a;
  color: white;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
}

/* Fixed navigation bar */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
}
💡 z-index When positioned elements overlap, z-index controls which one appears on top. Higher number = closer to the user. Only works on elements with position set to something other than static.

Source: MDN — CSS position

7. Overflow — What Happens When Content Doesn't Fit

When content is bigger than its container, the overflow property controls what happens:

Value Behavior Use
visible Default. Content spills out of the box. —
hidden Content is clipped. No scrollbar. Cards with images, rounded corners on containers
scroll Always shows scrollbar (even if content fits). Rarely used alone
auto Scrollbar appears only when needed. Chat panels, log windows, sidebars
overflow.css
/* Hide overflowing image corners in a rounded card */
.card {
  border-radius: 12px;
  overflow: hidden;  /* clips the image to the border-radius */
}

/* Scrollable chat panel */
.chat-messages {
  height: 400px;
  overflow-y: auto;  /* vertical scroll only when needed */
}

8. Opacity & Visibility

Property Effect Key Difference
opacity: 0 Invisible, but still takes up space. Can be animated. Good for fade-in/out transitions
visibility: hidden Invisible, still takes up space. Cannot receive clicks. Hide without layout shift
display: none Completely removed from the page. No space, no interaction. Cannot be transitioned (use opacity instead)
opacity.css
/* Dimmed disabled button */
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Muted helper text */
.helper-text {
  opacity: 0.6;
}

9. CSS Variables (Custom Properties)

Hardcoding colors and sizes everywhere is a nightmare to maintain. CSS variables let you define values once and reuse them everywhere. When you change a variable, every usage updates automatically.

variables.css
/* Define variables on :root (available everywhere) */
:root {
  --color-primary: #8b5cf6;
  --color-primary-dark: #7c3aed;
  --color-text: #1d1d1f;
  --color-text-muted: #515154;
  --color-bg: #fbfbfb;
  --color-border: #e5e5e7;
  --radius: 12px;
  --shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

/* Use variables with var() */
.btn {
  background-color: var(--color-primary);
  border-radius: var(--radius);
}

.btn:hover {
  background-color: var(--color-primary-dark);
}

.card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

Why CSS Variables Are Essential

Imagine you have #8b5cf6 in 47 places and the client asks for a different purple. Without variables, you find-and-replace 47 times and hope you didn't miss one. With variables, you change one line: --color-primary: #6366f1;. Every modern CSS framework and design system uses variables. Start using them from day one.

Source: MDN — Using CSS Custom Properties

10. Width & Height — Auto, Min, and Max

Understanding how width and height behave prevents hours of frustration:

Property Behavior Use
width: auto Default for block. Fills parent's width. Default — usually leave it alone
width: 100% Explicitly fills parent width (same as auto for block, but useful for replaced elements like <img>). Making images responsive
max-width Element can shrink smaller, but never exceeds this. This is how responsive containers work. max-width: 760px; margin: 0 auto; — centered container
min-width Element can grow bigger, but never shrinks below this. Buttons that need a minimum clickable width
height: auto Default. Height grows to fit content. Leave it alone 95% of the time
min-height: 100vh At least full viewport height, but can grow. Main content area (so footer stays at bottom)
⚠️ Avoid Fixed Heights Setting a fixed height on text containers is the #1 cause of broken layouts. Text length varies. Mobile screens are narrow, so text wraps more. Use min-height instead, and let the content determine the height.

Interactive Practice Zone

Test your understanding of CSS display, positioning, transitions, and more.

Question 1: Why does setting width on a <span> have no effect by default?
Question 2: Where should the transition property be placed?
Question 3: To position a badge in the top-right corner of a card, what combination do you use?
Question 4: What is the difference between display: none and opacity: 0?
Question 5: What does var(--color-primary) do in CSS?
Question 6: What pseudo-class fires when the user presses Tab to focus a form input?
0/6

Quiz Completed!

Come back and retry this quiz tomorrow — spaced repetition builds permanent knowledge.

11. Build Challenge: Interactive Portfolio Upgrade

Take your styled portfolio from Lesson 4 and level it up with everything you learned in this lesson:

  1. Open practices/lesson4-style.css (or create practices/lesson5-style.css)
  2. Add CSS variables at the top:
    • Define --color-primary, --color-text, --color-bg, --color-border, --radius
    • Replace all hardcoded colors with var(--color-primary) etc.
  3. Add hover effects on navigation links:
    • Color change on :hover
    • A transition: all 0.2s ease; on the base state
  4. Add a project card with:
    • Border, padding, border-radius
    • box-shadow on hover (use transition!)
    • transform: translateY(-2px) on hover
  5. Add a gradient to the header or hero section
  6. Style the footer with opacity for muted text
  7. Use overflow: hidden on the card if it has an image
⚠️ Write It Yourself Don't copy from the code blocks above. Use the CSS Foundations reference sheet if you forget a property name, but pick your own colors, your own gradient angles, your own shadow values. Making design decisions is part of being a professional developer.

Primary Source: For every CSS property, MDN CSS Reference is the canonical documentation. Also check Kevin Powell for CSS positioning and transitions videos.

Finished the build? Show me your updated portfolio and I'll review it before we move on to Flexbox layout.