Every screen is different. And your CSS needs to keep up with all of them.

Media queries are the CSS3 mechanism that makes responsive web design possible. They let you apply styles conditionally based on viewport width, device orientation, screen resolution, and even user preferences like dark mode.

With mobile devices driving over 61% of global web traffic (Statista, 2024), getting layout adaptation right is not optional.

This article covers everything from basic media query syntax to container queries, breakpoints, performance, and the JavaScript matchMedia API. By the end, you will know exactly how media queries work and how to use them correctly.

What Are Media Queries?

A media query is a CSS technique that applies style rules based on specific device or viewport conditions. When a defined condition is true, the browser applies the associated CSS block. When it is false, the block is ignored entirely.

Media queries are part of the CSS3 specification, standardized by the W3C in 2010. The W3C updated the Media Queries Level 3 recommendation as recently as 2024, confirming its continued role as a foundational web standard.

The core syntax has 3 components: the @media keyword, a media type, and one or more media feature expressions. For example:

@media screen and (max-width: 768px) { ... }

This tells the browser: if the device is a screen and the viewport is 768px wide or narrower, apply the enclosed styles.

Media queries work in 3 places: external stylesheets linked via <link>, internal <style> blocks inside HTML, and directly inside CSS files using the @media at-rule. Browser support covers all modern browsers, including Chrome 4+, Firefox 3.5+, Safari 4+, and Edge.

ComponentExamplePurpose
Media typescreenprintallDefines the output device category
Media featuremax-width: 768pxSets the condition to evaluate
Logical operatorandnot, commaCombines or negates conditions

The CSS cascade still applies inside media queries. Specificity and source order determine which rules win when conditions overlap.

How Do Media Queries Work?

The browser evaluates each media query condition on page load and again whenever the viewport changes, such as when a user resizes the browser window or rotates a device.

Evaluation is continuous, not one-time. If the user resizes the window from 1200px down to 480px, the browser re-checks all active media query conditions and applies or removes CSS blocks in real time.

Where is web design headed next?

Discover the latest web design statistics: industry growth, design trends, technology adoption, and insights defining the future of the web.

Explore the Data →

When a condition is true, the styles inside that block join the cascade. When false, they are skipped. The browser does not load a separate stylesheet or create a new rendering context. All CSS, including rules inside non-matching media queries, is parsed by the browser at load time.

This matters for performance. A stylesheet with 20 media query blocks is still one file. All 20 blocks are parsed and held in memory regardless of which conditions currently match.

Key process flow:

  • Browser parses the full CSS file, including all @media blocks
  • Conditions are evaluated against current viewport and device properties
  • Matching blocks enter the cascade; non-matching blocks are ignored
  • On viewport change, conditions are re-evaluated and styles update without a page reload

Google completed its rollout of mobile-first indexing in July 2024, meaning the mobile version of a page is now the primary version used for ranking. Sites without responsive styles applied through media queries risk ranking penalties from that crawl.

What Is the Syntax of a Media Query?

Media query syntax follows a predictable pattern, but the details trip up a lot of developers. Missing parentheses around features is one of the most common causes of a media query silently failing.

Media Types

The 3 media types used in practice are screenprint, and all.

screen targets displays: monitors, phones, tablets. print applies only when the page is printed or previewed for printing. all matches every output device and is the default when no type is specified.

Two other types exist in the spec (speech for screen readers, projection for projected presentations), but projection was deprecated in Media Queries Level 4. In daily work, screen and print cover almost every use case.

Media Features

Media features are the actual conditions being tested. They must always be wrapped in parentheses.

The most-used features in production CSS:

  • width / min-width / max-width: tests viewport width
  • height / min-height / max-height: tests viewport height
  • orientation: checks portrait vs landscape
  • resolution: targets high-DPI (retina) screens
  • prefers-color-scheme: detects light or dark mode preference
  • prefers-reduced-motion: detects motion sensitivity settings
  • hover: checks whether the primary input device supports hover

HTTP Archive (2024) data shows 768px appears in 67% of responsive sites, making min-width: 768px and max-width: 767px the single most common breakpoint pair in production.

Logical Operators in Media Queries

4 logical operators control how conditions combine: andnotonly, and a comma acting as OR.

The comma is where developers most often get confused. A comma between 2 queries means either condition can match. and requires both. not inverts a full query. only was originally meant to hide queries from old browsers that only understood media types, but it has no practical use in modern browsers.

/* Both conditions must be true */
@media screen and (min-width: 768px) { ... }

/* Either condition can be true */
@media (max-width: 480px), (orientation: portrait) { ... }

/* Condition must be false */
@media not screen { ... }

Media Queries Level 4 also introduced range syntax: @media (width >= 768px) instead of @media (min-width: 768px). Both are valid. Range syntax is supported in Chrome 104+, Firefox 63+, and Safari 16.4+.

What Is the Difference Between min-width and max-width in Media Queries?

This is the single most important decision when starting a stylesheet. Get it wrong, and you spend the next 3 months fighting CSS specificity issues you created yourself.

min-width applies styles when the viewport is equal to or wider than the specified value. You write base styles for small screens first, then add complexity as screens get larger. This is the mobile-first approach.

max-width applies styles when the viewport is equal to or narrower than the value. You write full desktop styles first, then override them for smaller screens. This is the desktop-first approach.

ApproachStarting pointAdds styles forBest for
Mobile-first (min-width)Small screensLarger viewportsNew projects, performance-sensitive builds
Desktop-first (max-width)Large screensSmaller viewportsRetrofitting existing desktop-only sites

Mobile-first is the recommended standard. Mobile devices account for over 61% of global website traffic (Statista, 2024), and mobile-first CSS loads faster on low-powered devices because the base styles are simpler.

Desktop-first is not wrong. It is just tricky to maintain. Overriding complex desktop layouts with max-width queries tends to produce longer stylesheets with more specificity conflicts. At least in my experience, teams that start desktop-first spend significantly more time debugging layout issues on smaller screens.

Mixing both approaches in the same stylesheet without a clear strategy is where things break. Pick one and stick to it across the full project.

What Are the Standard Media Query Breakpoints?

No universal breakpoint standard exists. Different CSS frameworks use different values, and the “right” breakpoints for a project depend on the content, not the device.

That said, some values appear consistently across the industry because they align with real device distribution data.

Common Breakpoint Ranges

HTTP Archive (2024) data shows the most commonly used breakpoints across responsive sites: **768px** in 67% of sites, 1024px in 54%, and 320px in 43%.

The current recommended breakpoint set for 2025 (DevToolBox):

  • 480px: mobile landscape
  • 768px: tablet
  • 1024px: laptop
  • 1280px: desktop
  • 1536px: large desktop and 4K

Framework Breakpoints vs. Custom Breakpoints

Bootstrap 5 uses 6 breakpoints: 576px, 768px, 992px, 1200px, and 1400px. Tailwind CSS defaults to 5: 640px, 768px, 1024px, 1280px, and 1536px. Both frameworks allow customization.

Google Developers recommends against device-specific breakpoints entirely. The better practice is content-driven: add a breakpoint where your layout visually breaks, not where a specific device model happens to sit.

The biggest mistake most developers make is copying framework breakpoints directly into a custom stylesheet without testing whether those values make sense for their specific content. Bootstrap’s 992px breakpoint exists because it worked for Bootstrap’s grid. It might not be the right value for your layout.

How Are Media Queries Used in Responsive Design?

Responsive web design rests on 3 foundations: fluid grids, flexible images, and media queries. Ethan Marcotte coined the term in 2010 and identified these as the core building blocks. Media queries are the conditional layer that triggers layout changes at specific points.

Around 90% of websites have implemented responsive design as of 2024, and 73.1% of web designers cite non-responsive design as the primary reason visitors leave a site (Hostinger, 2024).

Media Queries with Flexbox

Flexbox handles alignment and distribution within a single row or column. Media queries change how Flexbox behaves at different viewport widths.

Common pattern:

/* Mobile: single column */
.container {
display: flex;
flex-direction: column;
}

/* Tablet and up: row layout */
@media (min-width: 768px) {
.container {
flex-direction: row;
}
}

This pattern stacks elements vertically on small screens and shifts them into a horizontal row on wider viewports. Airbnb’s property card grid uses exactly this approach: single-column on mobile, multi-column on tablet and desktop, controlled entirely through media queries and Flexbox.

Media Queries with CSS Grid

CSS Grid defines two-dimensional layouts. Media queries switch the grid structure at different breakpoints.

Typical grid shift:

/* Mobile: 1 column */
.grid {
display: grid;
grid-template-columns: 1fr;
}

/* Desktop: 3 columns */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}

CSS Grid had 97.2% browser support as of 2024 (MDN). It is safe to use in production without fallbacks for any project targeting modern browsers.

The grid system and media queries work together: grid defines the structure, media queries decide when that structure changes.

One thing worth noting is that responsive typography is also managed through media queries. Font sizes, line heights, and heading scales often change across breakpoints to keep text readable on small screens and proportional on large ones.

What Are Container Queries and How Do They Differ from Media Queries?

Media queries respond to viewport size. Container queries respond to the size of a parent element. That is the entire difference, and it is a big one for component-based development.

Container queries reached 93% browser support in November 2024 (Josh W. Comeau, 2024), covering Chrome 105+, Safari 16+, and Firefox 110+. Despite wide availability, actual usage in the State of CSS 2025 survey showed only 41% of developers had used container size queries even once.

When Media Queries Fall Short

The problem media queries cannot solve: a card component placed in a narrow sidebar looks different from the same card placed in a wide main content area. Both scenarios exist at the same viewport width.

Media queries see only the viewport. They have no awareness of where a component is placed in the layout. This forces developers to write context-specific overrides for the same component in different layouts.

Container queries fix this. The card responds to its own container width, not the screen width.

Container Query Syntax

Container queries require 2 things: a container-type on the parent and a @container rule on the child.

/* Parent */
.card-wrapper {
container-type: inline-size;
}

/* Child responds to parent width */
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}

container-type values: inline-size enables queries on the inline axis (width in horizontal writing modes). size enables queries on both axes. normal is the default and disables container query behavior.

Using Both Together

Media queries and container queries are not in competition. They handle different scopes.

FeatureMedia QueriesContainer Queries
Responds toViewport sizeParent element size
Best forPage-level layout shiftsComponent-level layout shifts
Requires setupNoYes (container-type on parent)
Browser support (2024)100% modern browsers~93% (Chrome, Firefox, Safari)

Use media queries for the overall page structure: column counts, sidebar visibility, navigation layout. Use container queries for components that get reused in different layout contexts. A design system component that appears in a sidebar, a modal, and a main feed is the perfect container query candidate.

The hamburger menu is a good real-world example. Media queries control when it appears based on viewport width. Container queries could control how the menu items inside it reflow based on the menu container’s own dimensions.

How Do Media Queries Affect Page Performance?

CSS is a render-blocking resource by default. The browser will not paint any content until the CSSOM is fully constructed, and media queries sit inside that CSS (Google Web Fundamentals).

Every stylesheet is downloaded regardless of whether its conditions match. A <link> tag with a non-matching media query is still fetched, just at low priority. The parsing cost is unavoidable.

Where media queries do affect performance is CSS file size. Inline media queries scattered across component files add up. Without gzip compression, bloated CSS increases the size of the render-blocking resource directly.

53% of mobile users abandon a page that takes more than 3 seconds to load (Google). Keeping CSS lean, including media query blocks, is part of hitting that threshold.

How Linked Stylesheets Handle Media Queries

Using the media attribute on a <link> tag changes priority, not download behavior.

Priority rules from web.dev:

  • <link rel="stylesheet"> – render-blocking, always high priority
  • <link rel="stylesheet" media="print"> – low priority on screen load, does not block render
  • <link rel="stylesheet" media="(min-width: 40em)"> – blocks render if condition matches at load time

A print stylesheet linked with media="print" does not block rendering on screen. That is the one clear performance win from media attribute targeting.

CSS-in-JS and Media Query Overhead

Styled Components and Emotion generate media query rules at runtime. Each component mount triggers style injection, adding JavaScript execution time on top of CSS parse time.

Runtime overhead comparison:

Static CSS: parsed once at load, no JS cost for media queries.

CSS-in-JS: styles generated and injected per component render, media query evaluation happens client-side after JavaScript executes.

For most projects, the difference is minor. On large pages with hundreds of dynamic components, it compounds. Teams at Spotify and Atlassian have cited CSS-in-JS performance as a reason to move back to static stylesheets for high-traffic pages.

What Are the New Features in Media Queries Level 4 and Level 5?

The Media Queries specification has expanded well past viewport width checks. Level 4 and Level 5 introduce features that read user preferences directly from the operating system, which changes how accessibility and theming work in CSS.

FeatureSpec LevelWhat It DetectsBrowser Support
Range syntaxLevel 4Width/height with >= and <= operatorsChrome 104+, Firefox 63+, Safari 16.4+
prefers-color-schemeLevel 5Dark or light mode OS settingChrome 76+, Firefox 67+, Safari 12.1+
prefers-reduced-motionLevel 5Reduce animation OS settingChrome 74+, Firefox 63+, Safari 10.1+
prefers-contrastLevel 5High contrast OS preferenceChrome 96+, Safari 14.1+, Firefox 101+
forced-colorsLevel 5Windows High Contrast ModeChrome 89+, Edge 79+, limited Firefox

User Preference Media Features

Over 80% of users prefer dark mode in low-light environments (NateBal.com, 2024). The prefers-color-scheme media feature reads the OS-level dark or light mode setting and lets CSS respond without any JavaScript.

Basic dark mode pattern:

@media (prefers-color-scheme: dark) {
:root {
--bg: #0f0f0f;
--text: #f0f0f0;
}
}

The light-dark() CSS function, fully supported since May 2024 across Chrome, Firefox, and Safari, simplifies this further by accepting 2 color values in a single declaration without writing 2 separate media query blocks.

Accessibility Media Features

Vestibular disorders affect more than 70 million people (CSS-Tricks). For these users, parallax effects, carousels with slide animations, and similar motion can cause vertigo and nausea. prefers-reduced-motion is how CSS addresses this.

What the feature does not mean: it is not a signal to remove all animation. WCAG 2.3.3 specifies that motion animation should be disabled unless it is essential to the functionality being conveyed. The pattern is to replace motion with a fade or static alternative, not a blank state.

@media (prefers-reduced-motion: reduce) {
.animated-element {
animation: none;
transition: none;
}
}

Both prefers-reduced-motion and prefers-color-scheme can be simulated in Chrome DevTools under the Rendering tab, which removes the need to change OS settings during development.

How Do Media Queries Work in JavaScript?

CSS media queries handle presentation. When logic needs to change, not just styles, window.matchMedia() brings the same conditions into JavaScript.

The method returns a MediaQueryList object with a matches boolean. Global browser support for window.matchMedia() sits at 98.6%, covering all modern browsers back to IE10 (CSS-Tricks, Can I Use data).

Basic matchMedia Usage

One-time check:

const mq = window.matchMedia('(min-width: 768px)');
if (mq.matches) {
// viewport is 768px or wider
}

This evaluates the condition at the moment it runs. It does not update if the viewport changes.

Persistent listener:

mq.addEventListener('change', (e) => {
if (e.matches) {
// crossed 768px threshold going up
}
});

The addListener() method used in older tutorials was deprecated in Chrome 95. The correct API is addEventListener('change', callback) on the MediaQueryList object (MDN, 2024).

When to Use matchMedia vs. CSS

CSS should handle layout and visual changes. JavaScript’s matchMedia is for behavior changes that CSS cannot control.

Use matchMedia for:

  • Conditionally loading scripts or heavy components only on desktop
  • Switching between touch and mouse interaction handlers
  • Detecting orientation changes in HTML5 games or full-screen experiences

Avoid matchMedia for: anything CSS can already handle. Using window.innerWidth inside a resize event listener to replicate what a CSS media query does is slower and less accurate. matchMedia fires only when the condition changes state; resize fires on every pixel change.

What Are Common Media Query Mistakes?

Most media query bugs come from 3 places: missing HTML setup, conflicting CSS rules, and over-reliance on media queries for problems they were not designed to solve.

Missing the Viewport Meta Tag

This is the most common reason media queries appear to work in Chrome DevTools but fail on a real phone.

Without <meta name="viewport" content="width=device-width, initial-scale=1.0">, mobile browsers render the page at a default desktop width (typically 980px) and then scale it down. The viewport the browser reports to CSS is 980px, so max-width: 768px never triggers.

The fix is one line in the HTML head:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Common mistakes with the tag itself: setting content="width=1024" forces a fixed viewport width on all devices. Adding user-scalable=no blocks zoom for users with low vision, which is an accessibility violation under WCAG.

Mixing min-width and max-width Without a Strategy

Mixing both approaches in the same stylesheet creates specificity conflicts that are genuinely hard to debug. It usually happens when desktop-first legacy code gets mobile-first styles added on top.

A real example of the conflict:

/* Desktop-first rule */
@media (max-width: 768px) { .nav { display: none; } }

/* Mobile-first rule added later */
@media (min-width: 768px) { .nav { display: flex; } }

At exactly 768px, both rules match. Source order decides which wins. Took me an embarrassingly long time to track that down the first time. The fix is to pick one approach per project and document it.

Using Device-Specific Breakpoints

Setting breakpoints at 375px (iPhone SE), 390px (iPhone 14), and 414px (iPhone Pro Max) seems logical. It is not.

Device screen dimensions change every year. A breakpoint set for the iPhone 14 is already outdated for the 16 Pro Max. Content-driven breakpoints, where you add a breakpoint where the layout visually breaks during testing, remain stable regardless of which devices exist.

Google Developers has recommended this content-first approach since 2014. It is still the right method.

Skipping srcset for Responsive Images

Media queries control layout. They do not control which image file loads. Using a media query to swap a background image via CSS will download both images on some browsers. Responsive design for images requires the srcset and sizes attributes on <img> tags, not CSS.

Wrong approach (CSS background swap):

/* This can cause both images to download */
.hero { background-image: url('large.jpg'); }
@media (max-width: 480px) {
.hero { background-image: url('small.jpg'); }
}

Right approach:

<img
src="large.jpg"
srcset="small.jpg 480w, large.jpg 1200w"
sizes="(max-width: 480px) 480px, 1200px"
alt="..."
>

The viewport size, pixel density, and network conditions all factor into which file the browser selects with srcset. CSS background swaps have no access to any of that.

The mobile-first design approach, combined with correct use of srcset, is how you avoid shipping a 1.2MB hero image to a phone on a slow connection.

FAQ on Media Queries

What is a media query in CSS?

A media query is a CSS rule that applies styles only when a defined condition is true. It checks properties like viewport width, orientation, or resolution, then activates or ignores the associated CSS block based on the result.

What is the basic syntax of a media query?

The syntax uses the @media keyword, a media type, and a condition in parentheses. For example: @media screen and (min-width: 768px) { ... }. The styles inside apply only when the screen is 768px wide or wider.

What is the difference between min-width and max-width?

min-width targets viewports equal to or wider than the value, supporting a mobile-first approach. max-width targets viewports equal to or narrower. Mobile-first using min-width is the recommended standard for new projects.

Do media queries affect page load speed?

CSS is render-blocking by default, so large stylesheets with many media query blocks slow parse time. Non-matching <link> stylesheets still download, just at lower priority. Keeping CSS lean directly reduces render-blocking overhead.

What are the standard breakpoints for media queries?

No universal standard exists. Common values are 480px, 768px, 1024px, 1280px, and 1536px. Bootstrap 5 and Tailwind CSS use similar ranges. Best practice is to set breakpoints where your content breaks, not where specific devices sit.

What is the difference between media queries and container queries?

Media queries respond to the viewport size. Container queries respond to a parent element’s size. Use media queries for page-level layout shifts. Use container queries for components that appear in multiple layout contexts.

How do media queries work in JavaScript?

window.matchMedia() evaluates a media query string and returns a MediaQueryList object with a matches boolean. Adding an addEventListener('change', callback) lets JavaScript react whenever the condition changes state.

What are user preference media features?

These are Level 5 features that read OS-level settings. prefers-color-scheme detects dark or light mode. prefers-reduced-motion detects motion sensitivity. prefers-contrast detects high-contrast preferences. All are supported in Chrome 76+, Firefox 67+, and Safari 12.1+.

What is the most common media query mistake?

Missing the <meta name="viewport"> tag. Without it, mobile browsers render pages at a default 980px desktop width. Media queries never trigger correctly on real devices because the reported viewport width stays fixed at desktop size.

Are media queries still relevant with container queries available?

Yes. Media queries handle page-level layout: column structure, sidebar visibility, global navigation changes. Container queries handle component-level adaptation. The 2 features cover different scopes and work best when used together.

%MINIFYHTML24fed191fa78d0a03ecb118f5a280324b337f51d4d691365bace5f4497b1bd7d6%

Conclusion

This conclusion is for an article presenting what are media queries, and the core message is straightforward: they remain the foundation of cross-device CSS.

From controlling breakpoints and fluid layouts to reading OS-level user preferences like prefers-reduced-motion, media queries cover far more than viewport width.

Pair them with container queries for component-level control. Use window.matchMedia() when behavior, not just styling, needs to shift.

Always include the viewport meta tag. Pick mobile-first or desktop-first and stick to it. Set content-driven breakpoints, not device-specific ones.

Get these fundamentals right, and your layouts will hold up across every screen size, orientation, and pixel density without fighting your own stylesheet.