CSS Media Queries
Breakpoints, responsive design, and modern query features
Media Query Syntax
A media query applies CSS rules only when certain conditions are met. The most common condition is viewport width:
/* Base styles (mobile) */
.container { padding: 16px; }
/* Tablet and up */
@media (min-width: 768px) {
.container { padding: 32px; }
}
/* Desktop and up */
@media (min-width: 1024px) {
.container { padding: 48px; max-width: 1200px; margin: 0 auto; }
}
This is mobile-first: base styles target small screens, then min-width queries layer on styles for larger viewports.
Common Breakpoints
| Name | min-width | Targets |
| Small mobile | 480px | Larger phones (landscape) |
| Tablet | 768px | Tablets, small laptops |
| Desktop | 1024px | Laptops, desktops |
| Wide | 1280px | Large monitors |
| Ultra-wide | 1536px | Ultra-wide / 4K scaled |
These are guidelines, not rules. Set breakpoints where your layout actually needs to change, not at specific device widths.
Mobile-First vs Desktop-First
Mobile-first (recommended)
/* Default: mobile */
.grid { display: flex; flex-direction: column; }
/* Upgrade for larger screens */
@media (min-width: 768px) {
.grid { flex-direction: row; }
}
Desktop-first (avoid if possible)
/* Default: desktop */
.grid { display: flex; flex-direction: row; }
/* Downgrade for smaller screens */
@media (max-width: 767px) {
.grid { flex-direction: column; }
}
Mobile-first works better because mobile styles are simpler. You start simple and add complexity. Desktop-first means overriding complex styles on mobile, which creates more CSS and more bugs.
Combining Conditions
/* AND: both conditions must be true */
@media (min-width: 768px) and (max-width: 1023px) {
/* tablet only */
}
/* OR: either condition */
@media (min-width: 1024px), (orientation: landscape) {
/* desktop OR landscape */
}
/* NOT */
@media not print {
/* everything except print */
}
/* Modern range syntax (Chrome 104+, Firefox 63+, Safari 16.4+) */
@media (768px <= width < 1024px) {
/* tablet range */
}
Preference Queries
Media queries are not just for screen size. You can detect user preferences:
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--text: #e2e8f0;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
/* High contrast */
@media (prefers-contrast: high) {
.button { border: 2px solid currentColor; }
}
Responsive Layout Example
A real-world responsive layout using mobile-first queries:
.page {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
padding: 16px;
}
@media (min-width: 768px) {
.page {
grid-template-columns: 250px 1fr;
padding: 24px;
}
}
@media (min-width: 1280px) {
.page {
grid-template-columns: 280px 1fr 250px;
max-width: 1400px;
margin: 0 auto;
}
}
Mobile: single column. Tablet: sidebar + main. Desktop: sidebar + main + aside.
Container Queries (Modern CSS)
Container queries let components respond to their parent size instead of the viewport. Use them for reusable components that need to adapt to available space:
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: flex;
flex-direction: row; /* horizontal layout when there is space */
}
}
@container (max-width: 399px) {
.card {
display: flex;
flex-direction: column; /* stacked when narrow */
}
}
Frequently Asked Questions
What are the standard CSS breakpoints?
There is no universal standard. Common values: 480px, 768px, 1024px, 1280px, 1536px. Tailwind and Bootstrap use slightly different sets. The best approach: set breakpoints where your specific layout breaks, not at arbitrary device widths.
Should I use mobile-first or desktop-first?
Mobile-first (min-width) is recommended. You write simpler base styles for mobile and layer on complexity for larger screens. Desktop-first (max-width) requires overriding complex styles for mobile, which creates more CSS and more opportunities for bugs.
What is the difference between @media and @container?
@media responds to the viewport size. @container responds to a parent element's size. Container queries are better for reusable components — the component adapts based on its available space, not the window width.