RELATED: "HTML5 and CSS3 Feature Detection with Modernizr" and "HTML5 Is in Style: Working with CSS3 and HTML5"

The latest statistics on Internet consumption show that close to 9 percent of all web traffic now comes from mobile devices. That percentage is a significant increase over previous years and is certain to increase even more as consumers continue to purchase more and more devices. As a result of this massive shift to mobile, web application development is quickly switching from "Make it work cross-browser!" to "Get it to work in any browser on any device!" That's a big challenge for developers to tackle, especially if they don't have any background in mobile development. 

If you've been browsing websites from a mobile device, you've probably noticed that many sites aren't optimized for smaller screen sizes. The vast majority of websites target desktop browsers only and fail to take into account mobile-device screen sizes. By creating more responsive and flexible application layouts, it's possible to have one code base that looks good in a variety of scenarios, including desktops, laptops, tablets, and smartphones. In this article, I'll explain how responsive web applications can be built using Cascading Style Sheets (CSS) media types combined with CSS media queries.

CSS Media Types

If you've ever printed a page and noticed that it looks different from the actual page displayed in the browser, you've more than likely witnessed a CSS media type in action. Browsers have provided support for applying different CSS styles while printing for quite some time, and many sites take advantage of this support. Using CSS media types such as print allows backgrounds, navigation bars, and other items to be hidden as a user prints a web page, which makes the printed page much easier to read.

Figure 1 shows an example of using a CSS media type to change styles as a page is printed from the browser.

  1. @media print
  2. {
  4.     body {
  5.         background-color: white;
  6.     }
  8.     nav {
  9.         display: none;
  10.     }
  12. }

This type of code can be placed directly in a <style> element in a given page or in an external style sheet. Figure 2 shows the different media types that can be used to target various scenarios.

Media Type

When is it Used?

Figure 2: CSS media types
3d-glasses 3D scenarios
all All Media Types
braille Braille Tacitile Devices
embossed Paged Braille Printers
handheld Handheld devices
print Printed materials
projection Projected presentations
speech Speech synthesizers
tty Teletypes and terminals
tv Television devices

You can define media types in a web page using any of several different techniques. When a media type is identified (such as when a print operation occurs in the browser), the style sheet associated with the media type is applied dynamically by the browser.

One of the easiest ways to get started using media types is to add the media attribute of the <link> element, as follows:

  1. <link type="text/css" media="print" href="Styles/print.css" />

This code will cause the style sheet to be applied only when the specific media type (print, in this case) is identified by the browser. You can also combine the media attribute with an @import rule in an HTML page to cause a style sheet to be applied, as in the following example. (Note that the @import rule is ignored in older browsers.)

  1. <style type="text/css" media="print">
  2.     @import "Style/print.css";
  3. </style>

If you'd prefer to load a specific style sheet from within another style sheet, to do so you can use @import along with the media type. For example, if you have a style sheet named styles.css and want to include print styles in it, you can add the following statement in the file to define the print style sheet along with the media type that it applies to:

  1. @import url('print.css') print;

Finally, @media can be used directly in a style sheet, as shown earlier in Figure 1, to identify a specific media type section:

  1. @media print
  2. {
  3.     /* custom print styles go here */
  4. }

Although media types definitely fill a direct need, unfortunately, they can't be used to perform runtime logic. That's where CSS media queries come into play.

CSS Media Queries

By combining CSS media types with CSS media queries, you can dynamically change styles and provide a responsive layout that adapts based on a variety of conditions. Although media types target a specific type of media, such as print, you can add more control into your pages and even adjust the overall layout by adding CSS media query expressions. Expressions provide a way to associate logic with a given media type. You can use media query expressions to target properties such as screen height and width, aspect ratio, color, orientation (e.g., portrait versus landscape), and more. You can find a complete list of the different expressions in the W3C Media Queries document.

Note that media queries aren't the same as page optimization. Although CSS media queries can be used to dynamically change the layout of a page, they don't optimize a page for smaller devices. Page optimization normally involves the server transmitting smaller images, minimizing the HTML payload that's sent, and performing other types of optimization tasks. Although CSS media queries can be used to load different types of images, they don't have any effect on the overall HTML that's loaded.

Now let's take a look at how media types and media expressions can be used together to create a CSS media query. Figure 3 shows an example of some HTML that will be rendered.

  1. <body>
  2.     <div id="wrapper">
  3.         <article class="clearfix">
  4.             <section>
  5.                 This is section 1
  6.             </section>
  7.             <section>
  8.                 This is section 2
  9.             </section>
  10.             <section>
  11.                 This is section 3
  12.             </section>
  13.         </article>
  14.     </div>
  15. </body>

Figure 4 contains the CSS that's applied for styling purposes.

  1. #wrapper
  2. {
  3.     width: 980px;
  4.     margin: 0 auto;
  5. }
  7. section
  8. {
  9.     border: 1px solid black;
  10.     height: 50px;
  11.     width: 31%;
  12.     margin: 0px 0px 10px 5px;
  13.     padding: 5px;
  14.     font-weight: bold;
  15.     background-color: green;
  16.     color: white;
  17.     float: left;
  18. }
  20. .clearfix:before, .clearfix:after { content: ""; display: table; }
  21. .clearfix:after { clear: both; }
  22. .clearfix { *zoom: 1; }

When the HTML and CSS are rendered, the output shown in Figure 5 is displayed in the browser.

Figure 5: Browser output in a "normal" desktop mode

What happens when the page in Figure 5 is rendered on a phone with a small screen? Although most modern smartphones will display the page fine, the user will likely have to zoom in to read the content and swipe left or right to view specific areas. The experience can be made much better by using CSS media types combined with media queries.

To get started using CSS media queries, let's look at how to target devices that have a maximum width of 480 pixels and reformat the green boxes shown in Figure 5 so that they display vertically instead of horizontally. When we add code to stack the boxes vertically and adjust their widths, the user won't have to zoom in and swipe from left to right to see all the content.

Here's an example of defining a media type of screen along with a max-width media query expression:

  1. @media screen and (max-width:480px) {
  2.     /* custom styles go here */
  3. }

This code targets any screen that has a maximum width of 480 pixels using the (max-width:480px) expression and triggers the styles defined in the media query's brackets to be applied. Figure 6 shows a more complete example of checking for a specific max-width and then applying custom styles to the page when the expression returns true.

  1. @media screen and (max-width:480px)
  2. {
  3.     #wrapper
  4.     {
  5.         width: 98%;
  6.         margin: 0 auto;
  7.     }
  9.     section
  10.     {
  11.         width: 98%;
  12.         margin: 0px 0px 10px 0px;
  13.         background-color: red;
  14.         color: white;
  15.         float: none;
  16.     }
  17. }

When the expression is true, the custom #wrapper and section element styles are applied dynamically, causing the floats to be removed. Figure 7 shows the result of our media query code.

Figure 7: Using a CSS media query to target smaller screen sizes

To target widths between 481 and 979, you can use the CSS in Figure 8.

  1. @media screen and (min-width: 481px) and (max-width:979px) {
  2.     #wrapper
  3.     {
  4.         width: 98%;
  5.         margin: 0 auto;
  6.     }  
  8.     section
  9.     {
  10.         width: 98%;
  11.         margin: 0px 0px 10px 0px;
  12.         background-color: #ccc;
  13.         color: black;
  14.         float: none;
  15.     }
  16. }

In this code, you'll see that two expressions are used. Each expression is wrapped in parenthesis and separated with the "and" keyword. Although the code only changes each section's background and text color, you could certainly make additional modifications to the styles. Figure 9 shows the screen that's rendered in the browser.

Figure 9: Targeting widths between 481 and 979 pixels

You could include additional media queries to target smaller devices such as iPhone and Android phones. For example, to target a max-width of 320 pixels, you could use the CSS shown in Figure 10.

  1. @media screen and (max-width: 320px)
  2. {
  3.     #wrapper
  4.     {
  5.         width: 98%;
  6.     }
  8.     section
  9.     {
  10.         width: 98%;
  11.         margin: 0px 0px 10px 0px;
  12.         background-color: #000;
  13.         color: white;
  14.         float: none;
  15.     }
  16. }

Testing CSS Media Queries

Although CSS media queries are fairly straightforward to add to your code, how can you test that they're actually working? You can certainly resize the browser window yourself to do some basic testing. However, if you want to know exact sizes, it's better to take advantage of tools designed for that task.

Chrome has a great extension named Window Resizer that allows specific resolutions to be targeted easily. After you install the extension, an icon shows in the Chrome browser that you can select to pick a target, as shown in Figure 11. You can easily add custom resolutions, if you need them.

Figure 11: Using the Chrome Window Resizer extension

You can also use device emulators if you have them installed or perform testing on real devices, which is, of course, highly recommended if you have them. If you don't want to install an emulator, a nice (and reasonably priced) tool that can be used to test iOS devices on Windows is the Electric Mobile Simulator from Electric Plum (a free "Lite" version is also available). This tool provides a way to test what web pages look like on iPhone and iPad devices, as shown in Figure 12.

Figure 12: Using Electric Plum's Electric Mobile Simulator to test an iOS app

More to Come

In this article, you've seen the role that CSS media types and CSS media queries play in providing more responsive web pages. In "Working with CSS Media Queries and Media Types, Part 2," I'll demonstrate how a more robust site can benefit from CSS media queries to render pages that look good on a variety of devices. You can see a preview of the sample site in Figure 13; the downloadable code for this article includes the HTML and CSS used to create the site.

Figure 13: A site that uses CSS media queries to provide a responsive layout for smaller devices