CSS is what makes websites look good. Without it, every webpage would be plain black text on a white background. This tutorial takes you from zero to styling real web pages — no prior experience required.
What you'll learn
| Topic | What you'll be able to do |
|---|---|
| Setup | Write CSS in files, link to HTML |
| Selectors | Target any HTML element |
| Box model | Control spacing, borders, size |
| Colors & typography | Style text and backgrounds |
| Flexbox | Build one-dimensional layouts |
| CSS Grid | Build two-dimensional layouts |
| Responsive design | Make pages work on any screen |
| Transitions & animations | Add motion to elements |
| Projects | Style 3 real web pages |
CSS version used: CSS3 (current standard)
Part 1 — Why CSS?
CSS stands for Cascading Style Sheets. It controls how HTML elements look — colors, fonts, spacing, layout, animations.
| What CSS does | Example |
|---|---|
| Color & backgrounds | background: #1a1a2e |
| Fonts & text | font-size: 18px; font-weight: bold |
| Spacing | margin: 20px; padding: 10px |
| Layout | Flexbox, Grid, positioning |
| Responsive design | Different styles per screen size |
| Animations | Hover effects, transitions, keyframes |
The three web languages work together:
HTML → Structure (what's on the page)
CSS → Style (how it looks)
JS → Behavior (how it acts)
Part 2 — Setup (zero installation)
Option 1: Browser only (fastest start)
Create a file called index.html on your desktop:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My CSS Practice</title>
<style>
/* CSS goes here */
h1 {
color: blue;
}
</style>
</head>
<body>
<h1>Hello CSS!</h1>
</body>
</html>
Double-click the file → it opens in your browser.
Option 2: VS Code + Live Server (recommended)
- Download VS Code (free)
- Install the Live Server extension
- Create
index.htmlandstyle.css - Right-click
index.html→ "Open with Live Server" - Page auto-refreshes every time you save
Three ways to add CSS
<!-- 1. External file (best practice) -->
<link rel="stylesheet" href="style.css">
<!-- 2. Internal (in <head>) -->
<style>
h1 { color: red; }
</style>
<!-- 3. Inline (avoid for styling, useful for testing) -->
<h1 style="color: red;">Hello</h1>
Use external files for real projects. Keeps HTML and CSS separate.
Part 3 — CSS Syntax
Every CSS rule has the same structure:
selector {
property: value;
property: value;
}
Example:
h1 {
color: darkblue;
font-size: 32px;
font-weight: bold;
}
- selector — which HTML element(s) to style
- property — what to change (color, size, etc.)
- value — what to set it to
- declaration — one property + value pair
- rule — selector + all declarations inside
{}
Comments
/* This is a CSS comment — ignored by the browser */
h1 {
color: red; /* inline comment */
}
Part 4 — Selectors
Selectors tell CSS which elements to style.
Basic selectors
/* Element selector — all <p> tags */
p {
color: gray;
}
/* Class selector — elements with class="btn" */
.btn {
background: blue;
color: white;
}
/* ID selector — element with id="header" */
#header {
background: black;
}
/* Universal selector — every element */
* {
box-sizing: border-box;
}
Using classes in HTML
<!-- In HTML -->
<p class="intro">This paragraph is special.</p>
<p>This paragraph is normal.</p>
/* In CSS — only targets the intro class */
.intro {
font-size: 20px;
color: navy;
}
Multiple classes
<button class="btn btn-large btn-primary">Click me</button>
.btn { padding: 8px 16px; border-radius: 4px; }
.btn-large { padding: 12px 24px; font-size: 18px; }
.btn-primary { background: blue; color: white; }
Combinator selectors
/* Descendant — any <p> inside a <div> */
div p {
color: purple;
}
/* Child — direct <p> children of <div> only */
div > p {
font-weight: bold;
}
/* Adjacent sibling — <p> immediately after <h2> */
h2 + p {
font-size: 18px;
}
/* General sibling — all <p> after <h2> */
h2 ~ p {
color: gray;
}
Pseudo-class selectors
/* States */
a:hover { color: red; } /* when mouse over */
a:visited { color: purple; } /* already clicked */
button:focus { outline: 2px solid blue; } /* keyboard focus */
input:disabled { opacity: 0.5; }
/* Position */
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(2) { color: red; } /* 2nd item */
li:nth-child(odd) { background: #f5f5f5; } /* odd rows */
li:nth-child(3n) { color: blue; } /* every 3rd */
/* Other */
p:not(.intro) { color: gray; } /* every p WITHOUT .intro class */
input:checked { accent-color: green; }
Pseudo-element selectors
/* Style part of an element */
p::first-line { font-weight: bold; }
p::first-letter { font-size: 200%; float: left; }
/* Insert content before/after */
.required::after {
content: " *";
color: red;
}
/* Style selected text */
::selection {
background: yellow;
color: black;
}
Attribute selectors
/* Element with attribute */
input[type="email"] { border-color: blue; }
a[target="_blank"] { color: red; }
/* Attribute starts with */
a[href^="https"] { color: green; }
/* Attribute ends with */
a[href$=".pdf"] { color: orange; }
/* Attribute contains */
a[href*="example"] { text-decoration: underline; }
Specificity — which rule wins?
When multiple rules target the same element, specificity decides which wins.
| Selector type | Specificity score |
|---|---|
Inline style (style="") |
1000 |
ID selector (#header) |
100 |
Class/attribute/pseudo-class (.btn, [type], :hover) |
10 |
Element/pseudo-element (p, ::before) |
1 |
p { color: black; } /* score: 1 */
.text { color: blue; } /* score: 10 — wins over p */
#intro { color: red; } /* score: 100 — wins over .text */
Rule: More specific selector wins. Equal specificity → last rule wins (the "cascade").
Part 5 — Colors
CSS supports many color formats:
/* Named colors */
color: red;
color: darkblue;
color: coral;
/* Hex codes (most common) */
color: #ff0000; /* red */
color: #1a1a2e; /* dark navy */
color: #fff; /* white (shorthand for #ffffff) */
/* RGB */
color: rgb(255, 0, 0); /* red */
color: rgb(26, 26, 46); /* dark navy */
/* RGBA (with transparency) */
color: rgba(0, 0, 0, 0.5); /* 50% transparent black */
/* HSL (Hue, Saturation, Lightness) */
color: hsl(0, 100%, 50%); /* red */
color: hsl(220, 60%, 30%); /* dark blue */
/* HSLA */
color: hsla(220, 60%, 30%, 0.8);
/* Modern oklch (best for accessibility) */
color: oklch(50% 0.2 250);
CSS custom properties (variables)
:root {
--primary: #3b82f6;
--secondary: #10b981;
--text: #1f2937;
--bg: #ffffff;
}
h1 { color: var(--primary); }
button { background: var(--secondary); }
body { color: var(--text); background: var(--bg); }
Define once in :root, use everywhere. Change the variable → changes everywhere instantly.
Part 6 — Typography
body {
font-family: 'Inter', Arial, sans-serif;
font-size: 16px; /* base size */
line-height: 1.6; /* 1.6× the font size */
color: #1f2937;
}
h1 {
font-size: 2.5rem; /* rem = relative to root (16px) */
font-weight: 700; /* 100-900, or bold/normal */
letter-spacing: -0.02em;
text-align: center;
}
p {
font-size: 1rem; /* = 16px */
margin-bottom: 1em; /* em = relative to current font-size */
}
Font size units
| Unit | What it means | Example |
|---|---|---|
px |
Absolute pixels | font-size: 16px |
rem |
Relative to root <html> size |
font-size: 1.5rem = 24px |
em |
Relative to parent's font size | font-size: 1.2em |
% |
Relative to parent | font-size: 120% |
vw |
% of viewport width | font-size: 4vw |
Use rem for most font sizes — consistent, scales with user preferences.
Google Fonts
<!-- In <head> -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
body {
font-family: 'Inter', sans-serif;
}
Text properties
h1 {
text-transform: uppercase; /* UPPERCASE */
text-decoration: underline; /* underline */
text-decoration: none; /* remove underline from links */
text-align: center; /* left | center | right | justify */
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
white-space: nowrap; /* no line breaks */
overflow: hidden;
text-overflow: ellipsis; /* text... */
}
Part 7 — The Box Model
Every HTML element is a box. The box model has 4 layers:
┌─────────────────────────────────┐
│ MARGIN │ Space outside the border
│ ┌───────────────────────────┐ │
│ │ BORDER │ │ The visible border line
│ │ ┌─────────────────────┐ │ │
│ │ │ PADDING │ │ │ Space between content & border
│ │ │ ┌───────────────┐ │ │ │
│ │ │ │ CONTENT │ │ │ │ The actual content (text, image)
│ │ │ └───────────────┘ │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
div {
width: 300px;
height: 200px;
padding: 20px; /* inside spacing */
border: 2px solid black;
margin: 30px; /* outside spacing */
}
box-sizing: border-box
By default (content-box), width only counts the content. Adding padding makes the element bigger.
With border-box, width includes padding and border — much easier to work with:
/* Add this to EVERY project */
*, *::before, *::after {
box-sizing: border-box;
}
div {
width: 300px;
padding: 20px; /* box is STILL 300px wide */
}
Padding and margin syntax
/* All four sides */
padding: 20px;
/* top/bottom left/right */
padding: 10px 20px;
/* top right bottom left (clockwise from top) */
padding: 10px 20px 15px 5px;
/* Individual sides */
padding-top: 10px;
padding-right: 20px;
padding-bottom: 10px;
padding-left: 20px;
/* Shorthand — same for margin */
margin: 0 auto; /* center a block element horizontally */
Border
border: 2px solid #ccc; /* width style color */
border-top: 3px dashed red;
border-radius: 8px; /* rounded corners */
border-radius: 50%; /* circle */
/* Box shadow */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
box-shadow: 2px 2px 0 black; /* x y blur color */
Part 8 — Display and Positioning
Display values
/* Block — full width, starts on new line (div, p, h1, etc.) */
display: block;
/* Inline — flows with text, no width/height (span, a, em) */
display: inline;
/* Inline-block — inline flow but accepts width/height */
display: inline-block;
/* Flex — flexbox layout (see Part 9) */
display: flex;
/* Grid — grid layout (see Part 10) */
display: grid;
/* None — hides element, removes from layout */
display: none;
Position
/* Static (default) — normal document flow */
position: static;
/* Relative — offset from its normal position */
position: relative;
top: 10px;
left: 20px;
/* Absolute — positioned relative to nearest positioned ancestor */
position: absolute;
top: 0;
right: 0;
/* Fixed — stays in viewport (like a sticky header) */
position: fixed;
top: 0;
left: 0;
width: 100%;
/* Sticky — scrolls normally, then sticks */
position: sticky;
top: 0;
Centering with position
/* Center absolutely positioned element */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
z-index (stacking order)
.modal {
position: fixed;
z-index: 1000; /* higher = on top */
}
.overlay {
position: fixed;
z-index: 999;
}
Part 9 — Flexbox
Flexbox is the easiest way to build one-dimensional layouts (row or column).
.container {
display: flex;
}
That's it — children become flex items.
Flex container properties
.container {
display: flex;
/* Direction */
flex-direction: row; /* → (default) */
flex-direction: column; /* ↓ */
flex-direction: row-reverse; /* ← */
/* Wrapping */
flex-wrap: nowrap; /* all on one line (default) */
flex-wrap: wrap; /* wrap to next line if needed */
/* Main axis alignment (horizontal if row) */
justify-content: flex-start; /* left (default) */
justify-content: flex-end; /* right */
justify-content: center; /* center */
justify-content: space-between; /* items with space between */
justify-content: space-around; /* space around each item */
justify-content: space-evenly; /* equal space everywhere */
/* Cross axis alignment (vertical if row) */
align-items: stretch; /* fill container height (default) */
align-items: flex-start; /* top */
align-items: flex-end; /* bottom */
align-items: center; /* middle */
/* Gap between items */
gap: 16px; /* same horizontal and vertical */
gap: 12px 24px; /* row-gap column-gap */
}
Flex item properties
.item {
/* How much item grows relative to others */
flex-grow: 1; /* 0 = don't grow (default) */
/* How much item shrinks if needed */
flex-shrink: 1; /* 1 = shrink equally (default) */
/* Base size before growing/shrinking */
flex-basis: 200px; /* auto = use content size */
/* Shorthand: grow shrink basis */
flex: 1; /* flex: 1 1 0% (equal width columns) */
flex: 0 0 200px; /* fixed 200px, no grow/shrink */
/* Override container's align-items for this item */
align-self: center;
}
Common Flexbox patterns
/* Navigation bar */
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
/* Centered card */
.wrapper {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Equal-width columns */
.columns {
display: flex;
gap: 24px;
}
.column {
flex: 1; /* all columns equal width */
}
/* Sidebar + main */
.layout {
display: flex;
gap: 24px;
}
.sidebar { flex: 0 0 250px; } /* fixed 250px */
.main { flex: 1; } /* fills rest */
Part 10 — CSS Grid
Grid is for two-dimensional layouts (rows AND columns at once).
.grid {
display: grid;
}
Defining columns and rows
.grid {
display: grid;
/* 3 equal columns */
grid-template-columns: 1fr 1fr 1fr;
/* Or shorthand */
grid-template-columns: repeat(3, 1fr);
/* Fixed + flexible */
grid-template-columns: 250px 1fr;
/* Auto-fit responsive columns */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* Row heights */
grid-template-rows: auto;
/* Gap */
gap: 24px;
column-gap: 24px;
row-gap: 16px;
}
Grid template areas (most readable)
.layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
}
header { grid-area: header; }
.sidebar { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
Placing grid items
.item {
/* Span multiple columns */
grid-column: 1 / 3; /* from line 1 to line 3 */
grid-column: span 2; /* span 2 columns */
/* Span multiple rows */
grid-row: 1 / 3;
grid-row: span 2;
}
Grid vs Flexbox
| Flexbox | Grid | |
|---|---|---|
| Dimension | One (row OR column) | Two (rows AND columns) |
| Best for | Navigation, button groups, centering | Page layout, card grids |
| Alignment | Along one axis | Both axes independently |
| Content-driven | Yes — items determine size | No — container defines structure |
Use both. Flexbox for components, Grid for page layout.
Part 11 — Responsive Design
Responsive design means your site looks good on all screen sizes.
Media queries
/* Mobile-first approach (recommended) */
/* Base styles — mobile */
.container {
padding: 16px;
font-size: 16px;
}
/* Tablet: 768px and above */
@media (min-width: 768px) {
.container {
padding: 24px;
font-size: 18px;
}
}
/* Desktop: 1024px and above */
@media (min-width: 1024px) {
.container {
max-width: 1200px;
margin: 0 auto;
padding: 32px;
}
}
Common breakpoints
| Name | Width | Targets |
|---|---|---|
| Mobile | 0–767px | Phones |
| Tablet | 768–1023px | iPads, small laptops |
| Desktop | 1024–1279px | Laptops |
| Wide | 1280px+ | Large monitors |
Fluid typography
/* Scales between 16px (mobile) and 20px (desktop) */
body {
font-size: clamp(1rem, 1rem + 0.5vw, 1.25rem);
}
h1 {
font-size: clamp(1.75rem, 4vw, 3rem);
}
Viewport units
.hero {
height: 100vh; /* 100% of viewport height */
width: 100vw; /* 100% of viewport width */
}
/* Better for mobile (avoids browser chrome issues) */
.hero {
height: 100dvh; /* dynamic viewport height */
}
Responsive images
img {
max-width: 100%; /* never wider than its container */
height: auto; /* maintain aspect ratio */
}
Flexbox responsive grid
.cards {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card {
flex: 1 1 280px; /* grow, shrink, min 280px */
/* 1 column on mobile, more on wider screens automatically */
}
Part 12 — Transitions and Animations
Transitions (hover effects)
.btn {
background: blue;
color: white;
padding: 12px 24px;
border-radius: 6px;
transition: background 0.3s ease, transform 0.2s ease;
}
.btn:hover {
background: darkblue;
transform: translateY(-2px); /* lift effect */
}
.btn:active {
transform: translateY(0); /* press down effect */
}
Transition syntax
transition: property duration timing-function delay;
transition: all 0.3s ease; /* all properties */
transition: color 0.2s linear; /* specific property */
transition: background 0.3s ease, /* multiple */
transform 0.2s ease;
Timing functions
| Value | What it does |
|---|---|
ease |
Slow → fast → slow (default) |
linear |
Constant speed |
ease-in |
Slow start |
ease-out |
Slow end |
ease-in-out |
Slow start and end |
cubic-bezier(...) |
Custom curve |
Keyframe animations
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.hero-text {
animation: fadeIn 0.6s ease forwards;
}
/* Multiple keyframes */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.icon {
animation: pulse 2s ease-in-out infinite;
}
Animation properties
animation-name: fadeIn;
animation-duration: 0.6s;
animation-timing-function: ease;
animation-delay: 0.2s;
animation-iteration-count: 1; /* or: infinite */
animation-direction: normal; /* or: reverse, alternate */
animation-fill-mode: forwards; /* keep end state */
/* Shorthand */
animation: fadeIn 0.6s ease 0.2s 1 normal forwards;
Respect user preferences
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Part 13 — Common CSS Patterns
CSS Reset / Normalize
Start every project with this:
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
color: #1f2937;
}
img, video {
max-width: 100%;
height: auto;
}
a {
color: inherit;
text-decoration: none;
}
Center anything
/* Flexbox (most common) */
.wrapper {
display: flex;
justify-content: center;
align-items: center;
}
/* Grid */
.wrapper {
display: grid;
place-items: center;
}
/* Absolute position */
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* Horizontal only (block elements) */
.container {
max-width: 1200px;
margin: 0 auto;
}
Card component
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
Button styles
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
font-size: 16px;
font-weight: 600;
border: none;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-primary {
background: #3b82f6;
color: white;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-outline {
background: transparent;
color: #3b82f6;
border: 2px solid #3b82f6;
}
.btn-outline:hover {
background: #3b82f6;
color: white;
}
Visually hidden (for screen readers)
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
Part 14 — 3 Projects
Project 1: Personal Profile Card
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile Card</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: system-ui, sans-serif;
background: #f0f4f8;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 24px;
}
.card {
background: white;
border-radius: 16px;
padding: 40px 32px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
max-width: 360px;
width: 100%;
}
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #3b82f6;
margin-bottom: 20px;
}
.name {
font-size: 1.5rem;
font-weight: 700;
color: #111;
margin-bottom: 4px;
}
.role {
color: #6b7280;
font-size: 0.95rem;
margin-bottom: 20px;
}
.bio {
color: #374151;
line-height: 1.6;
font-size: 0.9rem;
margin-bottom: 24px;
}
.stats {
display: flex;
justify-content: center;
gap: 32px;
margin-bottom: 24px;
padding: 20px 0;
border-top: 1px solid #e5e7eb;
border-bottom: 1px solid #e5e7eb;
}
.stat-number {
font-size: 1.25rem;
font-weight: 700;
color: #111;
}
.stat-label {
font-size: 0.75rem;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.btn {
display: inline-block;
background: #3b82f6;
color: white;
padding: 12px 32px;
border-radius: 8px;
font-weight: 600;
text-decoration: none;
transition: background 0.2s ease;
}
.btn:hover { background: #2563eb; }
</style>
</head>
<body>
<div class="card">
<img class="avatar" src="https://i.pravatar.cc/200" alt="Profile photo">
<h1 class="name">Alex Chen</h1>
<p class="role">Frontend Developer</p>
<p class="bio">I build fast, accessible, beautiful web experiences. Passionate about CSS, animations, and clean code.</p>
<div class="stats">
<div>
<div class="stat-number">47</div>
<div class="stat-label">Projects</div>
</div>
<div>
<div class="stat-number">12k</div>
<div class="stat-label">Followers</div>
</div>
<div>
<div class="stat-number">98%</div>
<div class="stat-label">Rating</div>
</div>
</div>
<a href="#" class="btn">Follow</a>
</div>
</body>
</html>
What you practiced: box model, flexbox, border-radius, box-shadow, hover transitions.
Project 2: Responsive Navigation Bar
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navigation</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; }
nav {
position: sticky;
top: 0;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
z-index: 100;
}
.nav-inner {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
font-size: 1.25rem;
font-weight: 700;
color: #3b82f6;
text-decoration: none;
}
.nav-links {
display: flex;
list-style: none;
gap: 8px;
}
.nav-links a {
display: block;
padding: 8px 16px;
color: #374151;
text-decoration: none;
border-radius: 6px;
font-size: 0.95rem;
transition: background 0.2s, color 0.2s;
}
.nav-links a:hover {
background: #eff6ff;
color: #3b82f6;
}
.nav-links a.active {
background: #3b82f6;
color: white;
}
.cta {
background: #3b82f6;
color: white;
padding: 10px 20px;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
transition: background 0.2s;
}
.cta:hover { background: #2563eb; }
/* Hero to show sticky effect */
.hero {
max-width: 1200px;
margin: 80px auto;
padding: 0 24px;
text-align: center;
}
.hero h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
font-weight: 800;
color: #111;
margin-bottom: 16px;
}
.hero p {
font-size: 1.1rem;
color: #6b7280;
max-width: 600px;
margin: 0 auto;
}
</style>
</head>
<body>
<nav>
<div class="nav-inner">
<a href="#" class="logo">MySite</a>
<ul class="nav-links">
<li><a href="#" class="active">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Services</a></li>
<li><a href="#">Blog</a></li>
</ul>
<a href="#" class="cta">Get Started</a>
</div>
</nav>
<div class="hero">
<h1>Build Beautiful Websites</h1>
<p>Learn CSS and create stunning web experiences that work on every device and screen size.</p>
</div>
</body>
</html>
What you practiced: sticky positioning, flexbox nav, responsive sizing, clamp().
Project 3: Product Card Grid
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Grid</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: system-ui, sans-serif;
background: #f9fafb;
color: #111;
padding: 40px 24px;
}
h1 {
text-align: center;
font-size: 2rem;
margin-bottom: 40px;
color: #111;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 24px;
max-width: 1200px;
margin: 0 auto;
}
.card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
}
.card-img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-body {
padding: 20px;
}
.badge {
display: inline-block;
background: #dcfce7;
color: #16a34a;
font-size: 0.75rem;
font-weight: 600;
padding: 4px 10px;
border-radius: 100px;
margin-bottom: 12px;
}
.card-title {
font-size: 1.1rem;
font-weight: 700;
margin-bottom: 8px;
}
.card-desc {
color: #6b7280;
font-size: 0.9rem;
line-height: 1.5;
margin-bottom: 20px;
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
}
.price {
font-size: 1.25rem;
font-weight: 700;
color: #3b82f6;
}
.price-old {
font-size: 0.85rem;
color: #9ca3af;
text-decoration: line-through;
margin-left: 6px;
}
.btn-cart {
background: #3b82f6;
color: white;
border: none;
padding: 10px 18px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
.btn-cart:hover { background: #2563eb; }
</style>
</head>
<body>
<h1>Featured Products</h1>
<div class="grid">
<div class="card">
<img class="card-img" src="https://picsum.photos/seed/1/400/200" alt="Wireless headphones">
<div class="card-body">
<span class="badge">New</span>
<h2 class="card-title">Wireless Headphones</h2>
<p class="card-desc">Premium noise-canceling sound with 30-hour battery life.</p>
<div class="card-footer">
<div>
<span class="price">$79</span>
<span class="price-old">$129</span>
</div>
<button class="btn-cart">Add to Cart</button>
</div>
</div>
</div>
<div class="card">
<img class="card-img" src="https://picsum.photos/seed/2/400/200" alt="Smart watch">
<div class="card-body">
<span class="badge">Sale</span>
<h2 class="card-title">Smart Watch Pro</h2>
<p class="card-desc">Track fitness, sleep, and notifications from your wrist.</p>
<div class="card-footer">
<div>
<span class="price">$149</span>
<span class="price-old">$199</span>
</div>
<button class="btn-cart">Add to Cart</button>
</div>
</div>
</div>
<div class="card">
<img class="card-img" src="https://picsum.photos/seed/3/400/200" alt="Laptop stand">
<div class="card-body">
<span class="badge">Popular</span>
<h2 class="card-title">Aluminium Laptop Stand</h2>
<p class="card-desc">Ergonomic design with 6 height levels and cable management.</p>
<div class="card-footer">
<div>
<span class="price">$49</span>
<span class="price-old">$65</span>
</div>
<button class="btn-cart">Add to Cart</button>
</div>
</div>
</div>
</div>
</body>
</html>
What you practiced: CSS Grid auto-fit, card component, badges, hover effects, responsive layout.
Part 15 — Learning Path
| Stage | Topics | Time |
|---|---|---|
| 1. Basics | Selectors, colors, typography, box model | Week 1 |
| 2. Layout | Flexbox, Grid, positioning | Week 2–3 |
| 3. Responsive | Media queries, mobile-first, clamp() | Week 3–4 |
| 4. Effects | Transitions, animations, transforms | Week 4–5 |
| 5. Architecture | BEM naming, custom properties, organization | Week 5–6 |
| 6. Framework | Tailwind CSS or Bootstrap | Week 6–8 |
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
Not using box-sizing: border-box |
Padding makes elements too wide | Add reset at top of CSS |
Overusing !important |
Impossible to override later | Fix specificity instead |
height: 100% not working |
Parent has no height set | Use min-height: 100vh on body |
Centering with margin: auto not working |
Works only on block elements with set width | Use display: flex instead |
Animating width or height |
Causes layout recalculation, janky | Animate transform: scale() |
Using px for font sizes |
Doesn't scale with user font settings | Use rem instead |
z-index not working |
Element not positioned | Add position: relative |
| Too many media queries | Hard to maintain | Mobile-first + 2–3 breakpoints |
CSS vs Related Terms
| Term | What it is |
|---|---|
| CSS | The language for styling HTML |
| CSS3 | Current version with variables, grid, animations |
| Sass/SCSS | CSS preprocessor — adds variables, mixins, nesting |
| Tailwind CSS | Utility-first CSS framework — style with classes |
| Bootstrap | Component-first CSS framework |
| CSS Modules | Locally scoped CSS for React/Vue components |
| CSS-in-JS | Write CSS inside JavaScript (styled-components) |
| BEM | Block-Element-Modifier naming convention |
| PostCSS | Tool that transforms CSS with plugins |
| CSS custom properties | Native CSS variables (--color: red) |
FAQ
Do I need to memorize all CSS properties?
No. Learn the concepts — box model, flexbox, grid, selectors. Look up specific properties when needed. Even experienced developers use MDN docs daily.
Should I learn CSS or a framework like Tailwind/Bootstrap first?
Learn plain CSS first for 2–4 weeks. You'll understand WHY Tailwind/Bootstrap exist and won't struggle when things go wrong.
What's the best order: HTML first or CSS first?
HTML first. You need HTML to apply CSS to. Learn HTML basics (1 week), then start CSS.
Do I need to know CSS for React/Vue?
Yes. React and Vue are JavaScript frameworks — they don't replace CSS. You still style components with CSS (or Tailwind).
How long does it take to learn CSS?
Basics in 1–2 weeks. Comfortable with layout in 4–6 weeks. Truly proficient takes months of building projects. There's always more to learn.
What's the hardest part of CSS?
For most beginners: layout (especially before learning Flexbox/Grid). Learn those two well and 80% of layout problems become easy.