CSS Media Queries

Introduction

Reference: Mozilla developer page

CSS Media Queries allow us to define different stylesheets, or stylesheet rules, depending on the properties of the device. In this way, we can develop sites which have a usable layout on both a desktop browser and a mobile browser. Media queries test different properties of the current device (such as the width or aspect ratio), and depending on whether the properties are true or false, can apply different CSS rules. Thus we can design different layouts for desktop and mobile devices.

Here is an example of using media queries to load a different stylesheet based on the width of the device:

<link rel="stylesheet" media="only screen and (max-width: 599px)" type="text/css" href="mobile.css" />
<link rel="stylesheet" media="only screen and (min-width: 600px)" type="text/css" href="desktop.css" />
Note the media query, specified in the media property of the link tag. This code is telling the browser to include the stylesheet mobile.css if it is a screen-based device (as opposed to a printer, for instance) and the width of the screen is 599 pixels or less, or to include the stylesheet desktop.css if it is a screen-based device and the width of the screen is 600 pixels or more. So for a typical smartphone the first stylesheet will be linked in, and for a typical desktop browser the second stylesheet will be included.

When we say width, we mean the width of the browser viewport, i.e. the currently visible area of the browser window in which the page content is displayed. We do not mean the width of the device itself. This has the advantage that the "mobile" layout will apply if we resize the window of a regular desktop browser below 600 pixels - which is probably what we want.

Different media types

As well as screen, there are other media types such as aural, braille or print, for different types of devices. These three are for screen readers (which speak the contents of a web page), braille-based browsers, and printers, respectively.

Other CSS Media Query directives

Besides max-width and min-width, a range of other useful CSS media query rules exist. They include:

Combining conditions

You can combine conditions with the use of and and not operators, for example, this will only link in the stylesheet if the width of the viewport is at least 800 pixels and there are at least 24 bits of colour:

<link rel="stylesheet" type="text/css" media="only screen and (min-width: 800px) and (min-color: 24)"
 href="desktop.css" />
 
or this will link in the stylesheet if the viewport is not at least 800 pixels (i.e. less than 800 pixels) but the colour depth is at least 24:
<link rel="stylesheet" type="text/css" media="only screen and (not min-width: 800px) and (min-color: 24)"
 href="mobile.css" />
 

There is not an "or" operator but you can separate criteria with a comma and the stylesheet will be applied if any of the media are met, e.g:

<link rel="stylesheet" type="text/css" media="only screen and (min-width: 800px), 
only screen and (min-color:24)" href="style.css" />
 
would apply the stylesheet if either the width is at least 800 pixels or the colour is at least 24-bit.

Media Queries and individual CSS rules

The examples so far have shown how to link in whole stylesheets depending on the properties of the device. However in certain cases we might just want to incorporate certain rules (selectors) within the CSS depending on the device properties, for example the dimensions of a specific div. Here is how to do this in a CSS stylesheet:

 @media only screen and (min-width: 800px)
 {
    #div1 
    {
        width: 800px;
        height: 600px;
    }
    
    #div2 
    {
        width: 800px;
        height: 400px;
    }
}

@media only screen and (max-width: 480px) 
{
    #div1
    {
        width: 320px;
        height: 200px;
    }
    
    #div2 
    {
        width: 320px;
        height:200px;
    }
}
 
The first pair of rules will be applied if the width is at least 800 pixels, and the second, if the width is no more than 480 pixels. Note how we specify the media rule and then use curly brackets { and } to define the block of CSS which applies to this media rule. Within this outer block we list one or more CSS selectors (rules) which will be applied if the media rule holds true.

The problem with high resolution mobile devices

Please note, the following two references provide much additional information about this topic:

CSS media queries as above are fine for "classic" mobile devices with low resolution, but we come across a problem when trying to develop for modern, high resolution devices. This problem relates to the concept of the viewport. You might think "viewport" means the same as "screen" but in fact, this is not the case.

As Koch discusses in his article, there are actually two viewports. The first is the screen (also known as the 'device viewport' (Koch)) and the sceond is the 'layout viewport' (Koch). The layout viewport is the actual area on whch the page is rendered, and does not necessarily equal the screen size. For a mobile device the width of the layout viewport depends on the browser: "How wide is the layout viewport? That differs per browser. Safari iPhone uses 980px, Opera 850px, Android WebKit 800px, and IE 974px." (Koch). This may well exceed the width of the actual device viewport (screen), which means that parts of the page would, if nothing else was done, go off-screen, severely impacting usability.

Mobile browsers typically deal with this automatically deal with this by shrinking (zooming out) the page so that the layout viewport matches the device viewport. While at least we can see the page on-screen without parts of it disappearing off the right-hand side, this results in another problem - the page is too small on a mobile device, and thus is unreadable and has very poor usability. Furthermore, media queries use the layout viewport, not the device viewport, so, for example, on an Android device with a screen width of less than 800px, media queries designed for less-than-800px widths will not apply as the layout viewport is still 800.

So how can we deal with this? What we can do is set the layout viewport to have the same width as the device viewport and then use media queries to design an appropriate mobile layout.

To do the first, we can add this meta tag to our page (in the <head> section):

<meta name="viewport" content="width=device-width, initial-scale=1" />
This line is setting the size of the layout viewport and it's fixing its width to be device-width, which is the actual width of the device (screen) in CSS pixels (see below).

CSS pixels

An understanding of CSS pixels helps understanding of what is going on here. What are CSS pixels? These are 'virtual pixels' which are used by CSS rules. But what is one CSS pixel equivalent to? Normally 1 CSS pixel is equivalent to 1 "actual" pixel but this changes on performing zoom operations. So when you zoom in a page (for example, using Ctrl/+ on a desktop), CSS pixels grow larger to occupy more space than one real pixel. However if you zoom out (Ctrl.-), CSS pixels become smaller and one CSS pixel will occupy less space than one real pixel.

To give some actual examples, a page element scaled to 800 CSS pixels will occupy 800 'real' pixels at default zoom. However, if we zoom IN by a factor of 1.5, the element will occupy more screen space - 1200 'real' pixels. Its width in *CSS* pixels, though, will remain 800 so nothing will change in terms of which media query rules are matched. So in this example one CSS pixel will occupy 1.5 real pixels.

However, if we zoom OUT by a factor of 2, the page will occupy LESS screen space. So its width in 'real' pixels will now be 400 but it will still be 800 CSS pixels so nothing changes in terms of which media query rules are matched. So in this example one CSS pixel will occupy 0.5 real pixels.

The width: device-width, initial-scale : 1 in the directive above:

<meta name="viewport" content="width=device-width, initial-scale=1" />
forces the width of the page (in CSS pixels) to be the same as the width of the device in CSS pixels with no zoom applied (i.e. the width of the device in 'real' pixels). So here, the page will use, not 800 CSS pixels of width, but 640, by default (as that is the width of the page) - and media queries designed for devices with a width of less than 800 CSS pixels will kick in.

Exercises

  1. Develop your web mapping example to use a sidebar/main content area layout. The sidebar should contain links to OpenStreetMap (www.openstreetmap.org), OpenCycleMap (www.opencyclemap.org) and Freemap (www.free-map.org.uk). Use: sidebar width 20%, main content width 80%,e.g:
    #sidebar
    {
        position:absolute;
        top:0%;
        left:0%;
        width:20%;
        height:100%
    }
    
    #main
    {
        position:absolute;
        top:0%;
        left:20%;
        width:80%;
        height:100%
    }
    
  2. Use CSS media queries so that a different layout is produced when the screen width is 480 pixels or less. This alternative layout should have a map of width 480 pixels, height 200 pixels and should show the copyright message and the three links immediately above the map, so that everything is in one column, not two. The width of the sidebar (now top bar) should be 100%. This "narrower" layout is more mobile-friendly. Do not use position: absolute or set the top or left properties. Just let the elements flow in natural order.
  3. Change your answer so that the first layout appears if the aspect ratio is greater than 2/3, and the second layout if the aspect ratio is less than 2/3.
  4. Ensure the viewport is set so that the site looks friendly on a high-resolution mobile device.