A grid of small wooden drawers

At-media queries are conditions in your stylesheet. The style rules they contain are applied only if certain criteria are met, such as device width, resolution, or browser window dimensions.

Media queries can be written inside a stylesheet, or may be the conditions for using the CSS in an external stylesheet. We‘ll start by exploring the first, and most common, application.

@media rules

Most stylesheets begin with fundamental declarations that are true in all conditions:

@charset utf-8
@font-face {
	font-family: 'Mallory';
	src: url('Mallory-Light.woff2') format('woff2');
	font-style: normal;
	font-weight: 300;
}
* { 
    box-sizing: border-box;
}
body {
	font-family: Mallory, Gill Sans, sans-serif;
    background: hsl(240, 67%, 94%);
    color: black;
}

Working from this stylesheet, let‘s say we wanted to improve text contrast at smaller window sizes. We could add an @media rule to cover this condition by adding the following:

@media all and (max-width: 600px) {
    body {
        background: #000;
        color: #fff;
    }
}

If you test the resulting page, you‘ll see the background and text color change when the browser window narrows to 600px wide or less.

There are a few important things to note at this stage:

  1. @media rules work in addition to other aspects of responsive design, including fluid images.
  2. The declarations inside the @media rule contain only the things that are altered if the conditions are met. Do not attempt to rewrite the entire stylesheet inside an @media rule. Only the things that change are added; the base rules that are not affected by the new declarations will still apply under the new conditions.
  3. The @media rule uses curly braces to contain the declarations. You can have as many declarations inside the @media rule as you like. You can also have as many @media rules as you wish, although obviously the more you add, the more complex your CSS becomes.
  4. In general practice you should usually write your base CSS first in your stylesheet, i.e. the styles that will remain the same under all (or most) conditions, adding the @media rules at the end.

Due to the slightly more complex syntax of @media queries, it makes sense to test that they work first with something dramatic like a background color change, especially when you are just beginning to learn and apply them.

Syntax

The first part of the @media rule above – the all – states what kind of media the rule is applied to. all means exactly that: the declarations will be valid for every form of media, provided the condition (and (max-width: 600px)) is met.

Associating conditions with an @media rule is optional. How a web page will be printed out is often specified in a rule like this, without any further conditions:

@media print {
    /* rules for a print stylesheet here */
}

Other options for @media include screen (intended for color screens) and speech for speech synthesisers).

min-width and max-width

The two most common conditions associated with all or screen are and (min-width: x) and and (max-width: x). Both measure the browser viewport width, and are usually the most straightforward way of determining it‘s size.

It‘s easy to get min-width and max-width confused; thankfully, there‘s also an easy way to remember which is which.

  • min-width means “the browser window must be at least this width or greater
  • max-width means “the browser can be up to this width or smaller

You‘ll typically use one or the other in your stylesheet; it‘s rare (and usually confusing) to use both. Which one you use comes down to your design approach:

  • if you are using a mobile-first approach, then you are writing your base CSS for the smallest browser width, and adding adjustments to it as the browser widens with @media all and (min-width: x) { }.
  • if you take a desktop-first approach, then you are writing your CSS for what appears on your monitor and adjusting it as the browser narrows using @media all and (max-width: x) { }.

Units

Technically, the measurement defined for min-width and max-width can use almost any CSS length unit, with the exception of vw, vh, vmin or vmax. Using pixels is common, but comes with some caveats:

  • Pixels are not what you think they are in CSS. For example, the resolution for the product specs of the iPhone are not a direct part of the calculations for min-width and max-width.
  • It‘s best to ignore device sizes. People tend to become obsessed with the exact pixel dimensions of the browser in the iPhone XIII, or whatever their mobile device is. That is a fool‘s errand: you‘ll constantly be chasing new mobile releases to update your stylesheet, and inevitably ignore other devices. Instead, write @media rules as interventions where the design of your site needs them. By making the browser window wider or narrower, you can find where your particular design “breaks”, and intervene at that point, an approach that will work for every device.

combinators

You‘ve already seen one combinator in an @media query: and. It‘s also possible to use not and only and a comma delimiter:

@media only screen {
    …
}

Or:

@media screen, print {
    …
}

You can use and and or as many times as you wish to chain together conditions:

@media screen and (max-width: 600px) 
    and (min-resolution: 200dpi) {
        …
}

There are many conditions that can be added in an @media query, but it is always recommended to start with the basics first.

Variations

As mentioned at the start of this article, it‘s also possible to write media queries inside link elements:

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

Contrary to expectations, media conditions do not prevent the browser from loading the stylesheet. The browser loads the file regardless, but it does not use the CSS in the stylesheet unless it matches the associated conditions.

Conditions, Limitations and Conclusions

As powerful as they are, @media queries do have a few limitations that you should be aware of:

  1. Currently @media inspects conditions in the browser viewport and device, not the state of individual elements. So-called “element queries” are planned for CSS; right now, a JavaScript polyfill is recommended to create the functionality.
  2. @media queries can‘t use CSS variables in their conditions, nor can they be nested inside elements. If you want those kinds of features, use Sass or another CSS pre-processor.

Photograph by Jeremy Keith used under a Creative Commons Attribution 2.0 Generic license

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.