More than half of all web traffic comes from phones. Responsive design means building one website that works well on every screen size, from a small phone to a wide desktop monitor.
Flexible units, Flexbox and Grid get you most of the way there. Media queries handle the rest by applying CSS only when a condition is true, such as "the screen is at least 768px wide" or "the visitor prefers dark mode". Search engines also check how pages behave on mobile, so responsive design affects how your site is found as well as how it feels.
How a media query works
@media (min-width: 768px) {
.sidebar { display: block; }
}The rules inside the braces only apply when the condition matches. The conditions you'll use most are:
(min-width: 768px): the screen is at least 768px wide.(max-width: 767px): the screen is at most 767px wide.(orientation: landscape): the screen is wider than it is tall.(prefers-color-scheme: dark): the visitor's device is set to dark mode.(prefers-reduced-motion: reduce): the visitor has asked for less animation.(hover: hover): the device has a real mouse or trackpad.
Media queries don't add specificity. If a rule inside a query doesn't apply, check that it comes after the rule it's meant to override.
The mobile-first approach
Write your base CSS for small screens first, then add min-width queries to enhance the layout on larger screens:
.grid { display: grid; gap: 1rem; } /* phones: 1 column */
@media (min-width: 640px) { .grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(4, 1fr); } }Phones get the simplest CSS, and you never have to undo desktop styles for small screens. Starting small also forces you to decide what really matters on the page.
Choosing breakpoints
A breakpoint is the width at which a media query switches the layout. There's no official list, but common choices are 640px (large phones), 768px (tablets), 1024px (laptops) and 1280px (desktops).
A better approach is to resize your browser slowly and add a breakpoint wherever your design starts to look cramped or stretched. Your content, not a list of device sizes, should decide where the breakpoints go.
Don't forget the viewport meta tag
Media queries only work properly on phones if your HTML includes:
<meta name="viewport" content="width=device-width, initial-scale=1">Without it, phones pretend to be a desktop-sized screen and shrink the whole page. See HTML Head & Meta Tags.
CSS Media Queries Syntax
Media query syntax
@media (min-width: 768px) { /* tablet and up */ }
@media (max-width: 767px) { /* phones only */ }
@media (prefers-color-scheme: dark) { }
@media (min-width: 768px) and (orientation: landscape) { }CSS Media Queries Summary
- Media queries apply CSS only when a condition, such as a minimum width, is true.
- Mobile-first means writing small-screen CSS first and adding
min-widthqueries. - Choose breakpoints where your own layout starts to break.
- Queries can also respond to dark mode and reduced-motion preferences.
- Responsive pages need the viewport meta tag in the HTML head.
CSS Media Queries Examples
Each example runs in the page. Edit the code and press Run to see what changes.
A mobile-first layout
Open in the Playground and switch between phone, tablet and desktop sizes.
<div class="layout">
<header>Header</header>
<nav>Menu</nav>
<main>Main content</main>
<aside>Extras</aside>
</div>.layout {
display: grid;
gap: 8px;
font: bold 15px sans-serif;
}
.layout > * { padding: 16px; border-radius: 10px; background: #e1e6ff; }
header { background: #ffd23f; }
@media (min-width: 600px) {
.layout { grid-template-columns: 160px 1fr; }
header { grid-column: 1 / -1; }
}
@media (min-width: 900px) {
.layout { grid-template-columns: 160px 1fr 160px; }
}Line-by-line explanation
- Lines 1 to 5Phones: one column, everything stacked.
- Lines 10 to 13From 600px: menu beside the content; the header spans the full width.
- Lines 15 to 17From 900px: a third column for extras.
Dark mode and reduced motion
If your computer is in dark mode, the card is dark. If you've turned on "reduce motion", the bounce stops.
<div class="card">
<span class="ball"></span>
<p>I follow your system settings.</p>
</div>.card {
padding: 20px;
border-radius: 14px;
background: #fbf7f0;
color: #15161b;
font-family: sans-serif;
}
.ball {
display: inline-block;
width: 24px;
height: 24px;
border-radius: 50%;
background: #f0592b;
animation: bounce 0.8s infinite alternate;
}
@keyframes bounce { to { transform: translateY(-16px); } }
@media (prefers-color-scheme: dark) {
.card { background: #171a21; color: #f2efe8; }
}
@media (prefers-reduced-motion: reduce) {
.ball { animation: none; }
}Line-by-line explanation
- Lines 20 to 22Swap colours when the operating system uses dark mode.
- Lines 24 to 26Respect people who get dizzy from motion.
Common CSS Media Queries Mistakes
Desktop-first max-width spaghetti
.nav { display: flex; }
@media (max-width: 1024px) { .nav { … } }
@media (max-width: 768px) { .nav { display: block; } }
@media (max-width: 480px) { … }.nav { display: block; }
@media (min-width: 768px) { .nav { display: flex; } }Starting from mobile usually means less CSS and fewer overrides.
Missing parentheses or "and"
@media min-width: 768px { … }
@media screen (min-width: 768px) { … }@media (min-width: 768px) { … }
@media screen and (min-width: 768px) { … }CSS Media Queries in Real Projects
Test like a pro
Open DevTools (F12) and press the device toolbar button (Ctrl + Shift + M) to preview any page as a phone, tablet or laptop. This site's header switches to a menu button below 1080px, and the lesson sidebar becomes a slide-out drawer below 900px. Both are media queries.
CSS Media Queries Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Apply the rule only on screens 768px wide or more.
@ (: 768px) {
.menu { display: flex; }
}
@media (min-width: …) targets screens at least that wide.In a mobile-first approach, which queries do you mostly write?
min-width adds enhancements for larger screens.Which media feature detects the user's dark mode setting?
prefers-color-scheme reflects the operating system preference.On screens 700px and wider, the two columns should sit side by side. The media query is broken. Fix it.
<div class="cols"><div>Left</div><div>Right</div></div>.cols { display: grid; gap: 10px; }
.cols > div { background: #d6f4e4; padding: 10px; }
@media min-width = 700px {
.cols { grid-template-columns: 1fr 1fr }- A valid (min-width: 700px) media rule exists
- The media rule sets two columns
CSS Media Queries Quiz
3 questions to check what you learned.
What does responsive design mean?
- A site that loads fast
- One site that adapts its layout to any screen size
- A separate mobile website
- A site with animations
@media (max-width: 600px)applies when the screen is…- wider than 600px
- exactly 600px
- 600px wide or narrower
- in portrait mode only
What do container queries respond to?
- The size of a parent container
- The screen size
- The number of children
- The device type
CSS Media Queries Challenge
Responsive cards
Make the cards:
- One column by default (mobile-first)
- Three columns from
min-width: 800px - Use
display: gridwith agapof12px
<div class="cards">
<div class="card">HTML</div>
<div class="card">CSS</div>
<div class="card">JS</div>
</div>.card { padding: 20px; background: #fff1c2; border: 2px solid #15161b; border-radius: 12px; font: 700 18px sans-serif; }
- Cards is a grid with 12px gap
- A min-width: 800px query exists
- The query creates three columns
- Mobile-first base (no columns outside the query)