Media queries are a CSS feature that allows you to apply styles conditionally based on device characteristics like screen width, height, orientation, resolution, and user preferences. They are the foundation of responsive web design, enabling websites to adapt their layout and appearance across different devices from mobile phones to large desktop monitors.
Introduced in CSS3, media queries use the @media rule to test one or more conditions. If the conditions are met, the CSS rules inside the media query are applied. This allows developers to create fluid, adaptive designs that provide optimal viewing experiences on any device without requiring separate mobile and desktop versions.
Media types specify the category of device for which styles should be applied. While CSS2 defined many media types, most are now deprecated. Modern CSS focuses on four main types:
| Type | Description | Use Case |
|---|---|---|
all | Default - applies to all devices | General styles that work everywhere |
screen | Computer screens, tablets, smartphones | Most common - digital displays |
print | Print preview mode and printed pages | Printer-friendly versions |
speech | Screen readers and speech synthesizers | Accessibility for visually impaired users |
The screen type is most commonly used and is often omitted since it's the default for most media queries. The print type is valuable for creating printer-friendly versions of web pages by hiding navigation, sidebars, and ads.
Media queries use a specific syntax that combines media types with media features. The basic structure is @media [type] [logical operator] (feature) { CSS rules }. You can combine multiple conditions using logical operators like and, not, and only.
/* Basic syntax */
@media screen and (max-width: 768px) {
/* Styles for screens up to 768px wide */
}
/* Multiple conditions with AND */
@media screen and (min-width: 768px) and (max-width: 1024px) {
/* Styles for screens between 768px and 1024px */
}
/* OR operator using comma */
@media (max-width: 768px), (orientation: portrait) {
/* Styles for small screens OR portrait orientation */
}
/* NOT operator */
@media not print {
/* Styles for everything except print */
}
/* ONLY operator (legacy browser support) */
@media only screen and (min-width: 768px) {
/* Only applies to screens, ignored by old browsers */
}
Media features are the conditions you test in media queries. They describe specific characteristics of the device or browser. Here are the most commonly used features:
portrait or landscapehover or none)fine, coarse, none)light or dark mode preferencereduce or no-preferencehigh, low, or no-preferenceBreakpoints are specific screen widths where your design changes to accommodate different devices. While there's no universal standard, these breakpoints are widely used and based on common device sizes:
/* Mobile-First Approach (Recommended) */
/* Start with mobile styles, then add larger screens */
/* Extra Small devices (phones, less than 576px) */
/* No media query needed - this is the base */
body {
font-size: 14px;
padding: 10px;
}
.container {
width: 100%;
padding: 0 15px;
}
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
/* Small devices (landscape phones, 576px and up) */
@media (min-width: 576px) {
body {
font-size: 15px;
}
.container {
max-width: 540px;
margin: 0 auto;
}
}
/* Medium devices (tablets, 768px and up) */
@media (min-width: 768px) {
body {
font-size: 16px;
padding: 20px;
}
.container {
max-width: 720px;
}
.grid {
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.sidebar {
display: block; /* Show sidebar on tablets */
}
}
/* Large devices (desktops, 992px and up) */
@media (min-width: 992px) {
.container {
max-width: 960px;
}
.grid {
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
.nav {
display: flex; /* Horizontal navigation */
}
}
/* Extra large devices (large desktops, 1200px and up) */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
}
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
/* Extra extra large (1400px and up) */
@media (min-width: 1400px) {
.container {
max-width: 1320px;
}
}
Orientation media queries detect whether a device is in portrait (height > width) or landscape (width > height) mode. This is particularly useful for tablets and phones that can be rotated.
/* Portrait orientation (height > width) */
@media (orientation: portrait) {
.hero {
height: 80vh;
flex-direction: column;
}
.image-gallery {
grid-template-columns: repeat(2, 1fr);
}
.video-player {
aspect-ratio: 9/16; /* Vertical video */
}
}
/* Landscape orientation (width > height) */
@media (orientation: landscape) {
.hero {
height: 60vh;
flex-direction: row;
}
.image-gallery {
grid-template-columns: repeat(4, 1fr);
}
.video-player {
aspect-ratio: 16/9; /* Horizontal video */
}
}
/* Combine with width for precise control */
@media (max-width: 768px) and (orientation: landscape) {
/* Small screens in landscape - like phones rotated */
.navbar {
height: 50px; /* Shorter navbar to save space */
}
.content {
padding: 10px; /* Less padding */
}
}
The prefers-color-scheme media feature detects if the user has requested a light or dark color theme at the operating system level. Supporting dark mode improves user experience and reduces eye strain in low-light environments.
/* Define CSS variables for theming */
:root {
/* Light mode (default) */
--bg-primary: #ffffff;
--bg-secondary: #f8f9fa;
--text-primary: #212529;
--text-secondary: #6c757d;
--border-color: #dee2e6;
--link-color: #0d6efd;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #1a1a2e;
--bg-secondary: #16213e;
--text-primary: #eee;
--text-secondary: #adb5bd;
--border-color: #495057;
--link-color: #6ea8fe;
}
/* Adjust images for dark mode */
img {
opacity: 0.9;
filter: brightness(0.9);
}
/* Invert icons if needed */
.icon {
filter: invert(1);
}
}
/* Apply variables */
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}
.card {
background-color: var(--bg-secondary);
border-color: var(--border-color);
}
a {
color: var(--link-color);
}
The prefers-reduced-motion media feature detects if users have requested minimal animation. This is crucial for accessibility, as some users experience motion sickness or vestibular disorders triggered by animations.
/* Default: animations enabled */
.button {
transition: all 0.3s ease;
}
.modal {
animation: slideIn 0.5s ease-out;
}
.loader {
animation: spin 1s linear infinite;
}
/* Respect user's motion preference */
@media (prefers-reduced-motion: reduce) {
/* Disable or minimize all animations */
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
/* Keep essential animations but make them instant */
.button {
transition: none;
}
.modal {
animation: none;
}
/* Disable infinite animations completely */
.loader {
animation: none;
/* Show static loading indicator instead */
opacity: 0.7;
}
}
@keyframes slideIn {
from { transform: translateY(-100%); }
to { transform: translateY(0); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
Print media queries create printer-friendly versions of web pages. They typically hide navigation, sidebars, and ads while optimizing typography and layout for paper.
@media print {
/* Hide non-essential elements */
.navbar,
.sidebar,
.footer,
.ads,
.social-share,
.comments,
button,
video {
display: none !important;
}
/* Reset page styles */
body {
font-size: 12pt;
line-height: 1.5;
color: black;
background: white;
margin: 0;
padding: 0;
}
/* Optimize typography */
h1 { font-size: 24pt; }
h2 { font-size: 18pt; }
h3 { font-size: 14pt; }
/* Show link URLs */
a::after {
content: " (" attr(href) ")";
font-size: 10pt;
color: #666;
}
/* Prevent page breaks inside elements */
h1, h2, h3, h4, h5, h6 {
page-break-after: avoid;
page-break-inside: avoid;
}
img, table, pre, blockquote {
page-break-inside: avoid;
}
/* Ensure images fit on page */
img {
max-width: 100% !important;
height: auto !important;
}
/* Add page breaks where needed */
.page-break {
page-break-before: always;
}
/* Expand collapsed content */
details {
display: block;
}
details summary {
display: none;
}
details[open] {
display: block;
}
}
The hover and pointer media features detect input capabilities. This helps differentiate between touch devices (phones, tablets) and devices with precise pointing devices (mouse, trackpad).
/* Devices that support hover (mouse, trackpad) */
@media (hover: hover) and (pointer: fine) {
.button:hover {
background-color: #2980b9;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.tooltip {
display: none;
}
.card:hover .tooltip {
display: block;
}
/* Subtle hover effects */
.link:hover {
text-decoration: underline;
}
}
/* Touch devices (no hover capability) */
@media (hover: none) and (pointer: coarse) {
/* Use :active instead of :hover */
.button:active {
background-color: #2980b9;
}
/* Make touch targets larger (minimum 44x44px) */
.button,
.link {
min-height: 44px;
min-width: 44px;
padding: 12px 20px;
}
/* Show tooltips by default or on tap */
.tooltip {
display: block;
position: static;
}
/* Remove hover-dependent features */
.dropdown:hover .dropdown-menu {
display: none; /* Don't rely on hover */
}
}
/* Coarse pointer (touch, stylus) */
@media (pointer: coarse) {
/* Increase spacing for easier tapping */
.nav-item {
margin: 8px 0;
}
input,
select,
textarea {
font-size: 16px; /* Prevent zoom on iOS */
}
}
/* Fine pointer (mouse, trackpad) */
@media (pointer: fine) {
/* Smaller, more precise controls */
.close-button {
width: 20px;
height: 20px;
}
}
High-resolution displays (Retina, 4K) require higher quality images. The resolution media feature detects pixel density to serve appropriate image assets.
/* Standard resolution (1x) */
.logo {
background-image: url('logo.png');
width: 200px;
height: 50px;
}
/* High resolution (2x) - Retina displays */
@media (min-resolution: 192dpi),
(min-resolution: 2dppx) {
.logo {
background-image: url('logo@2x.png');
background-size: 200px 50px;
}
}
/* Extra high resolution (3x) - newer phones */
@media (min-resolution: 288dpi),
(min-resolution: 3dppx) {
.logo {
background-image: url('logo@3x.png');
background-size: 200px 50px;
}
}
/* Alternative: use image-set() */
.hero {
background-image: image-set(
url('hero.jpg') 1x,
url('hero@2x.jpg') 2x,
url('hero@3x.jpg') 3x
);
}
min-width queries for larger screensem or rem over px in media queries for better accessibilityprefers-reduced-motion and prefers-color-schemehover: none to detect touch devices and adjust interactions@media print for better printing experiencemax-width for mobile-first (use min-width instead)<meta name="viewport" content="width=device-width, initial-scale=1">prefers-reduced-motionExplore 500+ free tutorials across 20+ languages and frameworks.