Difficulty: Beginner
How do CSS media queries work? What are common breakpoints?
Media queries apply styles conditionally based on device characteristics.
Syntax: @media (condition) { rules }
Media types: screen, print, all Media features: width, height, orientation, prefers-color-scheme, prefers-reduced-motion, hover, pointer
Common breakpoints: - 480px: small phones - 640px: large phones - 768px: tablets - 1024px: laptops - 1280px: desktops - 1536px: large screens
Mobile-first uses min-width, desktop-first uses max-width.
/* Base: mobile styles */
.sidebar { display: none; }
.content { padding: 1rem; }
/* Small tablets: 640px+ */
@media (min-width: 640px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
/* Tablets: 768px+ */
@media (min-width: 768px) {
.sidebar { display: block; }
.layout {
display: grid;
grid-template-columns: 250px 1fr;
}
}
/* Laptops: 1024px+ */
@media (min-width: 1024px) {
.grid { grid-template-columns: repeat(3, 1fr); }
}
/* Desktops: 1280px+ */
@media (min-width: 1280px) {
.container {
max-width: 1200px;
margin: 0 auto;
}
}
/* Combining conditions */
@media (min-width: 768px) and (max-width: 1023px) {
/* Tablet only */
}
Mobile-first breakpoints build up complexity. Each larger breakpoint adds layout features. This is progressive enhancement.
/* Dark mode preference */
@media (prefers-color-scheme: dark) {
:root {
--bg: #111827;
--text: #f9fafb;
}
}
/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
/* High contrast preference */
@media (prefers-contrast: high) {
.card { border: 2px solid currentColor; }
}
/* Hover capability (touchscreen detection) */
@media (hover: hover) {
.card:hover { transform: translateY(-2px); }
}
@media (hover: none) {
/* Touchscreen - no hover effects */
.tooltip { display: none; }
}
/* Orientation */
@media (orientation: landscape) {
.hero { height: 100dvh; }
}
/* Resolution (retina) */
@media (min-resolution: 2dppx) {
.logo { background-image: url('logo@2x.png'); }
}
Feature queries let you adapt to user preferences and device capabilities, not just screen size. hover: none detects touchscreens.
/* Check if browser supports a CSS feature */
@supports (display: grid) {
.layout {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
/* Fallback for older browsers */
.layout {
display: flex; /* fallback */
flex-wrap: wrap;
}
@supports (display: grid) {
.layout {
display: grid; /* upgrade if supported */
}
}
/* Check for :has() support */
@supports selector(:has(*)) {
.card:has(img) {
grid-template-rows: auto 1fr;
}
}
/* Negation */
@supports not (backdrop-filter: blur(10px)) {
.modal-overlay {
background: rgb(0 0 0 / 0.8);
/* Solid fallback when blur isn't supported */
}
}
@supports is CSS feature detection (like Modernizr but native). Use it to provide fallbacks for newer CSS features.
Media Queries, Breakpoints, Feature Queries, Responsive Design, Print Styles