Master CSS from zero to pro
A structured 5-day guide covering everything — selectors, layouts, animations, responsive design, and real-world project patterns.
What is CSS?
CSS (Cascading Style Sheets) is the language that controls the visual presentation of web pages. While HTML builds the structure (the skeleton), CSS adds the skin — colors, fonts, spacing, layout, and animations.
Think of CSS as an interior designer: HTML builds the walls and rooms, CSS decides the paint, furniture, and lighting.
CSS works by selecting HTML elements and applying rules to them. Every CSS rule follows the same pattern: selector { property: value; }
Three ways to add CSS
<!-- 1. Inline CSS (avoid for most things) -->
<p style="color: red; font-size: 18px;">Hello</p>
<!-- 2. Internal CSS (in <head>) -->
<style>
p { color: blue; }
</style>
<!-- 3. External CSS (BEST PRACTICE) -->
<link rel="stylesheet" href="styles.css">
Selectors — Targeting Elements
Selectors tell CSS which HTML elements to style. Mastering selectors is one of the most important CSS skills.
| Selector | Syntax | Targets |
|---|---|---|
| Element | p | All <p> elements |
| Class | .card | Elements with class="card" |
| ID | #header | Element with id="header" |
| Universal | * | Every element |
| Descendant | div p | All <p> inside any <div> |
| Child | ul > li | Direct <li> children of <ul> |
| Sibling | h2 + p | <p> immediately after <h2> |
| Attribute | input[type="text"] | Text inputs |
| Pseudo-class | a:hover | Links on mouse hover |
| Pseudo-element | p::first-line | First line of paragraph |
/* Element selector */
h1 { color: #333; }
/* Class selector (reusable) */
.btn-primary {
background: #007bff;
color: white;
padding: 10px 20px;
}
/* ID selector (use sparingly — once per page) */
#hero-title { font-size: 3rem; }
/* Chaining: element AND class */
p.highlight { background: yellow; }
/* Pseudo-class: hover state */
.btn:hover { opacity: 0.8; }
/* Pseudo-element: before/after */
blockquote::before { content: '"'; font-size: 3rem; }
Avoid overusing IDs for styling. Classes are reusable; IDs are not. Prefer .btn over #btn.
The Cascade & Specificity
The "C" in CSS stands for Cascading — when multiple rules target the same element, the browser uses a priority system to decide which wins.
Specificity Score
Think of specificity as a 4-digit score: (inline, ID, class, element)
p { color: blue; } /* score: 0,0,0,1 */
.text { color: green; } /* score: 0,0,1,0 — wins */
#main { color: red; } /* score: 0,1,0,0 — wins */
inline style /* score: 1,0,0,0 — wins */
/* !important overrides everything (use rarely) */
p { color: purple !important; }
Avoid !important. If you need it, your specificity is probably too messy. Refactor instead.
Colors in CSS
CSS supports many color formats. Each has its use case.
.box {
/* Named colors */
color: tomato;
/* Hex (most common) */
background-color: #1a1a2e;
/* RGB */
border-color: rgb(255, 99, 132);
/* RGBA — with transparency (0=invisible, 1=solid) */
background: rgba(0, 0, 0, 0.5);
/* HSL — Hue (0-360°) Saturation Lightness */
color: hsl(220, 70%, 50%);
/* Modern oklch (best for color accuracy) */
color: oklch(65% 0.2 250);
}
Typography
Typography is 95% of web design. CSS gives you full control over how text looks and reads.
body {
font-family: 'Inter', sans-serif;
font-size: 16px; /* base size */
line-height: 1.6; /* 1.5–1.7 ideal for body text */
color: #333;
}
h1 {
font-size: clamp(2rem, 5vw, 4rem); /* responsive! */
font-weight: 700;
letter-spacing: -0.03em; /* tighter for headings */
line-height: 1.1;
}
p {
max-width: 65ch; /* ch = width of '0' char */
text-align: left; /* avoid justify on screens */
}
/* Google Fonts import */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
The Box Model
Every HTML element is a box. The box model describes how size, spacing, and borders work together.
Content → Padding → Border → Margin (inside out)
.card {
/* Content size */
width: 300px;
height: 200px;
/* Padding: space INSIDE the border */
padding: 20px; /* all sides */
padding: 16px 24px; /* top/bottom left/right */
padding: 10px 20px 10px 20px; /* top right bottom left */
/* Border */
border: 2px solid #ccc;
border-radius: 8px;
/* Margin: space OUTSIDE the border */
margin: 24px auto; /* auto = center horizontally */
/* CRITICAL: include padding in width */
box-sizing: border-box;
}
/* Global reset (put this at top of every CSS file) */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
Build a styled blog post card using everything from Day 1.
- Create an HTML file with a card div containing title, date, excerpt, and a "Read More" link
- Use a class selector to style the card with background, padding, border-radius, and box-shadow
- Style the title with a custom font-size and color
- Add a hover effect on the "Read More" link using
:hover - Center the card on the page using margin auto
The display Property
The display property controls how an element behaves in the flow of the page.
| Value | Behavior | Example elements |
|---|---|---|
block | Takes full width, starts on new line | div, p, h1–h6, section |
inline | Fits content, stays on same line. No width/height | span, a, strong, em |
inline-block | Inline but accepts width/height | img, button |
flex | Flexbox container | nav, card groups |
grid | CSS Grid container | page layouts |
none | Hides element (removes from flow) | hidden menus |
Flexbox — One-Dimensional Layouts
Flexbox is perfect for aligning items in a row or column. It's the go-to for navbars, card rows, centering elements, and button groups.
.container {
display: flex;
/* Direction */
flex-direction: row; /* row | row-reverse | column | column-reverse */
/* Alignment on main axis (horizontal for row) */
justify-content: space-between; /* flex-start | center | flex-end | space-around */
/* Alignment on cross axis (vertical for row) */
align-items: center; /* flex-start | flex-end | stretch | baseline */
/* Wrapping */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
/* Gap between items (modern) */
gap: 16px;
}
.item {
/* How much the item grows */
flex-grow: 1; /* 0 = don't grow */
/* How much it shrinks */
flex-shrink: 1; /* 0 = don't shrink */
/* Base size before growing/shrinking */
flex-basis: 200px;
/* Shorthand: grow shrink basis */
flex: 1 1 200px;
/* Override align-items for one item */
align-self: flex-end;
}
/* PERFECT CENTERING (both axes) */
.center {
display: flex;
justify-content: center;
align-items: center;
}
CSS Grid — Two-Dimensional Layouts
Grid is for full-page layouts and anything that needs rows AND columns at the same time — magazine layouts, dashboards, photo galleries.
.grid {
display: grid;
/* Define columns */
grid-template-columns: 1fr 1fr 1fr; /* 3 equal columns */
grid-template-columns: 200px auto 200px; /* fixed | flexible | fixed */
grid-template-columns: repeat(3, 1fr); /* same as 1fr 1fr 1fr */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* RESPONSIVE! */
/* Gap between cells */
gap: 24px;
column-gap: 20px;
row-gap: 16px;
}
/* Make an item span multiple columns */
.featured {
grid-column: span 2; /* takes 2 columns */
grid-row: span 2; /* takes 2 rows */
}
/* Named areas — perfect for page layouts */
.layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 240px 1fr;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
Flexbox: 1D — items in a row or column. Best for navigation bars, button groups, centering.
Grid: 2D — rows AND columns simultaneously. Best for page layouts, galleries, dashboards.
Positioning
The position property removes elements from the normal flow and places them precisely.
/* static — default, follows normal flow */
.normal { position: static; }
/* relative — offset from its normal position */
.shifted {
position: relative;
top: 10px;
left: 20px;
}
/* absolute — relative to nearest positioned ancestor */
.badge {
position: absolute;
top: -8px;
right: -8px; /* corner of parent */
}
/* fixed — stays on screen even when scrolling */
.navbar {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 100; /* stacking order */
}
/* sticky — fixed after scrolling to it */
.section-header {
position: sticky;
top: 60px;
}
Build a full page layout with header, sidebar, main content, and footer.
- Use CSS Grid with named areas for the overall page structure
- Use Flexbox inside the header to align logo left and nav links right
- Create a 3-column card grid in the main area using
repeat(auto-fit, minmax(280px, 1fr)) - Make the navbar
position: stickyso it follows on scroll - Add a floating "Back to Top" button using
position: fixed
position: absolute
Backgrounds & Gradients
CSS backgrounds go far beyond solid colors — gradients, images, patterns, and multiple layers are all possible.
.hero {
/* Solid color */
background-color: #1a1a2e;
/* Linear gradient */
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
/* Radial gradient */
background: radial-gradient(circle at 30% 50%, #e63946, #1a1a2e);
/* Image */
background-image: url('hero.jpg');
background-size: cover; /* cover | contain | 100% auto */
background-position: center;
background-repeat: no-repeat;
/* Image + overlay (layered backgrounds) */
background:
linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)),
url('hero.jpg') center/cover no-repeat;
}
Shadows & Borders
Shadows add depth and dimension. CSS supports box shadows, text shadows, and drop filters.
/* box-shadow: x-offset y-offset blur spread color */
.card {
/* Soft card shadow */
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
/* Multiple shadows */
box-shadow:
0 1px 3px rgba(0,0,0,0.12),
0 8px 24px rgba(0,0,0,0.08);
/* Inset shadow (inner glow) */
box-shadow: inset 0 2px 8px rgba(0,0,0,0.1);
/* Colored glow effect */
box-shadow: 0 0 20px 4px rgba(230,57,70,0.4);
}
/* text-shadow: x y blur color */
h1 { text-shadow: 2px 2px 6px rgba(0,0,0,0.3); }
/* Advanced borders */
.fancy {
border-radius: 50%; /* circle */
border-radius: 20px 4px 20px 4px; /* asymmetric */
outline: 2px dashed #e63946; /* outside border */
}
Transforms
Transforms move, scale, rotate, and skew elements without affecting layout. They are GPU-accelerated and perfect for hover effects.
.box {
/* Move */
transform: translate(20px, -10px);
/* Scale (1 = normal, 1.1 = 10% bigger) */
transform: scale(1.1);
/* Rotate */
transform: rotate(45deg);
/* Skew (tilt) */
transform: skew(-10deg);
/* Chain multiple transforms */
transform: translateY(-4px) scale(1.02) rotate(-1deg);
}
/* Classic card hover lift effect */
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-6px);
box-shadow: 0 16px 40px rgba(0,0,0,0.15);
}
Transitions & Animations
CSS animations bring your UI to life without JavaScript. Transitions animate between two states; Animations run continuously with keyframes.
/* transition: property duration timing-function delay */
.btn {
background: #e63946;
transition: background 0.3s ease;
/* Transition multiple properties */
transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.3s ease;
/* Transition ALL properties (less precise) */
transition: all 0.3s ease;
}
.btn:hover { background: #c62833; }
/* Timing functions */
/* ease (default), linear, ease-in, ease-out, ease-in-out */
/* cubic-bezier(x1, y1, x2, y2) — custom curve */
/* Define the animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.08); }
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Apply the animation */
.hero-text {
/* animation: name duration timing iteration direction fill-mode */
animation: fadeIn 0.6s ease both;
animation-delay: 0.2s;
}
.loader { animation: spin 1s linear infinite; }
.cta-btn { animation: pulse 2s ease-in-out infinite; }
/* Staggered children */
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }
Build a visually rich hero section for a fictional product.
- Use a linear or radial gradient for the background
- Add a layered background image with a dark overlay using multiple background layers
- Animate the heading in with a
fadeInkeyframe animation - Add a CTA button with a hover transform (scale + shadow) and smooth transition
- Use
text-shadowon the heading for depth
@keyframes and position: absolute
Media Queries
Media queries let you apply CSS based on screen size (or other conditions). This is the foundation of responsive design — making your site look great on mobile, tablet, and desktop.
/* Common breakpoints */
/* Mobile first (recommended): write base styles for mobile,
then ADD styles for larger screens */
@media (min-width: 480px) {
/* Tablet portrait and up */
}
@media (min-width: 768px) {
/* Tablet landscape and up */
.grid { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
/* Desktop */
.grid { grid-template-columns: 1fr 1fr 1fr; }
.sidebar { display: block; }
}
@media (min-width: 1280px) {
/* Wide desktop */
.container { max-width: 1200px; margin: 0 auto; }
}
/* Other media features */
@media (prefers-color-scheme: dark) {
body { background: #111; color: #eee; }
}
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; }
}
Write your CSS for mobile by default, then use min-width queries to enhance for larger screens. This is faster to load on mobile and easier to maintain.
CSS Custom Properties (Variables)
CSS variables let you store values and reuse them. Change one variable and it updates everywhere — perfect for design systems, themes, and dark mode.
/* Define variables on :root (global scope) */
:root {
--color-primary: #e63946;
--color-bg: #0a0a0f;
--color-text: #f0ede8;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 32px;
--font-sans: 'Outfit', sans-serif;
--radius-md: 8px;
--shadow: 0 4px 20px rgba(0,0,0,0.1);
}
/* Use variables with var() */
.card {
background: var(--color-bg);
padding: var(--spacing-lg);
border-radius: var(--radius-md);
box-shadow: var(--shadow);
}
.btn {
background: var(--color-primary);
padding: var(--spacing-sm) var(--spacing-md);
}
/* Dark mode with variables */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #0a0a0f;
--color-text: #f0ede8;
}
}
/* Override locally for a component */
.dark-card {
--color-bg: #1a1a2e; /* only affects this element */
}
CSS Units — px, rem, em, %, vw, vh
Choosing the right unit matters for responsiveness and accessibility.
| Unit | Relative to | Best used for |
|---|---|---|
px | Screen pixels | Borders, icons, fixed sizes |
rem | Root font-size (usually 16px) | Font sizes, spacing (accessible) |
em | Parent element font-size | Component-relative spacing |
% | Parent element | Widths, responsive containers |
vw | Viewport width | Full-width sections |
vh | Viewport height | Full-height hero sections |
ch | Width of '0' character | Readable text line lengths |
fr | Fraction of grid space | CSS Grid columns/rows |
clamp() | Min, ideal, max | Responsive fluid typography |
/* Responsive font with clamp(min, ideal, max) */
h1 { font-size: clamp(1.8rem, 5vw, 4rem); }
/* Full-height hero */
.hero { min-height: 100vh; }
/* Readable content width */
.prose { max-width: 65ch; }
/* Prefer rem for font sizes (respects user browser settings) */
body { font-size: 1rem; } /* = 16px */
h2 { font-size: 1.5rem; } /* = 24px */
h1 { font-size: 2.5rem; } /* = 40px */
Pseudo-Classes & Pseudo-Elements
These are powerful CSS selectors that target states and virtual elements without needing extra HTML.
/* State-based */
a:hover { color: blue; }
a:visited { color: purple; }
input:focus { outline: 2px solid blue; }
button:active { transform: scale(0.97); }
input:disabled { opacity: 0.5; cursor: not-allowed; }
/* Structural */
li:first-child { margin-top: 0; }
li:last-child { border-bottom: none; }
li:nth-child(odd) { background: #f5f5f5; } /* zebra striping */
li:nth-child(3n) { ... } /* every 3rd */
p:not(.intro) { color: #666; } /* all p EXCEPT .intro */
/* ::before and ::after — inject virtual content */
.quote::before {
content: '"';
font-size: 4rem;
color: rgba(0,0,0,0.1);
line-height: 0;
vertical-align: -0.4em;
}
/* Decorative line under heading */
h2::after {
content: '';
display: block;
width: 60px; height: 3px;
background: var(--color-primary);
margin-top: 8px;
}
/* Placeholder text styling */
input::placeholder { color: #aaa; }
/* First line of paragraph */
p::first-line { font-weight: bold; }
/* Selection color */
::selection { background: #e63946; color: white; }
Build a simple portfolio page that works perfectly on mobile and desktop.
- Define a design system in
:rootwith color, spacing, and font variables - Write mobile-first CSS — base styles for mobile, then
min-widthqueries for tablet/desktop - The project grid should stack on mobile (
1 col) and expand to 3 columns on desktop - Use
clamp()for all heading font sizes - Add a dark mode using
@media (prefers-color-scheme: dark)that overrides the color variables - Style active nav links with
:hoverand::afterunderline decoration
::selection
Filters & Blend Modes
CSS filters apply Photoshop-style effects directly in the browser. They're GPU-accelerated and work on any element including images.
img {
/* Single filters */
filter: blur(4px);
filter: grayscale(100%);
filter: brightness(1.2);
filter: contrast(1.5);
filter: saturate(2);
filter: hue-rotate(90deg);
filter: invert(100%);
filter: sepia(80%);
filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.5));
/* Chain filters */
filter: grayscale(50%) contrast(1.2) brightness(0.9);
/* Hover: reveal color */
transition: filter 0.3s ease;
}
img:hover { filter: none; }
/* Background blur (frosted glass) */
.glass {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(12px) saturate(180%);
border: 1px solid rgba(255,255,255,0.2);
}
/* Blend modes */
.overlay {
mix-blend-mode: multiply; /* multiply | screen | overlay | difference | color */
}
.bg-layer { background-blend-mode: soft-light; }
Clip-Path & Shapes
Clip-path cuts elements into any shape — triangles, circles, hexagons, custom polygons. It's used for diagonal section dividers, shaped hero images, and icon masks.
/* Basic shapes */
.circle { clip-path: circle(50%); }
.ellipse { clip-path: ellipse(60% 40% at 50% 50%); }
.triangle { clip-path: polygon(50% 0%, 0% 100%, 100% 100%); }
.diamond { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }
/* Hexagon */
.hex { clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); }
/* Diagonal section divider */
.hero { clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%); }
/* Animate clip-path */
.reveal {
clip-path: inset(0 100% 0 0); /* hidden (right side clipped) */
transition: clip-path 0.6s ease;
}
.reveal.visible { clip-path: inset(0 0% 0 0); } /* fully revealed */
Advanced Grid Patterns
CSS Grid can create complex magazine-style layouts with overlapping elements, spanning cells, and asymmetric designs.
/* Magazine/bento grid */
.bento {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
gap: 16px;
}
.item-big { grid-column: span 2; grid-row: span 2; }
.item-wide { grid-column: span 3; }
.item-tall { grid-row: span 2; }
/* Overlap elements using grid lines */
.overlap-grid {
display: grid;
grid-template-columns: 1fr 60px 1fr;
}
.left { grid-column: 1 / 3; } /* col 1 to 3 */
.right { grid-column: 2 / 4; } /* overlaps in middle */
/* Subgrid — children inherit parent's grid lines */
.card {
grid-column: span 2;
display: grid;
grid-template-columns: subgrid;
}
CSS Architecture & Best Practices
As projects grow, organized CSS becomes critical. Here are professional patterns used by real teams.
BEM Naming Convention
BEM = Block__Element--Modifier. It makes CSS predictable and avoids naming conflicts.
/* Block = component */
.card { ... }
/* Element = part of the block */
.card__title { ... }
.card__image { ... }
.card__footer { ... }
/* Modifier = variation */
.card--featured { ... }
.card--dark { ... }
.card__title--large { ... }
/* HTML:
<div class="card card--featured">
<h2 class="card__title">...</h2>
<img class="card__image">
</div>
*/
Utility Classes Pattern
/* Small, single-purpose utility classes */
.flex { display: flex; }
.center { justify-content: center; align-items: center; }
.gap-4 { gap: 16px; }
.mt-8 { margin-top: 32px; }
.text-sm { font-size: 0.875rem; }
.rounded { border-radius: 8px; }
.shadow { box-shadow: 0 4px 16px rgba(0,0,0,0.1); }
.sr-only { /* accessible: visible only to screen readers */
position: absolute; width: 1px; height: 1px;
overflow: hidden; clip: rect(0,0,0,0);
}
Professional Checklist
✓ Always use box-sizing: border-box globally
✓ Define color/font/spacing as CSS variables
✓ Write mobile-first media queries
✓ Use rem for font sizes, px for borders
✓ Keep specificity low (prefer classes over IDs)
✓ Group related properties (position → display → spacing → typography → visual)
✓ Use will-change: transform for heavy animations
✓ Test with browser DevTools (inspect, toggle, live-edit)
Modern CSS — 2024+ Features
CSS has evolved rapidly. Here are powerful modern features available in all current browsers.
/* :is() — match multiple selectors */
:is(h1, h2, h3) { font-weight: 700; }
:is(.card, .panel):hover { border-color: blue; }
/* :where() — same as :is() but zero specificity */
:where(article, section, aside) p { line-height: 1.7; }
/* :has() — parent selector (huge!) */
.card:has(img) { padding-top: 0; } /* card WITH an image */
label:has(+ input:invalid) { color: red; } /* label before invalid input */
/* container queries — style based on PARENT size */
.widget { container-type: inline-size; }
@container (min-width: 400px) {
.widget-title { font-size: 1.5rem; }
}
/* CSS nesting (native, no SASS needed) */
.card {
background: white;
&:hover { background: #f5f5f5; }
.card__title { font-size: 1.2rem; }
}
/* scroll-driven animations */
@keyframes fade-in {
from { opacity: 0; translate: 0 40px; }
to { opacity: 1; translate: 0 0; }
}
.reveal {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
Build a complete, production-quality landing page for a fictional SaaS product.
- Frosted glass navbar with
backdrop-filter: blur()andposition: sticky - Hero section with diagonal clip-path, gradient background, animated text reveal
- Bento-style feature grid using advanced CSS Grid (spanning cells, mixed sizes)
- Glassmorphism feature cards with
rgbabackgrounds andbackdrop-filter - Testimonials section with CSS Flexbox and hover transform effects
- Fully responsive using mobile-first media queries and CSS variables
- Smooth scroll animations using
@keyframesand animation delays
animation-timeline: view() — elements animate as they enter the viewport with zero JavaScript!
You've completed Learn CSS 🎉
Keep building. Here are the best next steps:
- → Learn Tailwind CSS — utility-first CSS framework
- → Learn CSS Modules or SCSS for large projects
- → Study CSS-in-JS (styled-components, Emotion) for React
- → Practice on Frontend Mentor challenges (frontendmentor.io)
- → Study great designs at Dribbble, Awwwards, Mobbin