Media-Specific CSS Tutorial
Overview
- Introduction to Media-Specific CSS
@mediaApproach to Implementing Media-Specific Styles- media Attribute Approach to Implementing Media-Specific Styles
@importApproach to Implementing Media-Specific Styles<link />Approach to Implementing Media-Specific Styles- Recommendations for Print Stylesheets
- Tutorial Details
Introduction to Media-Specific CSS
- The following media types are available:
all(the default; styles are applied to all devices and outputs)aural(for screen readers and browsers with voice capability)braille(for output to a Braille tactile feedback device)embossed(for paged Braille printers)handheld(for mobile devices such as cell phones and PDAs)print(for print output)projection(for full-screen presentation slides or kiosks)screen(for desktop browsers; the iPhone also uses this media type)speech(added in CSS2.1 as a replacement for the aural media type, which was deprecated)tty(for devices with a fixed-pitch character grid, such as a terminal screen)tv(for televisions or similar devices)
Current Browser and Device Support for Media Types
- Web developers typically focus on
screenandprint. - IE 6-8, Gecko-based browsers (e.g., Firefox), Safari, Chrome, and Opera do a good job of handling those two media types.
- The
projectionmedia type is used by Opera in full-screen mode and treats the web page as a series of slides; there is no scrolling occurring. auralsupport depends entirely on the screen reader or the browser with voice capability; it has nothing to do with the visual presentation of the page.- You will recognize the
voice-familyproperty from the Tantek hack; that is anauralproperty. - Various other
auralproperties exist, such asvolume,speech-rate, andpause-before. - More details about aural properties are available.
- You will recognize the
- Replacing
auralin the CSS2.1 specification isspeech, which then became its own Speech module in CSS3.- Opera supports this Speech module.
- More details and an example are available for the speech media type.
- No desktop browsers support
braille,embossed, orttyso any support would have to come from another device being used along with the browser.
Media Types and Legacy Browsers
- Since legacy browsers (e.g., Netscape 4.x) only support
screen, you can hide all CSS from them by adding a non-supported media type such as:screen, projectionor simplyall - Blocking styles in this fashion is a recommended practice.
@media Approach to Implementing Media-Specific Styles
- This approach uses
@mediato define the type of media and then the styles to apply in that setting. @mediais followed by a media type or types (multiple values are separated by commas), then a set of brackets which contain the rules that are applied for that media type.- Rules outside of
@mediaapply in every environment (defaulting toallas their media type). @mediacan be used in embedded CSS or in external CSS and it is the latter implementation that is preferred (for ease of explaining these concepts embedded is used here, but for actual websites use this in an external approach to reduce the stylesheets down to one file).
@media Example 1:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Usable Development: @media Example 1</title>
<style type="text/css"><!--
@media screen {
body {font: 75%/1.4 verdana,geneva,lucida,arial,sans-serif;
background: #fff; color: #000;}
h1 {font-size: 160%; color: green; font-style: italic;}
}
h2 {font-size: 140%; color: purple;}
@media print {
body {font: 12pt georgia,serif;}
h1 {font-size: 18pt;}
h2 {font-size: 15pt; color: #000;}
}
--></style>
</head>
<body>
<h1>Media-Specific CSS</h1>
<h2>Example 1</h2>
<p>Sample text</p>
</body>
</html>
See how the first @media example renders
@media Example 1 Considerations:
- The screen styles and the
'h2'are used for on-screen display. - The print styles and the
'h2'are used when printing. - To avoid using up paper and ink / toner testing this, use each browser's Print Preview to see the changes. This works for every browser except Chrome (which does not appear to have a print preview). Even IE Tester has a print preview in its Options tab.
- Note that the print-specific instructions for
'h2'override everything that was set for the'h2'outside of@media, to ensure proper appearance on the printed page. They are located last for priority in the cascade.
@media Example 2:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Usable Development: @media Example 2</title>
<style type="text/css"><!--
body {font: 75%/1.4 verdana,geneva,lucida,arial,sans-serif;
background: #fff; color: #000;}
h1 {font-size: 160%; color: green; font-style: italic;}
h2 {font-size: 140%; color: purple;}
@media print {
body {font: 12pt georgia,serif;}
h1 {font-size: 18pt; color: #000; font-style: normal;}
h2 {font-size: 15pt; color: #000;}
}
--></style>
</head>
<body>
<h1>Media-Specific CSS</h1>
<h2>Example 2</h2>
<p>Sample text</p>
</body>
</html>
See how the second @media example renders
@media Example 2 Considerations:
- Browsers render the same as in
@mediaExample 1, but note that in this approach more code is needed in the@mediaprint styles. - More code is needed because the styles outside of
@mediaapply to all media types (including print), so those values had to be specifically overridden by print-specific values. To assure priority in the cascade the print-specific styles appear last.
media Attribute Approach to Implementing Media-Specific Styles
- Another approach that works well with embedded CSS uses media as an attribute for
<style></style> - To indicate more than one type of media separate them with a comma, such as:
media="print, handheld"
- IE 6-8, Gecko-based browsers (e.g., Firefox), Safari, Chrome, and Opera are supportive.
media Attribute Example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Usable Development: media Attribute Example</title>
<style type="text/css" media="screen"><!--
body {font: 75%/1.4 verdana,geneva,lucida,arial,sans-serif;
background: #fff; color: #000;}
h1 {font-size: 160%; color: green; font-style: italic;}
h2 {font-size: 140%; color: purple;}
--></style>
<style type="text/css" media="print"><!--
body {font: 12pt georgia,serif;}
h1 {font-size: 18pt;}
h2 {font-size: 15pt;}
--></style>
</head>
<body>
<h1>Media-Specific CSS</h1>
<h2>Example 3</h2>
<p>Sample text</p>
</body>
</html>
See how the media attribute example renders
Considerations with the media Attribute Example:
- Screen-specific and print-specific styles are completely separate, so there is no concern with overlap leading to undesired results.
@import Approach to Implementing Media-Specific Styles
- Add the specific media type(s) after the
@importURL and before the closing semicolon. - To indicate more than one type of media separate them with a comma, such as:
@import url(somefile.css) print, handheld;
@import Example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Usable Development: @import Example</title>
<style type="text/css"><!--
@import url(screen.css) screen;
@import url(printed.css) print;
h2 {font-size: 140%; color: purple;}
--></style>
</head>
<body>
<h1>Media-Specific CSS</h1>
<h2>Example 4</h2>
<p>Sample text</p>
</body>
</html>
The screen.css file contains:
body {font: 75%/1.4 verdana,geneva,lucida,arial,sans-serif;
background: #fff; color: #000;}
h1 {font-size: 160%; color: green; font-style: italic;}
The printed.css file contains:
body {font: 12pt georgia,serif;}
h1 {font-size: 18pt;}
body h2 {font-size: 15pt; color: #000;}
See how the @import example renders
@import Example Considerations:
- IE 6 and IE 7 apply only the
'h2'instructions outside of@import. Everything else uses browser default styling. Any indication of media type in this manner (evenscreen) causes IE 6 and IE 7 to ignore the stylesheet file. This is one way to hide style information from those browsers. - IE 8 added support for
@importmedia types, but it is using thescreenstyles for screen as well as print. The print stylesheet appears to be ignored. - Gecko-based browsers (e.g., Firefox), Safari, Chrome, and Opera combine screen.css and the
'h2'outside of@importfor on-screen display and combine printed.css and the'h2'when printing. @importmust always precede other embedded styles if it is to work correctly, so to override the'h2'following@importthe'h2'inside the print-specific file had to become slightly more specific, accomplished through'body h2'. Now the print-specific version displays properly.
<link /> Approach to Implementing Media-Specific Styles
- Specify the media attribute inside
<link />such as:media="print"
- To indicate more than one type of media separate them with a comma, such as:
media="print, handheld"
<link /> Example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Usable Development: <link /> Example</title> <link rel="stylesheet" type="text/css" href="screen2.css" media="screen,projection" /> <link rel="stylesheet" type="text/css" href="printed2.css" media="print" /> </head> <body> <h1>Media-Specific CSS</h1> <h2>Example 5</h2> <p>Sample text</p> </body> </html>
The screen2.css file contains:
body {font: 75%/1.4 verdana,geneva,lucida,arial,sans-serif;
background: #fff; color: #000;}
h1 {font-size: 160%; color: green; font-style: italic;}
h2 {font-size: 140%; color: purple;}
The printed2.css file contains:
body {font: 12pt georgia,serif;}
h1 {font-size: 18pt;}
h2 {font-size: 15pt;}
See how the <link /> example renders
<link /> Example Considerations:
- The one drawback of this approach is that we are increasing the number of file downloads, which slows down the loading process.
- By specifying the
projectionmedia type we also block some legacy browsers (e.g, Netscape 4.x) from receiving any styles, which is generally what we want to have happen (and Opera will render the page based on that stylesheet in full-screen mode).
Recommendations for Print Stylesheets
Switch fonts from sans-serif to serif
- Serif fonts are slightly easier to read than sans-serif fonts on the printed page.
Make sure that text colors and border colors are black
- There is no need to switch printers into color mode because one heading is a color other than black.
Specifying
display: noneis useful for removing tags and their content from the print output- All child and descendant elements are also removed from display.
- Use
img {display: none;}to remove images in the printed version. - Just keep in mind that elements and content instructed to
display: noneare ignored by some screen readers, but hopefully the screen reader is not using the print stylesheet.
Use
display: noneto hide content from the screen display, which then appears in the print output- As long as screen and print styles are separate (they do not interact), the content will automatically appear when printing.
- Just keep in mind that elements and content instructed to
display: noneare ignored by some screen readers and screen readers are likely to be using the screen stylesheet.
Tables-based layouts effectively 'lock' text at a given location on the page
- Not all browsers respond well to attempts at restructuring table layouts when printing (the IE 6 and IE 7 browsers being the worst at this, given their limited support for the numerous values available for the
displayproperty). - The only reliable thing that can be done cross-browser with tables is
display: noneto remove cells (and be sure to get the entire column and not just part of it). - Layouts using divs are much easier to modify when printing.
- Not all browsers respond well to attempts at restructuring table layouts when printing (the IE 6 and IE 7 browsers being the worst at this, given their limited support for the numerous values available for the
Allow printed output to render in the normal flow
- Positioned elements can render off the printed page (or partially off the page), while floated elements can also get clipped.
- In some cases the floated element or positioned element cuts off all printing after it, so that the rest of the document is lost.
- Such printing anomalies have historically been in the Gecko-based browsers (e.g., Firefox).
Allow printed output to fill up the printed page width naturally
- Setting fixed widths for areas can cause content to be cropped in many browsers (IE 7 is the exception; it scales content to fit the printed page).
- It is best to allow block-level elements to naturally fill up the width of the printed page and flow content to the next line when necessary.
Control page breaks via CSS
- A way to control page breaks in printed output is via
page-break-beforeandpage-break-after, which need to have a value ofalwaysto work in IE browsers. - For example:
page-break-before: always; page-break-after: always;
- Just be careful with page breaks inside tables; those are likely to be problematic.
- It is most reliable to insert breaks between block-level elements.
- A way to control page breaks in printed output is via
Opera does not download images that are
display: nonein the screen styles- As a result, these images will never render when printing (printing does not cause the image to be downloaded from the server).
- Your best approach is to absolutely position the image out of the viewport (such as
top: -9999px;) in the screen display, so that it downloads but is not visible in the screen output. That approach allows it to be used in the print output.
Background images will likely not print
- Keep this in mind when creating your layout.
- If an image is a background yet you feel it is important to include it when printing, you can call it twice in the screen output (once as a CSS background image and again using an
<img />placed outside the viewport). - If you have text positioned on top of that
<img />you will definitely have problems getting the text color to change to something other than black across all the browsers. - If you definitely want background images to not print use your print styles to remove them and set a white background color.
If desired (and it may not be), you can display URLs after links in the print output
- This is handled via generated content, such as:
a:after {content: " (" attr(href) ") ";} - One issue with this approach is that IE 6 & IE 7 lack support for generated content.
- A document with lots of links can also result in a very cluttered printout so use with caution.
- Approaches based on JavaScript are much more elegant; this document uses such an approach in its printed output.
- This is handled via generated content, such as:
Sequence media-specific styles carefully if there are styles applying to all media
- If you have styles specified for
allmedia (or have no media specified, which then defaults toall), place print-specific styles (or call those styles) after the other styles. - This is important because the later position of the print styles will give them an edge in the cascade when there is conflict between rules and their specificities match.
- Avoiding styles applied to
allmedia eliminates this concern.
- If you have styles specified for
Test thoroughly cross-browser and cross-platform
Almost all browsers leave the print margins under the user's control
- Users specify these in the browser settings and our own
paddingandmarginsettings add to what the user has specified. - The Mac version of Opera allows the user to override those with their own
marginandpaddingsettings and therefore put content right up against the left / right edge of the printed page. - Make sure that the result is acceptable across browsers.
- Users specify these in the browser settings and our own
Layout anomalies can occur when printing from Gecko-based browsers (e.g., Firefox)
- Sometimes the anomaly (such as linked text losing spacing to its left and right sides) is only in the Print Preview and when the document is printed the spacing is fine.
- Other times it is a
positionorfloatissue and printed content is getting lost. - As long as screen and print styles are separate, however, there should not be any floating or positioning impacting the print layout (those instructions would only be in the screen-specific stylesheet).
Text rendering anomalies are fairly common in Opera's print preview
- Older versions of Opera (e.g., Opera 8.x) handled text just fine in their print preview.
- Version 9.x+ have had lots of anomalies with text display, in particular running text together.
Some browsers bring their own unique markup rendering when printing
- Gecko-based browsers (e.g., Firefox) and Internet Explorer 8 repeat
<thead></thead>and<tfoot><tfoot>rows if a table prints across multiple pages and that structural markup is used. - No other browsers do this and most of the time the repetition works well.
- The only time it doesn't work nicely in Firefox is when the table just barely crosses into the next page, because then the repeated header has little value. For Internet Explorer 8 there are bizarre line drawing issues with cells that cross pages. As always, test thoroughly.
- Gecko-based browsers (e.g., Firefox) and Internet Explorer 8 repeat
Tutorial Details
- Author: Jason Withrow (jason@usabledevelopment.com)
- Last Updated: July 21st, 2010
- URL: http://www.usabledevelopment.com/cssmedia