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.
/* 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 |
.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; } |
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.
🛝 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.
.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
all, background-color, transform, etc.)0.2s, 0.3s, 150ms)ease (default), ease-in, ease-out, ease-in-out, lineartransition: 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.
/* 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);
}
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
/* 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.
/* 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 controls which one appears on top. Higher number = closer to the user. Only works on elements with position set to something other than static.
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 |
/* 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) |
/* 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.
/* 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) |
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.
width on a <span> have no effect by default?transition property be placed?display: none and opacity: 0?var(--color-primary) do in CSS?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:
- Open
practices/lesson4-style.css(or createpractices/lesson5-style.css) - 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.
- Define
- Add hover effects on navigation links:
- Color change on
:hover - A
transition: all 0.2s ease;on the base state
- Color change on
- Add a project card with:
- Border, padding,
border-radius box-shadowon hover (usetransition!)transform: translateY(-2px)on hover
- Border, padding,
- Add a gradient to the header or hero section
- Style the footer with
opacityfor muted text - Use
overflow: hiddenon the card if it has an image
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.