A Practical Guide to CSS Media Queries

In this article, we'll take a closer look at what media queries are, how they work, and how to use them correctly, including for creating responsive designs. We'll also cover breakpoints, look at examples, and understand the different types of device types that can be specified directly with the @media property.

CSS Media queries - @media - allow you to style multiple versions of a single site depending on the type of device on which the layout/site is being viewed. In other words, they are constructs that allow you to specify, based on certain conditions, which styles should be used on a web page and which should not.

The purpose of Media queries is to help developers create responsive layouts. A responsive layout means that it will adapt to the screen width of a device.

Learning to use CSS Media Queries for creating Responsive layouts for specific devices and screen sizes

All responsive layouts start at the viewport level, specifically the viewport meta tag.

This tag tells the browser that the visible layout area's width should equal the device's width.

This value is independent of the actual screen resolution; instead, it is designed to ensure that the website's responsive design is displayed equally on all devices, regardless of screen pixel density. In other words, it maps the CSS to the physical resolution of the web page.

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

Here are the key differences between Viewport and Media Queries:

  • When adjusting responsiveness through the Viewport, we can adjust the styling according to the device’s viewport. The styling with CSS remains the same; the viewport has no design changes.
  • The Media Queries, however, have a different function. They help in adjusting our styling per the limits set on the screen size. The design changes under Media Queries are custom and reflect based on the current size of the screen.

The @media syntax

Creating a Media query begins with the @media keyword followed by one or more conditions. The condition can be a device type or a requirement for a certain device-specific characteristic. The requirement for a certain characteristic is written in parentheses.

Combining multiple conditions is done using logical operators.

Once a @media query is composed, the styles specified in it will be applied only when the final result of the function returns as true.

Here's an example of a media query with a single condition:

@media screen {
  /* style will be applied to any device with a "screen" */
}

/* this lets you set a different font for @media print - for example */
@media screen { 
  * {font-family: Georgia;}
}

Here's an example of a media query with multiple conditions:

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

The above example would then only apply the style to a smaller device that fits within the parameters minimum of 570px viewport width and a maximum of 768px.

Using @media queries outside of CSS

Media queries are a CSS property; however, they're often used with both JavaScript, and, HTML documents when using <link> elements to specify stylesheets.

On the JavaScript side - media queries can be used to do things like detect browser type - as I have explained in a separate article.

HTML

When it comes to HTML - whenever you use the <link> element to reference a stylesheet, you can add an media="" attribute that supports the actual CSS media properties.

/* example */

<link href="mobile.css" rel="stylesheet" media="screen and (max-width: 600px)">

/* detect OS theme preference directly */

<link rel="stylesheet" href="css/light.css" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="css/dark.css" media="(prefers-color-scheme: dark)">
JavaScript

In JavaScript, media queries are referenced using the window.matchMedia() method.

let isMobile = window.matchMedia("only screen and (max-width: 480px)").matches;

The device types for @media queries

There are four types of devices that we can specify:

  • all - the media expression will apply to all devices. If you don't specify any type, this one will apply by default.
  • print - styles within this media expression are applied when printing to printers or exporting to PDF, including in document preview mode.
  • screen - for devices with screens.
  • speech - for speech synthesizers (not yet supported by any browser).


In most cases, when you write styles just for the screen, you do not need to specify the screen or all types. Only the print type has a real practical use.

On top of device types, there are also device characteristics. These can range from simple device-based settings to specific user settings such as "prefers a dark color scheme". Here is a full list of the currently supported @media query characteristics, categorized by type:

Page and browser window characteristics
  • width - the width of the browser window;
  • min-width - minimum width of the browser window;
  • max-width - maximum width of the browser window;
  • height - the height of the browser window;
  • min-height - minimum browser window height;
  • max-height - maximum height of the browser window;
  • aspect-ratio - the ratio between the window width and height;
  • min-aspect-ratio - the minimum ratio between the width and height of the window;
  • max-aspect-ratio - the maximum ratio between the width and height of the window;
  • orientation - orientation of the device: landscape (landscape, horizontal) or portrait (portrait, vertical);
  • overflow-block - check how the output device handles content that extends beyond the viewing area along the block axis;
  • overflow-inline - checks whether the output device can scroll content that extends beyond the viewport on the inline axis.
/* example */

@media screen and (min-aspect-ratio: 3/1) and (max-aspect-ratio: 6/1) {
...
}
Display-related
  • environment-blending - a method for determining the external environment of the device, such as dim or too bright lighting;
  • display-mode - check browser mode used in PWA: fullscreen (full-screen mode without browser interface), standalone (as a native application), minimal-ui (minimal browser interface), and browser (normal browser window);
  • grid - checks whether the screen is raster (all modern screens) or grid (like old phones or text terminals);
  • resolution - device resolution in dpi or dpcm;
  • min-resolution - minimum resolution of the device in dpi or dpcm;
  • max-resolution - maximum resolution of the device in dpi or dpcm;
  • scan - the process of scanning the output device;
  • update - screen update speed: none (not updated), slow, fast.
/* example */

@media (max-width: 576px) and (display-mode: standalone) { 
...
}
Color
  • color - the number of bits per color on the output device;
  • min-color - the minimum number of bits per color on the output device;
  • max-color - the maximum number of bits per color on the output device;
  • color-index - the number of colors the device can display;
  • min-color-index - minimum number of colors that the device can display;
  • max-color-index - the maximum number of colors that the device can display;
  • monochrome - the number of bits per color on the monochrome output device;
  • min-monochrome - the minimum number of bits per color on the monochrome output device;
  • max-monochrome - the maximum number of bits per color on the monochrome output device;
  • color-gamut - approximate range of colors supported by the browser and the output device;
  • dynamic-range - the combination of brightness level, color depth, and contrast ratio for the video in the browser or output device;
  • inverted-colors - checks whether colors are inverted by the browser or OS.
Interactions
  • hover - checks whether the main device allows you to hover over items;
  • any-hover - checks if any of the input devices allows you to point to items;
  • pointer - checks if the main input device is a pointer and how accurate it is;
  • any-pointer - checks if any of the input devices is a pointer and how accurate it is.
/* example */

@media (hover: none) and (pointer: coarse) {
/* smartphones, touchscreens */
}
Video-related
  • video-width - the width of the video on the selected display (under consideration);
  • video-height - the height of the video on the selected display (under consideration);
  • video-color-gamut - the approximate range of colors supported for video in the browser and output device;
  • video-dynamic-range - the combination of brightness level, color depth, and contrast ratio for the video in the browser or output device;
  • video-resolution - the resolution of the video on the selected display (under consideration).
User preferences (device settings)
  • forced-colors - checks if the browser prohibits colors available for use;
  • prefers-color-scheme - determines whether the user prefers a light or dark theme;
  • prefers-contrast - determines whether settings are set to increase or decrease the contrast between colors;
  • prefers-reduced-data - determines whether the user prefers to load less data on the page;
  • prefers-reduced-motion - determines whether animations are disabled in the user's system settings;
  • prefers-reduced-transparency - determines whether transparency is disabled in the user's system settings.
/* example */

/* light mode */
@media (prefers-color-scheme: light) { }

/* dark mode */
@media (prefers-color-scheme: dark) { }

The best way to learn about specific options for any of the abovementioned characteristics is through the official W3 Docs - Level 5, Level 4, and Level 3.


Logical operators

When writing media queries, you can use four different logical operators:

, (comma), and, not, only.

The only operator is a deprecated feature that was used to hide styles from older browsers that only supported CSS2 features. As such, it will not be discussed past this statement.

and

This operator is used to combine multiple conditions. In this case, their logic will be executed when each of them is true.

For example, the following @media query will only apply if all three conditions are met (its screen, width >= 1280px, and landscape orientation):

@media screen and (min-width: 1280px) and (orientation: landscape) { 
... 
}

, (comma)

This operator defines the use of styles when only one of the specified conditions must be met.

In this example, styles will be applied to the page in two cases: 

when width >= 524px or orientation is portrait.

@media (min-width: 524px), (orientation: portrait) { 
... 
}

not

The operator not is used for negation.

When using not with and negation, it works for the entire media query. In this case, when specifying not - it is not necessary to specify the device type.

For example, apply styles only when not (screen and width >= 418px and height >= 724px).

@media not screen and (min-width: 418px) and (min-height: 724px) { 
... 
}

When using not in a comma expression, it adds a negation for that part only.

For example, apply styles when the following condition is true:

not a screen or not width >= 418px.

@media not screen, not (min-width: 418px) { 
... 
}

Media Query Features (Characteristics)

This section will extend the device types section we looked at earlier. Many of the "characteristic requirements" or "media features" are very specific and, in many ways, not practical for everyday development work. Instead, this section will focus on the most popular types of Media Queries that are useful in everyday CSS work.

width

The media width characteristic allows you to condition that the viewport's width equals a certain value.

For example, apply CSS only to a viewport with a width of 316px.

@media (width: 316px) { ... }

You can use min-width and then define a range with max-width.

For example, @media for viewport widths from 586px to 1280px:

@media (min-width: 586px) and (max-width: 1279.98px) { ... }

/* In other words, this query will not work for a width past 1280px. */

For widths greater than 768px:

@media (min-width: 768px) { ... }

If you need less than 1536px:

@media (max-width: 1535.98px) { ... }

height

You can use height and  min-height to set conditions on the viewport height.

For example, @media for viewport height greater than 720px:

@media (min-height: 720px) { ... }

orientation

With the help of orientation, you can set certain styles depending on which mode (landscape or portrait) the site is displayed in.

For example, depending on the viewport orientation, you can display different pictures:

@media (orientation: landscape) {
  .featured-hero { background: url(hero-l.png) no-repeat; }
}

@media (orientation: portrait) {
  .featured-hero { background: url(hero-p.png) no-repeat; }
}

aspect-ratio

The aspect-rationmin-aspect-ratio, max-aspect-ratio characteristics allow you to set styles depending on the aspect ratio of the viewport.

/* Minimum */
@media (min-aspect-ratio: 9/16) {
  .featured-image {
    background-color: blue;
  }
}

/* Maximum  */
@media (max-aspect-ratio: 16/9) {
  .featured-image {
    background: red;
  }
}

/* Exact */
@media (aspect-ratio: 1/1) {
  .featured-image {
    background: white;
  }
}

The aspect-ratio feature has many different applications, not just for images but also cards. I recommend reading this tutorial from Peter-Paul Koch, and this one from Michelle Barker.


resolution

The resolution, min-resolution, and max-resolution characteristics can be used when you want to set styles depending on the device's pixel density.

For example, set a different font size for devices with a pixel density per inch greater than 150:

/* Default */

h2 {
  font-size: 1.5rem;
}

/* Minimum resolution */

@media (min-resolution: 150dpi) {
  h2 {
    font-size: 1.1rem;
  }
}

Media Query Breakpoints

There are now thousands of mobile phones and other various devices that can interact with CSS. And because of this, the common approach to dealing with breakpoints (device width) is to assume certain width parameters and build media queries around that.

Here are the currently most popular media query breakpoints:

BreakpointMinimum widthCSS
small640px@media (min-width: 640px) { ... }
medium768px@media (min-width: 768px) { ... }
large1024px@media (min-width: 1024px) { ... }
extra large1280px@media (min-width: 1280px) { ... }
ultra wide1536px@media (min-width: 1536px) { ... }

These can also be understood as smartphone ⤑ tablet ⤑ laptops & desktops.


Responsive Design with CSS

These days with all the modern CSS tools and features - creating a non-responsive layout is a feat in itself. Of course, certain elements (particularly on modern flashy designs) will always require Media Queries.

But I can say from experience (working with WordPress themes almost daily) that thanks to features like Grid, Flexbox, and Multicol, the need to write media queries is much less than it used to be.

There are also certain CSS math functions, such as clamp() and calc() which are fantastic for creating responsive typography.

Summary

Media queries are useful for creating responsive designs in CSS that can adapt to different device types and screen sizes.

Below are some of my personal tips for working with media queries:

  • Be mindful about which styles you change: When using media queries, you don't need to change every aspect of your design at each breakpoint. Instead, focus on the most important elements for providing a good user experience on different devices. For example, you might only change the layout of your page at specific breakpoints rather than changing the styles for every element on the page.
  • Test your design on multiple devices: It's important to test your design on various devices to ensure that it looks and works as intended. This will help you identify any issues with your media queries and ensure that your responsive design is effective on various devices.
  • Study Grid and Flexbox: As mentioned above, Grid and Flexbox are must-know CSS concepts if you wish to create a seamless and cohesive design across all devices.