Skip to content

CSS Media Queries and Responsive Design

New Courses Coming Soon

Join the waiting lists

How to work with media queries in CSS to build responsive web pages

In this post I’m going to first introduce media types and media feature descriptors, then I’ll explain media queries.

Media types

Used in media queries and @import declarations, media types allow us to determine on which media a CSS file, or a piece of CSS, is loaded.

We have the following media types

screen is the default.

In the past we had more of them, but most are deprecated as they proven to not be an effective way of determining device needs.

We can use them in @import statements like this:

@import url(myfile.css) screen;
@import url(myfile-print.css) print;

We can load a CSS file on multiple media types separating each with a comma:

@import url(myfile.css) screen, print;

The same works for the link tag in HTML:

<link rel="stylesheet" type="text/css" href="myfile.css" media="screen" />
<link rel="stylesheet" type="text/css" href="another.css" media="screen, print" />

We’re not limited to just using media types in the media attribute and in the @import declaration. There’s more

Media feature descriptors

First, let’s introduce media feature descriptors. They are additional keywords that we can add to the media attribute of link or to the @import declaration, to express more conditionals over the loading of the CSS.

Here’s the list of them:

Each of them have a corresponding min-* and max-*, for example:

and so on.

Some of those accept a length value which can be expressed in px or rem or any length value. It’s the case of width, height, device-width, device-height.

For example:

@import url(myfile.css) screen and (max-width: 800px);

Notice that we wrap each block using media feature descriptors in parentheses.

Some accept a fixed value. orientation, used to detect the device orientation, accepts portrait or landscape.


<link rel="stylesheet" type="text/css" href="myfile.css" media="screen and (orientation: portrait)" />

scan, used to determine the type of screen, accepts progressive (for modern displays) or interlace (for older CRT devices)

Some others want an integer.

Like color which inspects the number of bits per color component used by the device. Very low-level, but you just need to know it’s there for your usage (like grid, color-index, monochrome).

aspect-ratio and device-aspect-ratio accept a ratio value representing the width to height viewport ratio, which is expressed as a fraction.


@import url(myfile.css) screen and (aspect-ratio: 4/3);

resolution represents the pixel density of the device, expressed in a resolution data type like dpi.


@import url(myfile.css) screen and (min-resolution: 100dpi);

Logic operators

We can combine rules using and:

<link rel="stylesheet" type="text/css" href="myfile.css" media="screen and (max-width: 800px)" />

We can perform an “or” type of logic operation using commas, which combines multiple media queries:

@import url(myfile.css) screen, print;

We can use not to negate a media query:

@import url(myfile.css) not screen;

Important: not can only be used to negate an entire media query, so it must be placed at the beginning of it (or after a comma)

Media queries

All those above rules we saw applied to @import or to the link HTML tag can be applied inside the CSS, too.

You need to wrap them in a @media () {} structure.


@media screen and (max-width: 800px) {
  /* enter some CSS */

and this is the foundation for responsive design.

Media queries can be quite complex. This example applies the CSS only if it’s a screen device, the width is between 600 and 800 pixels, and the orientation is landscape:

@media screen and (max-width: 800px) and (min-width: 600px) and (orientation: landscape) {
  /* enter some CSS */
→ Get my CSS Handbook
→ Read my CSS Tutorial on The Valley of Code

Here is how can I help you: