A style for every media

CSS media rules are used for styling a web site differently depending on the capabilities of the device used to access it. For example different style sheets can be used for viewing and printing a web site by specifying a media type when linking to them.

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

Another example is responsive web sites that adapt to the available space. Media queries can be used to import different style sheets depending on the width of the browser window.

@import url("phone.css") (max-width: 320px);
@import url("pad.css") (min-width: 321px) and (max-width: 639px);
@import url("pc.css") (min-width: 640px);

We can also use media rules to include or exclude CSS rules inside a style sheet. But that is also the most granular we can get, media rules are not supported inside the style attribute. The following example shows how we can set the text color to black when printing to a non-color printer (though browser support for this is a bit lacking).

@media print and (monochrome) {
	body { color: Black; }
}
@media not print, print and (monochrome: 0) {
	body { color: Navy; }
}

A media query consist of a media type and zero or more conditions separated by and. The media type is optional and is assumed to be all when missing. A condition is always enclosed in parentheses. In its basic form it is made up of a name and a value. For numerical values you can use min- and max- prefixes or omit the value if you just want to check that it is non-zero.

@media projection { }
@media (min-resolution: 80dpi) { }
@media handheld and (orientation: portrait) { } 
@media screen and (width: 640px) and (height: 480px) { }
@media tv and (aspect-ratio: 16/9), tv and (aspect-ratio: 16/10) { }
@media not all and (scan: interlace) { }
@media only print and (color) { }

Note that min and max prefixes are always inclusive. Be careful that you don’t accidentally match two media rules when using ranges. The keyword not can be used to negate the whole media rule. If you need to hide a style sheet from browsers that only support media types and not media queries you can use the keyword only. The media type is not optional when using not or only.

A comma is used to separate a list of queries within a rule. The whole rule will match if at least one query matches (i.e. it is an or operator). There is no or inside a query so sometimes you have to write somewhat repetitively.

Browser support

Media types is an old CSS2 standard and is widely supported. Full media queries is from CSS3, it is not supported by Internet Explorer 8 and below. For other browsers there is at least some sort of support. Things like min-width is probably no problem but when you delve into the more odd features you should test it properly, not every browser may interpret it equally.

I have put together a page that shows which media query rules are matched on your browser. Trying it out on handheld devices can be very educational. Current smart phones will not use the media type handheld for example. This is part of the reason why the current trend is to design around the width of the screen and not the type of device.

A word of warning if you are trying to minimize download size of your site. Even if a browser won’t use style sheet that is linked to with a media query it may still download it.

A demonstration of combination

CSS selector combinators are used when you need to refer to elements via their relationship to other elements. Possible relationships are descendants, children and siblings.

I have created a demonstration page where you can see the combinator syntax as well as what they do. There are a couple more relevant pseudo-classes that I didn’t include.

If you need to support older versions of Internet Explorer you have to be careful. IE 6.0 or older does not support CSS 2.1 selectors while IE 8.0 or older does not support CSS3 selectors.

Web safe all the fonts

In CSS 3 you can use your own fonts instead of having to rely on whatever the user happens to have installed. With @font-face you can define a new font and tell the browser where to download it from.

@font-face {
  font-family: "My own font";
  src: url(fonts/myownfont.woff);
}

The best format to use for your fonts is WOFF (Web Open Font Format). You can easily convert common TrueType or OpenType fonts to WOFF. Make sure that you have the proper license for the fonts you use.

The new font can then be used exactly like any other font in your style sheets. As usual we give alternative fonts that the browser can fall back on if it fails to download our font.

body {
  font-family: "My own font", Arial, Sans-Serif;
}

The browser will also use the alternative fonts if it does not support the new technologies. Support exist in all current browsers. There are services on the web that can give you support for older browsers as well as take care of the licensing for you.

I have created an example page where I use a font of my own creation to hide spoilers.

CSS sprite button

When you have a lot of small images on a web page you can combine them into one image and then use CSS to cut out the individual parts. This practice is called CSS sprites and can make your web page load faster.

I’m going to use this technique here to implement an image button with hover and clicked states. It will also degrade gracefully and does not use any JavaScript. We start with the following beauty I created in Paint:

The dimensions of this image are 150 times 150 pixels. Each box is 50 pixels high.

<a id="button" title="Explanation" href="#">Fallback text</a>

We use an ordinary link as the basis for our button. This is what users who have CSS turned off will see. It should also work well with screen readers. The title attribute sets a text that is shown when the user hovers over the button. In practice it would probably be the same as the link text.

#button
{
    text-indent: -5000px;
    display: block;
    width: 150px;
    height: 50px;
    background-image: url("CssSpriteButton.png");
    background-position: 0 0;
}
#button:hover
{
    background-position: 0 -50px;
}
#button:active
{
    background-position: 0 -100px;
}

In the CSS we have to set a height and width of the button. When we then set our image as the background only the first box will be shown. In the hover and active states we set the background position to a negative vertical value. This means we will show the second and third box respectively. The result is a working button.

The text indent is there to move the text out of the way. Otherwise the text would be put on top of the image. There are several other techniques to hide the text. Some of which can handle the situation where the user has CSS enabled but images disabled. Personally I don’t think it is worth the effort.

CSS sprites and background images can be used in many other ways. For example, you can make nice image maps with it.

Flickering

If you read older articles about CSS sprites, for example the one linked above, you will come across concerns about flickering. The proposed solution for this is to put the background image for the normal state in a parent tag and let the background image for the hover state cover it.

However, as far as what I’ve read this problem only exists in Internet Explorer 6 and possibly only when the cache has been turned off. Personally I would not worry about it. Even if this happens it is still perfectly usable, it just looks a bit bad.