Introduction to Media Queries — Breakpoints and @media Syntax
A media query is a CSS at-rule that wraps a block of rules and applies them only when a specified condition is true. This is the mechanism that allows one stylesheet to serve every screen size. With media queries in place, you can say “apply these styles on screens wider than 768px” or “apply these styles when the user prefers dark mode” — and the browser will respect exactly that.
Basic @media syntax
Section titled “Basic @media syntax”@media (condition) { /* CSS rules — only applied when condition is true */}The condition is a media feature — a testable property of the browser environment. The most common media features test the viewport width:
/* Styles apply when viewport is 768px wide or wider */@media (min-width: 768px) { .site-nav { flex-direction: row; }}
/* Styles apply when viewport is 600px wide or narrower */@media (max-width: 600px) { .hero { min-height: 300px; }}The rules inside a media query block are regular CSS — selectors, properties, values. They behave exactly like rules outside a media query, except they only activate when the condition is met.
min-width vs max-width
Section titled “min-width vs max-width”min-width conditions activate when the viewport is at least that wide — “styles for screens this wide or wider.” This is the mobile-first approach.
max-width conditions activate when the viewport is at most that wide — “styles for screens this wide or narrower.” This is the desktop-first approach.
/* Mobile-first: base styles, then enhance upward */.tours-grid { flex-direction: column; /* mobile: single column */}
@media (min-width: 768px) { .tours-grid { flex-direction: row; /* tablet and above: horizontal */ flex-wrap: wrap; }}/* Desktop-first: full layout, then simplify downward */.tours-grid { flex-direction: row; /* desktop: horizontal */ flex-wrap: wrap;}
@media (max-width: 767px) { .tours-grid { flex-direction: column; /* mobile: stack vertically */ }}Both produce the same visual result. Lesson 05 covers why mobile-first (using min-width) is the better approach.
Common breakpoints
Section titled “Common breakpoints”There is no universal standard for breakpoint values — every design is different, and the principle of content-driven breakpoints (break where your layout starts to look bad, not at device sizes) is sound advice.
That said, these ranges are widely used and cover the device landscape well:
| Breakpoint | Width | Targets |
|---|---|---|
| Small phone | 480px | Large phones in portrait |
| Tablet | 768px | Tablets in portrait, large phones landscape |
| Small laptop | 1024px | Tablets landscape, small laptops |
| Desktop | 1280px | Laptops and desktop monitors |
For the STO site, two breakpoints handle most of the work: 768px (tablet) and 1024px (desktop).
Combining conditions
Section titled “Combining conditions”Use and to require multiple conditions to be true simultaneously:
/* Only apply between 600px and 1023px */@media (min-width: 600px) and (max-width: 1023px) { .tours-grid { /* tablet-specific layout */ }}Use a comma (,) to apply when either condition is true — like a logical OR:
/* Apply on small screens OR when printed */@media (max-width: 480px), print { .site-nav { display: none; }}Use not to negate a condition:
/* Apply on everything except screens wider than 1200px */@media not (min-width: 1200px) { /* ... */}prefers-color-scheme — dark mode
Section titled “prefers-color-scheme — dark mode”The prefers-color-scheme media feature detects whether the user has set their operating system to dark mode:
@media (prefers-color-scheme: dark) { :root { --color-bg: #1a1a2e; --color-text: #e8e8e8; }}This is how CSS dark mode is implemented without JavaScript. The browser reads the OS preference and applies the matching styles automatically. By overriding custom properties on :root, every rule that uses var(--color-bg) or var(--color-text) picks up the dark values automatically — you do not need to rewrite individual component rules inside the media query.
prefers-reduced-motion — accessibility-aware animation
Section titled “prefers-reduced-motion — accessibility-aware animation”The prefers-reduced-motion feature detects whether the user has requested reduced motion in their OS accessibility settings — typically set by users with vestibular disorders or motion sensitivity:
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition-duration: 0.01ms !important; }}If you add transitions or animations to the STO site later, wrapping them with this media query ensures they do not trigger in users who need motion-reduced experiences.
Where media queries live in your stylesheet
Section titled “Where media queries live in your stylesheet”Media queries go at the bottom of your stylesheet in a desktop-first approach, or interspersed with the rules they modify in a mobile-first approach. There is no performance difference — the browser reads all CSS before rendering.
The most readable pattern is to keep media queries near the rules they modify:
/* Base nav styles */.site-nav { display: flex; flex-direction: column; gap: 1rem;}
/* Tablet and up */@media (min-width: 768px) { .site-nav { flex-direction: row; gap: 2rem; }}The analogy: a media query is like a conditional outfit — “if it’s below 10°C, add the jacket.” The jacket rules only apply when the temperature condition is met. The rest of your wardrobe stays the same.
Exercise
Section titled “Exercise”Write your first responsive media queries for the STO site:
- Set a compact hero height as the mobile default and expand it for wider viewports:
.hero-section { min-height: 300px;}
@media (min-width: 601px) { .hero-section { min-height: 100vh; }}- Use a slightly smaller body font on narrow screens, upgrading to the full size on wider viewports:
body { font-size: 0.875rem;}
@media (min-width: 401px) { body { font-size: 1rem; }}-
Open DevTools Device Toolbar. Set the width to 375px and confirm the hero height is 300px and the font size is 0.875rem. Increase the width to 800px and confirm the hero returns to
100vhand the font size to1rem. -
Try adding a
prefers-color-scheme: darkblock that changes the body background to a dark color. Toggle your OS dark mode setting and reload — the page should switch.
@media (condition) { }applies CSS rules only when the condition is true.min-widthfires when the viewport is at least that wide (mobile-first / enhance upward).max-widthfires when the viewport is at most that wide (desktop-first / simplify downward).- Common STO breakpoints: 768px (tablet), 1024px (desktop).
- Combine conditions with
and(both true),,(either true),not(negate). prefers-color-scheme: darkenables dark mode support.prefers-reduced-motion: reducerespects users who need less animation.
Lesson 06 brings Flexbox and media queries together into the complete responsive STO layout — navigation, card grid, and hero — all working from mobile to desktop.