Bibliographic Information

Developing with Web Standards

Publisher: New Riders
Pub. Date: November 11, 2009
Print ISBN-10: 0-321-64692-4
Print ISBN-13: 978-0-321-64692-7
Web ISBN-10: 0-321-64755-6
Web ISBN-13: 978-0-321-64755-9

Abstract

New semantic like section,header,footer, article, nav aside, figure are NOT rendered in IE7 and IE6. They ignore them. Even
is ignored. Invisible.
There is sample code for get-header function that would help with epc.
Plus a set of scripts to use on custom order checkout.
HTMLHelp’s valet.htmlhelp.com/tidy.

With modern browsers, it’s also possible to use any element with an id as the destination for a link. So, for example, in our Pride and Prejudice site, if we have a table of contents with links to each of the volumes and chapters, we could link to the first volume of Chapter 2, which we marked up a little while ago like this:
This approach is preferable to adding extraneous empty anchor elements simply as a destination of a link.
In addition to linking within a document, we can link to:
  • Other pages on the same site—that is, other pages within the same root directory on your server
  • Parts of other pages on the same site
  • Other pages on the web
  • Parts of other pages on the web
  • Other resources on the web, such as image files, resources located on ftp servers, and so on
We can also use a link to open a new email message in a mail application.

Core DOM Objects and Methods

Now we’ve got an overview of the core concepts of the DOM, let’s take a look at some of the most commonly used DOM objects, and their methods and properties.

Window

The window object gives access to the properties and methods of the window containing the document. Getting the window object with JavaScript is straightforward: just use the word window. The window object has quite a few built-in properties that can be read, and sometimes changed, using JavaScript. These include how far the page is currently scrolled horizontally or vertically (window.scrollX and window.scrollY), the width and height of the content area of the window, (window.innerWidth and window.innerHeight), and a good deal else besides.
JavaScript and the DOM are case sensitive, which means that accessing window.innerwidth instead of window.innerWidth will cause an error. Note the format of DOM property and method names—where the initial letter of the first “word” is in lowercase, and subsequent “words” are in uppercase. This is referred to as camel case, and is the naming convention for all DOM methods and properties, making it easy to remember exactly how these names are written (provided you remember the name of course).
In addition to properties, like all DOM objects, window also provides a number of methods that a script can invoke to get the window to do things like move, resize, or ask for user input via various built-in dialogs like Alert, Prompt, and Confirmation. For example, we can stop the window from loading, perhaps to let the user stop loading a particularly long page, using window.stop.
Some methods take arguments, and may return results that can be used later in the script. For example, here, we can use the built-in window method prompt to ask a user for some input, and place the response in a variable called answer.
answer=window.prompt("What is 3+2");
We might also use another window method, alert, to display the user’s response:
window.alert(answer)
OK, so that’s a perfectly pointless thing to do, and likely to be really annoying, but it’s a good basic illustration of how the DOM works.
You’ll often see the use of window methods like alert by themselves, like this:
alert(theLink.href)
(Window methods are special in the DOM—you can refer to them without explicitly adding window to your code.)

Document

The document object gives developers access to the contents of the HTML document, and has a number of its own methods and properties that can be particularly useful when DOM scripting. For example, we can get (or set) the title, get the URL, and get a list of all the form elements in the document. The document object is also an element, which is the next main type of DOM object we’ll look at—this means that in addition to its own methods and properties, document objects also have all the methods and properties of other elements. To put it technically, the document object implements the element interface in addition to the document interface.

Element

Every element in an HTML document is represented in the DOM by an element object. Elements have numerous properties, such as className, id, its location with respect to its containing element (offsetLeft and offsetTop), its current width and height (offsetWidth and offsetHeight), and much else. There are numerous methods we can use as well, such as retrieving the value of a given attribute (getAttribute) or even all child elements of a particular type (getElementsByTagName).
One thing we may well want to do is get or change the style of an element, and there are several ways of doing this, which we’ll turn to now.
Style
If we simply want to directly change the style of an element, for example its background color, we can get the style property of the element, which returns a style object. We can then directly set the backgroundColor property of this object to the color we want.
Suppose we have a paragraph in a variable called thePar. We can change its background color like this:
thePar.style.backgroundColor="red"
There are a few things going on here. Note how we’ve chained our properties—we get the style property of the paragraph, which is a style object. Then we set the backgoundColor property of this object to red (we can use any color value we’d use in CSS as the value of the background color). The style object has a property for every possible CSS property, though it uses slightly different names for these. Dashes, like those in CSS’s background-color and text-align are removed, and the resultant name is converted to camel case, so in the preceding example, we have backgroundColor and textAlign.
The style object only contains the inline style of an element, not those from any linked or embedded style sheet. So, if we get the value of this property, we’ll only get the CSS properties set via inline CSS or set directly on the style using the DOM. If we set a CSS property via the DOM using the style object, this is the same as using inline CSS.
If we want all the style properties currently set on an element (including those set via style sheets), we need a function of the window object called getComputedStyle. After getting an element from the document using a method like getElementById, we pass the element whose styles we want to the getComputedStyle method. The getComputedStyle method then returns a style object that contains all the CSS properties of the element:
theStyle=window.getComputedStyle(thePara, null)
The object returned as the value of the variable theStyle is the same type of object as the style property of an element, but the new object contains all the currently set values of all the CSS properties for that element, whether from the default style sheet, the user style sheet, any linked or embedded style sheets, or inline styles. (Note that we can’t set an element’s styles with this object—we just get the currently computed values, then use the style property of the element to make any changes. We use the style property to set CSS properties on an element via the DOM.)
GetElementsByTagName
It might be necessary to get all the elements of a given kind—for example, all the links or all the input elements in a document or inside a particular element. We can use the getElementsByTagName method on any element object, or on the document—remember, the document is an element itself—to return a list of these elements. To find all input elements, in the document we would use this:
allInputs=document.getElementsByTagName("input")
We can iterate through this list using a JavaScript standby, the for loop, to perform various actions—more on this when we get to event handlers. (Want to know more about the for loop? Check out the JavaScript resources at the end of the book.)
GetElementById
One of the simplest and most common DOM methods is locating an element by its id value. Because ids are meant to be unique, we can very quickly find the element with an id of a given value. If more than one element on a page has a given id value (which shouldn’t be the case), this method will probably return the first such element, but that’s not guaranteed.
The GetElementById method is only a method of the document object, unlike getElementsByTagName. So, to locate an element with the id value site-navigation, we’d use: theElement=document.getElementById ("site-navigation").
One very common gotcha with this method is the capitalization of Id in GetElementById—the d must be lowercase and the I uppercase.
Now that we’ve taken a look at some of the most common objects you’ll work with when DOM scripting, we’ll turn to how we bring together user interaction (like typing, tapping, and clicking) with our document and scripts using an important part of the DOM called events.

Inspecting the DOM

These days, most browsers ship with or have as extensions very powerful debugging tools that can help inspect the DOM, and otherwise debug your web development. Here’s a very brief overview of some of the most widely used tools for popular browsers.

IE Developer Toolbar for IE 6 and 7

The IE developer toolbar, which can be downloaded and installed for IE 6 and 7, has the ability to inspect the DOM, validate HTML and CSS, check accessibility and much more. For developing and debugging in Internet Explorer, it’s a must-have.

Internet Explorer 8 Developer Toolbar

IE 8 has built-in developer tools, accessible from the tools button menu (F12 opens these tools). The IE developer tools have similar features to the IE 6 and 7 toolbar, and once again is indispensible for developing and debugging with IE 8.

Firefox Firebug and Web Developer Toolbar

These two Firefox extensions are essential tools for web developers using Firefox. The Web Developer toolbar is similar to the IE developer toolbar, while Firebug provides a huge array of functionality for debugging and developing HTML, CSS, and JavaScript, including a sophisticated DOM inspector.

DragonFly for Opera

DragonFly is a developer extension from Opera Software for the Opera browser, and features a rich DOM inspector in addition to other script, HTML, and CSS development tools.

Safari Web Inspector

Apple’s Safari browser for Windows and Mac OS features the Web Inspector, which is similar to DragonFly, Firebug, and the IE 8 developer tools, and it includes a DOM inspector.
With each of these browsers and the developer tools mentioned above you can select an element in the DOM, inspect its properties, such as current CSS, and traverse the DOM (going up to inspect parent elements, sideways to inspect sibling elements, or down to inspect child elements). For example, figure 5.3 shows the DOM as a collapsible tree on the left, with the properties for the selected element on the right. These DOM inspectors can help you quickly determine the structure of a document, which can greatly aid in the development of DOM scripts (and their debugging when they don’t work).
Until recently, DOM and JavaScript debugging were very poorly supported in browsers. Though these web development tools still lack the sophistication of those available to desktop application developers, we’re making huge strides.

Elements To Use

Now we’ve got an overview of the core concepts of the DOM, let’s take a look at some of the most commonly used DOM objects, and their methods and properties.

Window

The window object gives access to the properties and methods of the window containing the document. Getting the window object with JavaScript is straightforward: just use the word window. The window object has quite a few built-in properties that can be read, and sometimes changed, using JavaScript. These include how far the page is currently scrolled horizontally or vertically (window.scrollX and window.scrollY), the width and height of the content area of the window, (window.innerWidth and window.innerHeight), and a good deal else besides.
JavaScript and the DOM are case sensitive, which means that accessing window.innerwidth instead of window.innerWidth will cause an error. Note the format of DOM property and method names—where the initial letter of the first “word” is in lowercase, and subsequent “words” are in uppercase. This is referred to as camel case, and is the naming convention for all DOM methods and properties, making it easy to remember exactly how these names are written (provided you remember the name of course).
In addition to properties, like all DOM objects, window also provides a number of methods that a script can invoke to get the window to do things like move, resize, or ask for user input via various built-in dialogs like Alert, Prompt, and Confirmation. For example, we can stop the window from loading, perhaps to let the user stop loading a particularly long page, using window.stop.
Some methods take arguments, and may return results that can be used later in the script. For example, here, we can use the built-in window method prompt to ask a user for some input, and place the response in a variable called answer.
answer=window.prompt("What is 3+2");
We might also use another window method, alert, to display the user’s response:
window.alert(answer)
OK, so that’s a perfectly pointless thing to do, and likely to be really annoying, but it’s a good basic illustration of how the DOM works.
You’ll often see the use of window methods like alert by themselves, like this:
alert(theLink.href)
(Window methods are special in the DOM—you can refer to them without explicitly adding window to your code.)

Document

The document object gives developers access to the contents of the HTML document, and has a number of its own methods and properties that can be particularly useful when DOM scripting. For example, we can get (or set) the title, get the URL, and get a list of all the form elements in the document. The document object is also an element, which is the next main type of DOM object we’ll look at—this means that in addition to its own methods and properties, document objects also have all the methods and properties of other elements. To put it technically, the document object implements the element interface in addition to the document interface.

Element

Every element in an HTML document is represented in the DOM by an element object. Elements have numerous properties, such as className, id, its location with respect to its containing element (offsetLeft and offsetTop), its current width and height (offsetWidth and offsetHeight), and much else. There are numerous methods we can use as well, such as retrieving the value of a given attribute (getAttribute) or even all child elements of a particular type (getElementsByTagName).
One thing we may well want to do is get or change the style of an element, and there are several ways of doing this, which we’ll turn to now.
Style
If we simply want to directly change the style of an element, for example its background color, we can get the style property of the element, which returns a style object. We can then directly set the backgroundColor property of this object to the color we want.
Suppose we have a paragraph in a variable called thePar. We can change its background color like this:
thePar.style.backgroundColor="red"
There are a few things going on here. Note how we’ve chained our properties—we get the style property of the paragraph, which is a style object. Then we set the backgoundColor property of this object to red (we can use any color value we’d use in CSS as the value of the background color). The style object has a property for every possible CSS property, though it uses slightly different names for these. Dashes, like those in CSS’s background-color and text-align are removed, and the resultant name is converted to camel case, so in the preceding example, we have backgroundColor and textAlign.
The style object only contains the inline style of an element, not those from any linked or embedded style sheet. So, if we get the value of this property, we’ll only get the CSS properties set via inline CSS or set directly on the style using the DOM. If we set a CSS property via the DOM using the style object, this is the same as using inline CSS.
If we want all the style properties currently set on an element (including those set via style sheets), we need a function of the window object called getComputedStyle. After getting an element from the document using a method like getElementById, we pass the element whose styles we want to the getComputedStyle method. The getComputedStyle method then returns a style object that contains all the CSS properties of the element:
theStyle=window.getComputedStyle(thePara, null)
The object returned as the value of the variable theStyle is the same type of object as the style property of an element, but the new object contains all the currently set values of all the CSS properties for that element, whether from the default style sheet, the user style sheet, any linked or embedded style sheets, or inline styles. (Note that we can’t set an element’s styles with this object—we just get the currently computed values, then use the style property of the element to make any changes. We use the style property to set CSS properties on an element via the DOM.)
GetElementsByTagName
It might be necessary to get all the elements of a given kind—for example, all the links or all the input elements in a document or inside a particular element. We can use the getElementsByTagName method on any element object, or on the document—remember, the document is an element itself—to return a list of these elements. To find all input elements, in the document we would use this:
allInputs=document.getElementsByTagName("input")
We can iterate through this list using a JavaScript standby, the for loop, to perform various actions—more on this when we get to event handlers. (Want to know more about the for loop? Check out the JavaScript resources at the end of the book.)
GetElementById
One of the simplest and most common DOM methods is locating an element by its id value. Because ids are meant to be unique, we can very quickly find the element with an id of a given value. If more than one element on a page has a given id value (which shouldn’t be the case), this method will probably return the first such element, but that’s not guaranteed.
The GetElementById method is only a method of the document object, unlike getElementsByTagName. So, to locate an element with the id value site-navigation, we’d use: theElement=document.getElementById ("site-navigation").
One very common gotcha with this method is the capitalization of Id in GetElementById—the d must be lowercase and the I uppercase.
Now that we’ve taken a look at some of the most common objects you’ll work with when DOM scripting, we’ll turn to how we bring together user interaction (like typing, tapping, and clicking) with our document and scripts using an important part of the DOM called events.

Inspecting the DOM

These days, most browsers ship with or have as extensions very powerful debugging tools that can help inspect the DOM, and otherwise debug your web development. Here’s a very brief overview of some of the most widely used tools for popular browsers.

IE Developer Toolbar for IE 6 and 7

The IE developer toolbar, which can be downloaded and installed for IE 6 and 7, has the ability to inspect the DOM, validate HTML and CSS, check accessibility and much more. For developing and debugging in Internet Explorer, it’s a must-have.

Internet Explorer 8 Developer Toolbar

IE 8 has built-in developer tools, accessible from the tools button menu (F12 opens these tools). The IE developer tools have similar features to the IE 6 and 7 toolbar, and once again is indispensible for developing and debugging with IE 8.

Firefox Firebug and Web Developer Toolbar

These two Firefox extensions are essential tools for web developers using Firefox. The Web Developer toolbar is similar to the IE developer toolbar, while Firebug provides a huge array of functionality for debugging and developing HTML, CSS, and JavaScript, including a sophisticated DOM inspector.

DragonFly for Opera

DragonFly is a developer extension from Opera Software for the Opera browser, and features a rich DOM inspector in addition to other script, HTML, and CSS development tools.

Safari Web Inspector

Apple’s Safari browser for Windows and Mac OS features the Web Inspector, which is similar to DragonFly, Firebug, and the IE 8 developer tools, and it includes a DOM inspector.
With each of these browsers and the developer tools mentioned above you can select an element in the DOM, inspect its properties, such as current CSS, and traverse the DOM (going up to inspect parent elements, sideways to inspect sibling elements, or down to inspect child elements). For example, figure 5.3 shows the DOM as a collapsible tree on the left, with the properties for the selected element on the right. These DOM inspectors can help you quickly determine the structure of a document, which can greatly aid in the development of DOM scripts (and their debugging when they don’t work).
Until recently, DOM and JavaScript debugging were very poorly supported in browsers. Though these web development tools still lack the sophistication of those available to desktop application developers, we’re making huge strides.

Guidelines and Checkpoints

WCAG 1
Published in 1999, in the days of version 4 browsers, WCAG 1 was the first major attempt to codify a set of practices to ensure more accessible websites. The goal of WCAG 1 was to show “how to make Web content accessible to people with disabilities” (www.w3.org/TR/WCAG10).
WCAG 1 is divided into fourteen guidelines, each of which is subdivided into checkpoints, and each of these checkpoints has a priority, from A to AAA (usually called “triple A”). Conformance to WCAG 1 guidelines can be measured by conformance to these checkpoints. A document has a conformance level A if it meets all of the level A checkpoints. Likewise, a document is considered AA (“double A”) if it meets all the AA checkpoints, and triple A if all of the AAA checkpoints are met.
Before we delve a little more deeply into these guidelines and checkpoints, it’s worth noting that AAA compliance is widely considered to be difficult to attain, and not always worth the effort: many AAA checkpoints are highly subjective, and AAA compliance produces little practical value. As a result, AA compliance is the level most experts (and some official government guidelines) recommend aiming for.
Guidelines and Checkpoints
As noted above, each of the fourteen guidelines of WCAG 1 has several checkpoints. In this chapter, we’ll examine only those checkpoints that most commonly cause difficulties. The WCAG 1 guidelines (and an accompanying “Techniques” document) are quite straightforward, so don’t be afraid to read them yourself.
Guideline 1: Provide Equivalent Alternatives to Auditory and Visual Content
This guideline addresses the needs of people with hearing or visual disabilities. One of the most common errors developers make is to omit appropriate alt content for images. In HTML 4, all img elements must have an alt attribute, though the attribute value may be empty (that is alt="") when an image is purely decorative—though we should really be using CSS, rather than markup, to add such images.
Rich audio and video content accessibility requires far more than simple textual equivalents, and the requisite captioning techniques go quite some way beyond the scope of this book. You’ll find links to resources on audio and video captioning and related accessibility techniques at the end of this book.
Guideline 2: Don’t Rely On Color Alone
This applies to CSS more than HTML, as style should always be applied using CSS, not presentational markup. Up to eight percent of the male population has some form of difficulty discerning the difference between colors, while people using monochrome devices (such as Amazon’s Kindle) will not be able to discern between many different colors. Instead of, for example, using green to indicate safe and red to indicate danger, use shapes, text labels, and other indicators to convey the information.
Guideline 3: Use Markup and Style Sheets and Do So Properly
This guideline suggests that we should use the technologies of the web according not just to the letter of the law (table-based layouts will, after all, validate), but according to its spirit as well. Checkpoints here include ensuring documents are valid, relative units like em and % are used instead of px in CSS, and the appropriate semantic and structural elements of HTML are used (for example headings, lists, quotations, and so on).
Guideline 5: Create Tables That Transform Gracefully
Tabular data can cause significant problems for people using assistive devices like screen readers. Guideline 5 has several checkpoints to help improve the accessibility of such data.
These checkpoints include using row and column headers in data tables, and for complex data tables, use features like thead, tfoot, and tbody to group rows, col and colgroup to group columns, and the axis, scope, and headers attributes to show the relationships between cells and headers. We look at techniques for improving the accessibility of data tables later in this chapter.
Guideline 9: Design for Device-Independence
Guideline 9 focuses on the importance of being able to use a site or page no matter what input device you’re using—a keyboard, a voice input device, and so on—instead of only with a mouse.
These are just a few of the guidelines, but many major sites fail to comply even with this limited set. Conformance to WCAG 1 level AA is mostly straightforward, and is usually machine testable using tools we’ll cover in a moment. It is, therefore, relatively easy to assess a site’s level of conformance with these guidelines—and developers have little excuse for failing to meet them.

Common Accessibility Problems (and Solutions)

We’ll finish this chapter by addressing some of the most common accessibility problems, and ways of addressing them simply with HTML and CSS.

Links and Titles

Links are extensively used by screen readers and assistive devices to give users quick access to the contents of a page. While they only constitute a small percentage of the text on a page, they are a key way for many users to access a page’s content. The text of a link is an important guide to where a link will take a user. For optimum accessibility, link text should “clearly identify the target of each link” (WCAG 1), and avoid assumptions about users’ input devices revealed by use of terminology like “click here” as the link text. When several links on a page use the same text, they should all point to the same location.
The title attribute on link elements, although considered by many to add valuable accessibility information, can in fact be harmful: it can obscure other content in browsers that display title information as a tooltip, it isn’t accessible unless a mouse is used, or users of screen readers have their settings so that title values are read out. There is no consensus in the industry as to whether the title attribute should be used, but it should definitely not be the only way for users to identify a link’s destination.

Headings

Screen readers often use the headings on a page to create a “table of contents” to help users scan the page and jump to relevant areas. If you use heading elements as headings and use the heading order sensibly, you can make these screen-reader behaviors more usable. Don’t skip heading levels (from h2 to h4 for instance). The visual style of headings can always be changed by CSS, so there’s no need to skip a heading level.

alt text

Any non-textual content should have a textual alternative. With images, you can do this using the alt attribute. (A pedantic note from an old-timer: it’s not the alt “tag.”) Any alt content should be succinct, and although all img elements require an alt attribute in order for a page to validate, purely decorative images should have an empty string as the value of their alt attribute. Better still, purely decorative images (list-item bullets, for example, or decorative background images) should be included via CSS, not markup, which should be reserved for semantically useful content.

Color Contrast

The rather vague term color blindness leads to the common misconception that people who are color blind see the world in grayscale. This kind of vision impairment (“monochromasy”) is in fact extremely rare; the majority of people with color blindness see in color, but have difficulty distinguishing between certain colors that are easily distinguishable by people without color blindness.
Although it’s important that we avoid using only color to convey meaning (for example, using red as a warning, in the absence of additional shapes, text, or other information), there are other color-related accessibility concerns to consider. A lack of sufficient visual contrast between the text and its background is a commonly neglected problem. A text-background pair that appears “obviously” high contrast to someone without color blindness may be illegible to someone with color blindness or another visual deficiency.
Many tools will report whether a pair of colors has a sufficient contrast for legibility, but using these can be time consuming, since you must manually test each foreground and background color combination for a site. Tools like AccessColor from AccessKeys (www.accesskeys.org/tools/color-contrast.html) analyze an entire document by looking at the DOM and highlighting possible contrast problems. Most contrast-testing tools only work when text is set against a background color (not an image), however, and they don’t test dynamic effects like hovering, so they can’t provide a foolproof test of color contrast.

Tables

Tables present particular challenges for visually impaired users. The structure of a table, which may appear obvious to sighted users, can be confusing when read by a screen reader. HTML provides several elements and attributes to help screen readers read out the contents of tables more sensibly.
In addition to the standard td (table data) elements, tables may also have table header (th) elements, as we saw in Chapter 4. To make tables as accessible as possible, th elements should be used for the cells that are the headers of rows or columns.
caption and summary
The table caption element exists to provide a short description of the table, which is used both visually by a browser, and by screen readers. It’s recommended tables have a caption, which is marked up immediately after the opening tag of the table. Tables may only have a single caption.
Timetable for Day 1 of the conference
In addition, the table element may have a summary attribute, which provides an overview of the contents of the table for users of screen readers. Sighted readers can also get a sense of the table and its contents at a glance; the summary attribute exists to help readers with visual disabilities do so as well. Unlike captions, summaries are not rendered by visual browsers—they are exclusively used by screen readers.
Timetable for Day 1 of the conference
abbr and scope
Already we’ve given the browser a good deal of information that will make our tables more accessible. But particularly for complex tables, HTML has a number of under-utilized but helpful features that screen readers can use to help their users make more sense of data tables.
Because screen readers usually read each cell (including header cells) linearly, each header will be read many times, which may become time consuming and annoying. We can use the abbr attribute of the th element to define abbreviated text to be read in place of the full contents of the th element.
Design TrackBusiness TrackDevelopment Track
It’s not always clear from the structure of a table whether a th element is the header for a row or a column of cells. The scope attribute allows us to specify which cells the th element is the header of. In our case above, the headers are for columns, and so our markup would be:
Design TrackBusiness TrackDevelopment Track
For relatively simple tables, a screen reader can use the scope attribute to read out the header (or abbreviated header if we’ve added an abbr attribute) in front of the contents of a cell.
For example, in figure 6.1, the screen reader might read the highlighted cell as “design Font Embedding and Typography Mark Boulton.” But, as this example shows, this is far from the whole picture. What the reader really needs to hear is something along the lines of “10.45am–11.40am design Font Embedding and Typography Mark Boulton.” In essence, we need to associate more than one header with the cell. We can do this by adding an id to each header, and then using the headers attribute for td elements to associate th elements with a td element.
6.1. A sighted person can easily deduce that the font embedding session is in the design track at 10.45. For those using screen readers, it can be far from easy, unless we use the right markup.
Code View: Scroll / Show All
Timetable for Day 1 of the conference
Time
Design Track
Business Track
Development
Track
While this additional information requires extra effort to mark up, the impact on accessibility for people using screen readers can be substantial. Like most development practices, when first encountered and used, these techniques may seem like a burden, but using appropriate attributes and elements soon becomes second nature.

Forms

You can directly and significantly improve the accessibility of your pages by marking up forms correctly. A few simple practices will greatly increase the usability of forms for people with various disabilities.
Form field labels provide absolutely vital information for users of screen readers. Although visual cues make it easy for those of us with good vision to determine what a field is for, unless form fields are explicitly and correctly associated with labels, users of screen readers may be unable to determine how a form works.
Some form elements—button elements, for example—have their own labels. For these elements, the value of the value attribute is the label for the element. When there is no implicit label, which is the case for most form elements, the label element should be used, and associated directly with the element it is the label for using the for attribute of the label. Here’s how we can ensure maximum accessibility for our labeled text input field:
"last-name-label">
Note that we’re also using the ARIA attribute aria-labelledby in the form element itself—the input element, in the preceding example—to give the browser the id of the element that labels the present element. So in our example, we have indicated that an element (the label element, appropriately enough) with the id of last-name-label provides the label for the input element whose id is last-name.
Sharp-eyed readers may note that aria-labelledby works just like the HTML 4 for attribute, but backward: with for, the labeling element identifies the labeled element by its id; with aria-labelledby, the labeled element identifies the labeling element by its id. Note too that labelledby, though not standard U.S. spelling, is correct in this instance.
When a label element cannot be used, WCAG 2 suggests that it is sufficient to use the title of the element as the label. For example, we’d need to use title for a search box in the toolbar of a page, where a label would take up more horizontal space than is available.
Grouping Field Elements
More complex forms may make more sense when related fields are grouped together with a heading for each group. HTML provides the fieldset and legend elements for precisely this purpose. A fieldset is simply a fieldset element that contains all of the related form elements. The first element of the fieldset should be its legend, which is similar to a caption for a table.
Billing Contact

But first we need to know, who'll be paying

for the tickets?
    Name...
    The techniques we’ve covered here address many of the most common accessibility difficulties that users face on the web. Implementing them is typically not onerous, and goes a long way to improving the experience of your sites by people who are most reliant on the web. It will also go a long way to addressing the legal and institutional obligations you or your organization may be required to meet.

    We can use the following targets in conditional comments:
    • [if IE]—will be used by any version of IE from 5 and up (conditional comments were introduced with version 5)
    • [if IE 5], [if IE 7] and so on (note the space between IE and the browser number), targets specific browser versions
    • [if gt IE 6] (gt stands for greater than—this example targets versions after version IE 6)
    • [if gte IE 7] (gte stands for greater than or equal to—this example targets version IE 7 or more recent)
    • [if lt IE 8] (lt stands for less than—this example targets versions of IE older than IE 8)
    • [if lte IE 6] (lte stands for less than or equal to—this example targets IE 6 or older)
    Conditional comments can only be used inside HTML—we can’t conditionally comment our CSS with this approach.

    When Feature Support Is Missing

    The techniques we’ve covered so far deal with browser inconsistencies due to buggy support for CSS in one or more browsers and good support in others. The second significant challenge developers face is the absence of support in one browser for a feature that is supported in other browsers. This is more common as Firefox, Safari, and Opera introduce support for CSS3 features and Internet Explorer continues to offer limited CSS3 support. (We look in detail at CSS3 in Chapters 12 through 15.)
    In many cases, progressive enhancement is the way to go. If a browser doesn’t support border-radius, text shadows, box shadows, or other CSS3 features, we can usually just ignore the lack of support for such cosmetic properties. But, there are often features that go beyond the cosmetic—in particular, CSS3 selectors—that are well supported in browsers other than Internet Explorer, and which can radically improve the quality of our markup (as we’ll see in Chapter 12). In the absence of support for such features in a widely used browser like IE, can we use them at all?
    Happily, the answer is yes. Using JavaScript—and popular JavaScript libraries whose use requires little actual scripting knowledge—we can add support for many features that are not natively supported in web browsers. Let’s take a look at some of these libraries.

    Dean Edwards’s IE 7 (and IE 8)

    The best known JavaScript library for enhancing IE 6 and 7’s support for features of CSS2 and CSS3 is Dean Edwards’s ie7-js (code.google.com/p/ie7-js), which was originally known simply as “ie7.” This popular library has been updated and is now offered as a superset library, ie8-js, which includes all the functionality of ie7-js and adds support for IE 8 and features of CSS (and HTML) still missing even from IE 8.
    The library’s goal is “to make Microsoft Internet Explorer behave like a standards-compliant browser,” and it adds support for:
    • CSS selectors like the child, adjacent sibling, structural, and attribute selectors
    • CSS properties including max-width, min-width, max-height, and min-height
    • Alpha transparency in PNG graphics
    ...as well as fixing common bugs like the Double Margin and Peek-a-Boo bugs we saw earlier in the chapter, via a related bug-fixing library, ie7-squish.
    When introduced, the idea of JavaScript libraries for extending and fixing browsers was quite radical, but in the years since ie7-js was first released, the idea of using JavaScript for this sort of purpose has become widely accepted. Still, two possible drawbacks remain. First, many people still use the web with JavaScript disabled, either because of personal security concerns or because of security policies in large corporate, government, and institutional networks. Because of this limitation, all JavaScript libraries should be used in conjunction with unobtrusive scripting techniques like those discussed in Chapter 5. The second potential drawback is that use of the library may harm site performance, particularly for very high-traffic sites. If you use one of these libraries in a production environment, you’ll need to consider the potential negative performance effects for your specific project.
    Both ie7-js and ie8-js are easy to use. They’re hosted on Google Code, so in many cases you won’t even have to host them yourself. It’s a good idea to use conditional comments to link only to Internet Explorer, so that other browsers don’t download the unnecessary file. Here’s what that might look like if we wanted to use the ie8 version of the library along with the ie7-squish bug-fixing library:
    And presto! Internet Explorer now supports all of the features that the library adds as though that support were native in the browser. These libraries are used on large, popular websites, and have been refined over several years, so they’re safe to use in just about every situation. The only real surprise is that more developers don’t use them.

    Feature Support

    When Feature Support Is Missing

    The techniques we’ve covered so far deal with browser inconsistencies due to buggy support for CSS in one or more browsers and good support in others. The second significant challenge developers face is the absence of support in one browser for a feature that is supported in other browsers. This is more common as Firefox, Safari, and Opera introduce support for CSS3 features and Internet Explorer continues to offer limited CSS3 support. (We look in detail at CSS3 in Chapters 12 through 15.)
    In many cases, progressive enhancement is the way to go. If a browser doesn’t support border-radius, text shadows, box shadows, or other CSS3 features, we can usually just ignore the lack of support for such cosmetic properties. But, there are often features that go beyond the cosmetic—in particular, CSS3 selectors—that are well supported in browsers other than Internet Explorer, and which can radically improve the quality of our markup (as we’ll see in Chapter 12). In the absence of support for such features in a widely used browser like IE, can we use them at all?
    Happily, the answer is yes. Using JavaScript—and popular JavaScript libraries whose use requires little actual scripting knowledge—we can add support for many features that are not natively supported in web browsers. Let’s take a look at some of these libraries.

    Dean Edwards’s IE 7 (and IE 8)

    The best known JavaScript library for enhancing IE 6 and 7’s support for features of CSS2 and CSS3 is Dean Edwards’s ie7-js (code.google.com/p/ie7-js), which was originally known simply as “ie7.” This popular library has been updated and is now offered as a superset library, ie8-js, which includes all the functionality of ie7-js and adds support for IE 8 and features of CSS (and HTML) still missing even from IE 8.
    The library’s goal is “to make Microsoft Internet Explorer behave like a standards-compliant browser,” and it adds support for:
    • CSS selectors like the child, adjacent sibling, structural, and attribute selectors
    • CSS properties including max-width, min-width, max-height, and min-height
    • Alpha transparency in PNG graphics
    ...as well as fixing common bugs like the Double Margin and Peek-a-Boo bugs we saw earlier in the chapter, via a related bug-fixing library, ie7-squish.
    When introduced, the idea of JavaScript libraries for extending and fixing browsers was quite radical, but in the years since ie7-js was first released, the idea of using JavaScript for this sort of purpose has become widely accepted. Still, two possible drawbacks remain. First, many people still use the web with JavaScript disabled, either because of personal security concerns or because of security policies in large corporate, government, and institutional networks. Because of this limitation, all JavaScript libraries should be used in conjunction with unobtrusive scripting techniques like those discussed in Chapter 5. The second potential drawback is that use of the library may harm site performance, particularly for very high-traffic sites. If you use one of these libraries in a production environment, you’ll need to consider the potential negative performance effects for your specific project.
    Both ie7-js and ie8-js are easy to use. They’re hosted on Google Code, so in many cases you won’t even have to host them yourself. It’s a good idea to use conditional comments to link only to Internet Explorer, so that other browsers don’t download the unnecessary file. Here’s what that might look like if we wanted to use the ie8 version of the library along with the ie7-squish bug-fixing library:
    And presto! Internet Explorer now supports all of the features that the library adds as though that support were native in the browser. These libraries are used on large, popular websites, and have been refined over several years, so they’re safe to use in just about every situation. The only real surprise is that more developers don’t use them.

    Horizontal Centering

    Centering a block of content horizontally is a very common design request, and CSS offers two ways of accomplishing it. We can use the text-align CSS property to center the inline content of an element (or to set that content flush left, flush right, or justified), but this property isn’t designed for centering block-level elements. To center a block-level element (for example, a paragraph) inside its parent element (a div, perhaps, or the body element itself), we’ll use the width CSS property.
    Suppose we want to make paragraphs that are half the width of the body, and are centered horizontally on the page. We can do this by creating a CSS rule that selects paragraphs and uses the width and margin properties, setting the width at 50 percent of the parent element and using the margin value auto for the element’s left and right margins. This works because when it’s used to define horizontal margins, auto specifies that the margin space inside the containing element be divided evenly between the left and right margins.
    Here’s a CSS rule that would make paragraphs half as wide as the parent element and center them horizontally:
    p {
    width: 50%;
    margin: 0 auto;
    }
    Since we’re defining the element’s width using a percentage value, we could also use this rule instead:
    p {
    width: 50%;
    margin: 0 25%;
    }
    These two rules are functionally identical because we know the width of the p element as a percentage of its parent’s width. If we specified the element’s width using something other than a percentage—ems, for example—we would have to use auto for the left and right margins, because we wouldn’t know how much horizontal space there would be between the edges of the p element and those of its parent element.
    Easy, right? Sadly, there’s one more step. Internet Explorer in Quirks mode doesn’t support the auto value for the margin property, so we need a workaround for Internet Explorer in Quirks mode. Luckily, we can rely on a text-align bug in IE to center our elements in IE/Quirks mode without affecting browsers that properly support auto values for margin.
    Sticky Note
    If you aren’t clear as to what exactly Quirks mode and standards mode are, we go into this in detail in Chapter 7.
    I mentioned that text-align is not designed to center block-level elements. In IE Quirks mode, however, text-align does center block-level elements. We can use this bug to counter the effects of IE’s lack of support for auto margin values in Quirks mode without confusing more CSS-capable browsers. Here’s how:
    First, we’ll use text-align: center on the containing element of the elements we wish to center (in this instance, we want to center paragraphs inside the body):
    body {
    text-align: center
    }
    This rule will center the paragraphs in IE, but will also center all text on the page in other modern browsers, because text-align is inherited. To overcome this problem, we’ll set the text-align of paragraphs to left (we could also use right or justified). This ensures that the text itself will not be centered—and because text-align aligns an element’s contents, not the element itself, the paragraph elements themselves will be centered in IE. Here’s what our CSS rules look like:
    body {
    text-align: center
    }
    p {
    text-align: left;
    width: 50%;
    margin: 0 auto
    }
    Because there’s no single CSS property for centering block-level elements horizontally, this design request is often a frustrating problem for CSS newcomers. Once you know how to do it, though, it’s very easy to achieve in all modern browsers with the tricks I’ve just described. Vertically centered elements, on the other hand, are more difficult to implement—but not impossible.

    Differences from HTML4

    To get into the details of HTML5, let’s begin by taking a look at how it differs from HTML4.
    While HTML5 is designed to be backward compatible with HTML4, it actually has two “flavors” of syntax—an HTML syntax and an XHTML syntax—so you can continue to use HTML5 with whichever syntax you’re most comfortable with.
    HTML5 also allows developers to use two XML languages—MathML, a markup language for mathematics, and SVG, a markup language for vector graphics we’ll cover in the last chapter of this section—directly within HTML markup.
    Additionally, HTML5 introduces several new HTML elements, the most useful of which are detailed in the “Headers, Footers, Sections, and other New Structural Elements in HTML5” section of this chapter. Some of the characteristics of current HTML elements have also changed in HTML5. Anchor elements (), for example, can now contain any other elements, not just inline elements as is the case with HTML4 and XHTML 1. So it’s now possible to link, say, the entire header of a page to a URL simply by putting it within an anchor element. As you might expect, some elements deprecated in earlier versions of HTML, such as font, center, u, and non-iframe frames, are not part of HTML5, though other elements that might be considered presentational, such as , remain in the language. The specification also includes a number of changes to the DOM, and much more besides.
    When it comes to everyday implications for developers, here are some of the most significant changes you’ll see in HTML5.

    Declaring a DOCTYPE

    Described in the specification as a “mostly useless, but required” header, a DOCTYPE is required in HTML5 documents, mostly to ensure compatibility with older browsers that respond to missing DOCTYPEs by rendering such pages in “quirks” or “non-standards” modes. The required DOCTYPE is about as simple as it can be. At the top of an HTML5 document we simply use the following:
    The DOCTYPE is case-insensitive—it can be uppercase, lowercase, or a mix of cases.

    Headers, Footers, Sections, and other New Structural Elements in HTML5

    As we’ve mentioned, HTML5 introduces many new elements. In the rest of this chapter, we’ll look at several new structural elements of HTML5, along with elements related to embedded content, such as video and audio.
    The logic of the new structural elements in HTML5 comes from research into common ways in which current web documents are marked up. Some of the most common class and id values and most commonly used “patterns” of markup that web developers will instantly recognize include “header,” “footer,” and “nav” (or some other variation of the term “navigation”). HTML5 uses many of these common patterns and terms for new elements.
    header
    Many web pages include an area at the top of the page that displays identifying information about the page and site, often including an organization’s logo and name, and often also navigation, for example, the different subsections of the site. HTML5 introduces a new element, header, for this type of content—though in HTML5, header elements don’t have to appear at the top of a page, as we’ll see in a moment.
    Header elements are governed by a number of syntax rules: They must contain at least one heading (h1 to h6) and must not contain a section element, another header element, or a footer element. Unfortunately, the nav element is a kind of section, so the header can’t contain nav elements. This is a significant challenge in the real world, as many page headers contain navigation systems. Although the most recent editors’ draft of the HTML5 specification has relaxed this requirement, as of this writing, the current official draft specification still prevents nav elements from being contained within a header. It’s to be hoped that the relaxation of this constraint will become a permanent part of the HTML5 specification.
    Content Elements
    HTML4 and XHTML 1.x offer few ways of grouping together the content of a page. There’s the p element for paragraphs, but for larger logical chunks of information—chapters, for example—we must use divs. And, as we saw in Chapter 4, a div is simply a block container with no intrinsic semantic connotations. HTML5 introduces several elements that allow developers to group and semantically identify content.
    section
    Paragraphs of information are typically grouped together into larger sections, such as a book chapter, a magazine or newspaper article, or a blog post. HTML5 provides the
    element for grouping together content—paragraphs, images, headings, and so on—to form a larger logical unit.
    section elements may contain a header and a footer, and indeed can contain any element that can be contained inside the body of an HTML5 document. They can also include more specific information, or metadata, about a section using the class or id attribute as appropriate. For example, an academic paper often includes an abstract, so we could mark that up as
    . A book usually has many chapters, so we’d likely mark up chapters using
    .
    The section element is not designed to be a replacement for the div element, which is still part of HTML5; section elements should only be used when they’re semantically appropriate. For other forms of content groupings, div is still the appropriate element to use in HTML5.
    article
    HTML5 also offers specific types of sections, one of which is the article. Articles are sections that can logically exist independently from the page in which they occur. For example, a single page on a newspaper or magazine website might contain several independent articles. By contrast, the chapters of a novel marked up as a single HTML document do not stand independently from the containing page, and so are more appropriately marked up as section, rather than article, elements. Other forms of content that might be marked up with the article element include blog posts, dictionary and encyclopedia entries, and short stories.
    Headings in section and article Elements
    HTML4 headings have a significant limitation: there can be, at most, six levels of headings within a given document. There are certainly documents for which this is an unrealistic number: documents such as articles of legislation often require many more levels than six, and heading levels are fundamentally important to the nature of legislation (they are used in legal citation).
    HTML5 addresses this deficiency by allowing (and encouraging) each section to begin numbering its headings from level 1 and “strongly encouraging” that each section be associated with a single heading. This single heading should either be an h1 (that is, each section, no matter how deeply nested within other sections begins with a heading of level 1), or the level of the single heading of each section should match the level of nesting of the section. This is outlined in the specification at www.whatwg.org/specs/web-apps/current-work/#headings-and-sections.
    As you can see, HTML5 offers a much more sophisticated (and, arguably, overly complex) document structuring model than HTML4. In HTML4, a single parent element—usually the body or a div—typically contains headings and paragraphs as its direct children. The structure of such documents is revealed only by its numbered headings. In HTML5’s sectioning model, it’s really the nesting of section elements, rather than heading levels, that reveals the structure of the document.
    Here’s what the structure of this chapter might well look like in HTML4:

    HTML5

    What is HTML5?

    Key features of HTML5

    As we saw in Part I of this book, by around 2000, most

    major forces in the web development community considered
    XHTML to be the future of HTML. Much of the
    ...
    In HTML5, each heading is associated with a section, and we can explicitly reveal the document’s structure via the nesting of these sections. Here’s how the same document might be marked up in HTML5:

    HTML5

    What is HTML5?

    Key features of HTML5

    As we saw in Part I of this book, by around 2000,

    most major forces in the web development community
    considered XHTML to be the future of HTML. Much of
    the ...
    ...

    A Tale of Two Models

    What’s the difference between the two heading-level models—and more importantly, why have two at all?
    First, a significant reason for the new model is to enable more than six levels of headings. It closely matches XHTML 2’s model, in which there is only one heading element (h), and in which heading levels are marked solely by the use of the section element, with each nested section increasing the heading level by one.
    But why have another model that matches HTML4’s heading model? Some browsers—particularly screen readers like JAWS, which are used by people with visual impairments to access the web—use heading levels to create outlines of the content, making pages more easily navigable. Screen readers tend to be developed slowly, and user upgrade rates are correspondingly gradual, so many visually impaired web users will probably lack access to HTML5 support for the foreseeable future. As a result, the widespread adoption of the XHTML 2–style heading-level model could present significant challenges for these users.
    Is one of these approaches to be preferred? There’s considerable debate about the merits of the first (h1-only) method and about its impact on accessibility. This method tends to make styling with CSS somewhat more complicated, as it requires the use of descendent or child selectors like “section section section h1” rather than a simple selector such as h4, and it also makes accessing page elements using JavaScript more difficult. Neither approach is discouraged, so I recommend using the latter model (multiple numbered heading levels) for now provided that the nesting level of sections matches the number of their headings.
    Or, we can simply continue to number headings as we would in HTML4, as if the section elements weren’t there:

    HTML5

    What is HTML5?

    Key features of HTML5

    As we saw in Part I of this book, by around 2000,

    most major forces in the web development community
    considered XHTML to be the future of HTML. Much of
    the ...
    ...
    nav
    Just as “header” (or some variation of that term) is one of the most commonly used class and id names in HTML, “navigation” (or some variation, such as “nav”) is similarly popular. HTML5 introduces the nav element, to mark up “a section of a page that links to other pages or to parts within the page.” The specification continues, explaining the element is not intended to be used to mark up all groups of links on a page: “only sections that consist of primary navigation blocks are appropriate for the nav element.”
    One drawback of the nav element is that developers often mark up navigation in HTML4 and XHTML as a list of links—after all, site and page navigation is usually made up of a list of links. Because nav is a kind of section, however, if we wish to continue using lists for navigation markup, we must wrap our lists in a nav element. For example, we may currently use something like the following for our navigation:
    "Back to the home page">Home
    title="Slides and podcasts from past events">
    Resources
    title="Future and past conferences">Events
    To continue using this list for our navigation links in HTML5, we’d wrap the whole thing in the nav element, like this:
    "http://www.webdirections.org/" title="Back to the
    home page">Home
    title="Slides and podcasts from past events">
    Resources
    title="Future and past conferences">Events
    aside
    Articles and stories often feature sidebars, which contain related secondary content. HTML5 calls these “asides” and provides the aside element for marking up this kind of content. We’ll see asides, along with other new HTML5 elements, in action in a moment.
    figure
    HTML4 offers a single way to include images in markup, and CSS provides background-image and other ways of adding images as decoration, but not as part of the document itself. In real life, however, images appear in documents in different ways and for different reasons and are often accompanied by captions or descriptions. HTML5 provides the figure element for these kinds of images.
    A figure in a book or article often includes an image and a caption. Together, the image and caption comprise a figure element in HTML5 (though the caption element is not technically required.) In HTML4, we’d likely mark up this sort of content as follows:
    the image itselfThis is the caption for the
    image
    In HTML5, we can use the figure element in place of the div, and then go a step further using the legend element—which is used in HTML4 to caption form elements—in place of the span element in our example. Rather than invent a new element for this purpose, HTML5 reuses an existing element of HTML with similar semantics. Putting these components together, our HTML 4 example could be marked up in HTML5 using the following markup:
    the image itselfThis is the caption for the image
    The order of legend and image can also be reversed.
    Somewhat confusingly, the figure element can in fact be used for more than just images. The specification states that the element is for content that is “self-contained and is typically referenced as a single unit from the main flow of the document.” It can thus be used to mark up illustrations, diagrams, photos, code listings, and so on, that are referred to from the main content of the document but that could, without affecting the flow of the document, be moved away from that primary content, such as to the side of the page, to dedicated pages, or to an appendix.
    footer
    Another common markup and page design pattern is a page footer, which typically contains fine-print content such as copyright notices, privacy policies, contact details, and so on. As you might guess, HTML5 introduces a footer element for this kind of content. Just as headers can be used in places other than the top of a document, footers don’t appear only at a document’s end—they may appear at the end of sections or articles as well. Blog posts often conclude with details such as the author’s name, the date and time of publication, tags for the post, and so on, and in HTML can all be sensibly marked up in a footer element.
    Footers also need not appear at the very end of their containing element—for example, in a blog post or article, they might be followed by comments. For some time, the HTML5 specification stated that footer elements could not contain headings, header elements, sections, or other footers, which was something of a problem, since many web page footers include detailed content structures. Happily, these restrictions have been lifted in the current and (we hope) final draft of HTML5.

    New Selectors

    One key to true web development proficiency is the intelligent use of CSS selectors. In Chapter 4 of this book, we looked at selectors such as the descendant and child selectors—selectors often underutilized or ignored by developers but which provide tremendous power when used with care. These selectors can be particularly useful when the HTML for a particular page is off-limits—for example, when the markup is generated by a CMS or other application. CSS3 provides even more powerful and finely tuned selectors that are already widely supported in browsers, even though the CSS3 Selectors module is still a candidate recommendation rather than a final, published standard. All current, popular browsers except for Internet Explorer 8 and its ancestors support most or all CSS3 selectors. We can, therefore, use CSS3 selectors today, though we must take care to ensure that our sites are still useful when viewed in Internet Explorer.
    In the following pages, we’ll look at a number of CSS3 selectors that can be useful in common development situations and which can be used for progressive enhancement. In the next chapter, we’ll follow up by looking at new properties in CSS3.
    Sticky Note
    There are a number of JavaScript libraries, such as Dean Edward’s IE7 (dean.edwards.name/IE7) and John Resig’s Sizzle (sizzlejs.com/), that provide ways in which you can use CSS3 selectors with Internet Explorer 6 and upwards. These libraries do, of course, require users to have JavaScript enabled in their browsers.

    Structural Pseudo Element Selectors

    As we saw in earlier chapters, a good understanding of descendant and child selectors can help alleviate the symptoms of “id-itis” and “class-itis,” ailments characterized by specifying class and id values for elements in an HTML document solely for the purpose of styling those elements. CSS3 provides even more fine-grained selectors for selecting elements based on the structure of a document than its predecessors do. For example, we might want to select every other row of a table, or only the first paragraph inside each parent element, or only the last item in a list. Structural pseudo element selectors in CSS3 give us the ability to do precisely these things.

    Document Structure

    We saw earlier that we can think of the structure of an HTML document as a tree—a little like a family tree, though with only a single parent per element. Perhaps a better analogy is the classic “tree of life” way of imagining evolution. At the top of the tree is the HTML element: the root element of the document. Every other element:
    • Always has exactly one parent element—for example, the body and head elements have the HTML element as their parent.
    • May have one or more child elements (elements contained directly within them)—for instance, the body and head elements are children of the HTML element.
    • May have one or more sibling elements (elements that share a parent)—the body and head elements, for example, are siblings, as they have the same parent: the HTML element.
    • May have descendent elements (child elements of an element’s child, or an element’s child’s child, and so on)—for example, every element in an HTML document is a descendent element of the HTML element, and all headings, paragraphs, links, and so on, are descendants of the body element.

    first-child

    In print design, the first paragraph is often styled differently from subsequent paragraphs in a chapter. It’s not hard to style a web page using CSS in this way by applying a class value to such paragraphs. For example, using a little of the HTML5 we picked up in the last chapter, we might do the following:

    It is a truth universally

    acknowledged, that a single man in possession of a good
    fortune must be in want of a wife.

    However little known the feelings or views of such a

    man...
    Now, in the example of a classic such as Pride and Prejudice it is rather unlikely that the first paragraph of a chapter might need moving elsewhere, but many other kinds of documents are far more dynamic—articles in the process of being edited, for example, or blog posts, or developing news stories. As a consequence, during the development or maintenance of a site, a paragraph might easily be copied elsewhere with the first-paragraph class intact, which would mean that the new “first” paragraph wouldn’t be styled correctly. In cases like this, it would make a lot more sense to apply a style based on an element’s place in the structure of the document. This is a far less fragile solution than marking up the document with classes, and the first-child selector is designed for precisely this kind of situation.
    Syntax
    Using the first-child selector is very straightforward. We simply append first-child to a selector that identifies the element we wish to select. For example, p:first-child selects any paragraph that is the first child of its parent element. We might use this selector to, for example, make the text of first paragraphs bigger than following paragraphs, using a rule that looks like this:
    p:first-child {
    font-size: 1.1em;
    }
    Note that this example selects all paragraphs that are the first child of their parent elements, not the first child of all p elements. (You can think of the first-child selector as being similar to a dynamic selector like a:hover, except that instead of selecting an element when it is in the hover state, it selects an element when it is the first child of its parent element.) Note also that if we hadn’t specified any element before the first colon in this example, this rule would have selected all elements that are the first child of an element. We’re unlikely to want to indiscriminately select all first child elements, but if we needed to do so, that’s how we’d do it.
    We can also append first-child to other selectors. For example, we can select any element with a class of “chapter” that is also the first child of its parent element, like so: .chapter:first-child. We can also combine first-child selectors with, for example, descendant selectors, thus selecting only paragraphs that are the first child of section elements with the class “chapter.” Here’s what that looks like:
    section.chapter p:first-child {
    font-size: 1.1em;
    }

    first-of-type

    Now, the preceding example may seem a little artificial, because you’d probably expect a section element to contain a heading that comes before the chapter’s contents. A more realistic example might look like this:

    Chapter 1

    It is a truth universally

    acknowledged, that a single man in possession of a good
    fortune must be in want of a wife.

    However little known the feelings or views of such a

    man...
    In this case, there is no element that matches the selector p:first-child, because the first paragraph in the section is preceded by a heading. If we want to style the first paragraph element of every section that has chapter as its class, we’ll have to turn elsewhere. CSS3 does offer a more general selector than first-child: the nth-child selector works in a similar way, but although we’ll examine this selector in detail shortly, it’s still not the best match for this situation. If, for example, we used nth-child to select paragraphs that were the second child of their parent elements, we would still have to rely on a stable document structure. If one or more chapter sections had a different structure, or if we changed the whole document’s structure during development, our solution would need to be changed once more.
    Less fragile is another CSS3 structural selector, first-of-type. This selector allows us to select an element when it is the first instance of the specified type of element within its parent element. In this case, first-of-type is the selector we want, as it will allow us to select only the first paragraph inside an element, whether that paragraph is preceded by other elements (like headers) or not. Our rule will look something like this:
    section.chapter>p:first-of-type {
    font-size: 1.1em;
    }
    This is a much more robust solution than adding class to the markup or relying on a specific document structure. If we move a paragraph elsewhere in a section or document, or if the structure of the parent element’s content changes, our solution will still work. And unlike class- and id-based solutions, the first-of-type selector won’t require us to touch the document’s HTML at all. Looking for the least fragile selector pays long-term dividends in the form of easier code maintenance and greater reliability.
    How can we decide whether a solution is fragile or robust? It’s more an art than a science, but fragile solutions will tend to be inflexible, to rely on a specific document structure, or to require that we change the document’s markup to accommodate styles, usually by adding class or id values. Robust solutions often allow us to select elements based on characteristics that don’t require a specific, rigid document structure. CSS3 provides sophisticated selectors, and it pays to consider them before falling back on methods like using class and id for styling. Anytime you find yourself changing the markup of a document to accommodate CSS, alarm bells should ring. We have more appropriate tools than the hammer for adding to our markup, and if you do alter markup, it should be as a last resort.
    As is the case with all CSS3 features, we should use these selectors to progressively enhance a page’s presentation. In the preceding example, there’s no great loss for the users of browsers that don’t support these selectors—the only thing those users will miss is a slight change in type size for the first paragraph of each chapter.

    last-child

    The selectors we’ve seen so far select elements based on their order beginning with the first child of the parent element and counting forward, but we can also select elements based on their order beginning with the last child and counting backward. Just as first-child selects an element when it is the first child of its parent, last-child selects an element when it is the last child of its parent element. Similarly, last-of-type selects an element when it is, for example, the last paragraph inside its parent element.
    Such selectors are useful for selecting, say, the last paragraph within a chapter section, perhaps in order to add additional margin space, or a border. The following example applies the solid thin black border to paragraphs that are the last child of a section with the class chapter:
    section.chapter p:last-child {
    border-bottom: solid thin black;
    }
    More robust, however, is the last-of-type selector. If the structure of our section changes such that an element other than a paragraph becomes the last element, the last paragraph of the chapter will still be selected—and thus still have a border—if we use last-of-type in our CSS rule:
    section.chapter p:last-of-type {
    border-bottom: solid thin black;
    }
    So far, we’ve been selecting specific, individual children of an element, but we can also select groups of elements that meet specific structural criteria within an element. We’ll turn to these selectors next.

    nth-child

    One of the most common ways of styling data tables, both in print and on the web, is to alternate the background colors of rows of data—a technique sometimes referred to as zebra striping. Typically, zebra stripes are implemented in HTML and CSS by applying a class such as odd or even to every other row in the HTML markup, then using a class selector to apply a background color to odd, even, or both classes of row. This method violates our rule of changing markup as little as possible for the purposes of styling, but until CSS3, there was no other way—short of using JavaScript—to implement zebra stripes without markup changes. As you might guess, CSS3 provides a selector that solves our problem.
    CSS3 introduces the nth-child selector, which selects an element when it is the 3rd, 17th, or any other specified child of an element. We need a selector that will allow us to select every other row in a table, and luckily, we can use nth-child to do this in several ways.
    In addition to using nth-child with numbers such as 1 or 27, we can use two keywords: odd and even. As you might guess tr:nth-child(odd) selects every odd-numbered table row, and tr:nth-child(even) selects every even-numbered row. We might use the following rule:
    tr:nth-child(odd) {
    background-color: #ededed;
    }
    ...which would produce a table that looks something like this:
    12.4. Zebra striping a table with nth-child

    We could also specify two alternating background colors by using both odd and even nth-child selectors:
    tr:nth-child(odd) {
    background-color: #d4f128;
    }
    tr:nth-child(even) {
    background-color: #e0f64c;
    }
    ...which would produce a table that looks something like this:
    12.5. Two-color zebra striping in a table using nth-child
    But what if we wanted to use three different background colors? This is where another feature of CSS3 structural selectors becomes useful. We can use a formulation like 2n, 3n+1, or 5n+2 to select groups of child elements, based on their position within their parent element. For example, tr:nth-child(2n) selects all the even children of an element, and tr:nth-child(2n+1) selects every odd table row. You can think of n as a variable that is replaced with every integer from 0 on. So tr:nth-child(2n) will select these rows:
    • tr:nth-child(0)—(2*0)
    • tr:nth-child(2)—(2*1)
    • tr:nth-child(4)—(2*2)
    • tr:nth-child(6)—(2*3)
    ...and so on. If a table had 1,000 rows, the 1000th row would be selected by this selector, because 1,000=2*500.
    The selector tr:nth-child(2n+1), on the other hand, selects all the odd children of an element:
    • tr:nth-child(1)—(2*0+1)
    • tr:nth-child(3)—(2*1+1)
    • tr:nth-child(5)—(2*2+1)
    • tr:nth-child(7)—(2*3+1)
    The 999th row of a thousand-row table would be selected by this selector, because 999=2*499+1.
    We can also use nth-child selectors to select, for example, every third element (tr:nth-child(3n)), the element that comes before every fifth element (tr:nth-child(5n-1)), and so on. Let’s see how can we use these selectors to give three different background colors to a table’s rows.
    We’ll create one selector to select every third element, one to select every third element plus one, and one to select every third element plus two. The following three selectors will do the trick:
    • tr:nth-child(3n)—selects every third element
    • tr:nth-child(3n+1)—selects the first element after every third element
    • tr:nth-child(3n+2)—selects the second element after every third element
    We can now apply three different background colors, repeated indefinitely, with the following CSS:
    tr:nth-child(3n) {
    background-color: #94239f;
    }
    tr:nth-child(3n+1) {
    background-color: #bb46c9;
    }
    tr:nth-child(3n+2) {
    background-color: #bf69cc;
    }
    12.6. Alternating three-color stripes in a table with nth-child
    To get a sense of just how sophisticated these selectors can be, let’s take a look at a real-world example [12.7].
    12.7. Styling a table with first-of-type and nth-of-type, as displayed in Safari 4
    As with zebra-striped table rows, before CSS3 selectors became available, we’d have had to use classes to style the various td elements in figure 12.7 with different background colors. Using CSS3 selectors, we can simply select the first td element in a row and give it a reddish background, select the second td element in a row and give it a blue background, and select the third td element and give it a grey background. Our CSS rules would look like this:
    td:first-of-type{
    background-color: rgb(255,0,0);
    }
    td:nth-of-type(2){
    background-color: rgb(0,64,128);
    }
    td:nth-of-type(3){
    background-color: rgb(76,76,76);
    }
    td:[colspan]{
    background-color: rgb(200,200,200);
    }
    Because the td elements that span three columns (such as the registration row) are the first of their type in their row, unless we specify a different background color for these rows, they’ll also be red. So, the fourth rule, which has an attribute selector, selects td elements that have a colspan value and gives these elements a lighter grey background. (If you need a quick refresher, check out the discussion of CSS2 attribute selectors in Chapter 4.)
    As always, we need to consider what happens if a selector is not supported by a user’s browser. In this case, the text color of the session names could be very similar to the background color of td elements, which would compromise legibility. We can rely on specificity (which we discussed in Chapter 4) to help us avoid this problem. A suffix such as nth-child increases the specificity of a selector, which means that td:nth-of-type will override any plain td selector. So, we can safely use something like the following CSS rule to allow for graceful degradation:
    td {
    background-color: rgb(0,64,128);
    }
    This rule ensures that browsers that don’t support our CSS3 selectors will give all our td elements a blue background, and browsers that do support the structural CSS3 selectors will override this rule and apply the more sophisticated styles illustrated in figure 12.7.
    It’s a little-known but useful fact that the keywords odd and even, as well as formulations like 3n+1, also work for other structural pseudo element selectors, such as nth-of-type.
    The structural selectors of CSS3 are among the most significant enhancements to CSS in this version of the language. We’ve touched on many of them here, and on some of CSS3’s extensions to the CSS2 attribute selector that we looked at in Chapter 4. We’ve also covered the most important concepts for understanding how these selectors work. You can find more resources for investigating CSS3 selectors in the resources section at the end of this book.

    target

    For a completely different new selector in CSS3, we turn to the target selector. Any web developer will be familiar with selectors such as link and hover, which along with focus, active, and visited are referred to as “dynamic”—or, to be exact, dynamic pseudo-class—selectors. The target selector is an additional dynamic selector in CSS3. It selects an element when it is the element currently being pointed to by the document’s URL. For example, if the current URL in a browser’s address bar is http://westciv.com/index.html#resources, the element

    is the current target. (Of course, documents frequently lack a current target—for example, if the current URL is http://westciv.com/index.html, there is no target element.) When the current URL is http://westciv.com/index.html#resources, the target selector p:target will select the paragraph with an id of resources. Similarly, if we use target by itself, we can select whatever element is the target of its document (if there is a target). We can also chain selectors to make the target selector more specific. In the preceding case, if we want to select only the paragraph with an id of resources when it is the target, but not to select any other targeted element, we can use this rule:

    p#resources:target.
    So, what good is this selector exactly? When we jump to a location inside a page, either from within that page or from another page, it’s often not immediately clear what (or where) the linked element is. We can use the target selector and a visual cue, such as a particular background color, to draw attention to the target of the link and help the users orient themselves within the page. We might use a rule that looks like this:
    p:target {
    border-bottom: background-color: yellow;
    }
    In this example, whenever the user follows a link—from within or from outside a document—to any specific paragraph on our page, that paragraph will be styled with a yellow background until the target URL for the page changes.
    The target selector is an example of the new features in CSS3 that are more focused on web applications than traditional web pages. In fact, there are a number of new properties specifically designed for working with web applications, some of which we’ll see in the next chapter.

    box-shadow

    The text-shadow property was part of the draft CSS2 recommendations and was implemented in Safari 1.1 back in 2003, but the ability to add shadows to an element’s box hasn’t been implemented in Safari and Firefox until recently, and is still not supported in Internet Explorer 8 and Opera 10.
    Like text-shadow, the box-shadow property specifies one or more shadow values that are applied to the element’s box outside its border, but inside its margin. No matter the size or offset of the shadow, it has no effect on the flow of the document, meaning that it won’t affect a page layout in any way. This greatly aids its use for progressive enhancement, as there is no need to take into account a shadow’s size when laying out a page (this is true of text shadows as well).
    To add a shadow around a block of text, we’d use a CSS rule like this one:
    p{
    box-shadow: .2em .2em .3em #888;
    padding: .5em;
    }
    ...which will give us a shadow like the one in figure 13.8:
    13.8. A simple box-shadow
    Or at least, such a rule will work in theory. In practice, because the CSS3 Borders and Backgrounds Module is not final at the time of writing, browsers that support this feature do so only with their vendor-specific extensions: -moz- and -webkit-. To make this work in WebKit- and Mozilla-based browsers like Firefox 3.5, we’ll need to use a rule like this one:
    p{
    -moz-box-shadow: .2em .2em .3em #888;
    -webkit-box-shadow: .2em .2em .3em #888;
    box-shadow: .2em .2em .3em #888;
    padding: .5em;
    As with text-shadow, we can add multiple shadows to etch or emboss a box, using, for example:
    box-shadow: -.1em -.1em .15em #ffffff,.1em .1em .15em #001199;
    This rule produces an effect like the one shown in figure 13.9:
    13.9. An embossed box-shadow
    Shadows in CSS3 are easy to implement and increasingly well supported. They are also backward-compatible, provided you maintain high contrast between text color and background color to ensure good legibility without text shadows. Otherwise they are an almost perfect candidate for progressively enhancing your sites.
    Compatibility
    box-shadow is supported in Safari (version 3.1 and higher) and Firefox 3.5 and higher. Internet Explorer doesn’t support the box-shadow property, but it does have its own proprietary filter mechanism that can enable various shadow and other effects. With the release of Internet Explorer 8, use of these filters becomes quite a complicated matter, and as they will almost certainly never be supported in other browsers, using these filters in new projects is something that should be very carefully considered. We’ll touch on the issue of IE filters again when we look at the opacity property.

    The Math of Rounded Corners

    How exactly does the value 1em translate into a rounded corner? For those who need to know the gruesome details, border-radius defines an ellipse for the corner. When there is a single value, the ellipse has a vertical and horizontal radius of 1em. And an ellipse with equal radii is a circle. Now, imagine the circumference of the circle aligned so that a quarter of the circle aligns with the corner of the element, as in figure 13.11.
    13.11. A border-radius with horizontal and vertical radii of 1em

    User-Agent Sniffing

    User-agent sniffing is something to avoid, for a number of reasons.
    • Client-side browser detection relies on JavaScript being enabled, and a surprising percentage of web users (five percent or more, according to www.w3schools.com/browsers/browsers_stats.asp) have JavaScript disabled, particularly in larger organizations and in the financial sector.
    • Browsers lie. Because so many developers have used this technique badly in the past, thus effectively excluding or downgrading the experience of users of unsupported browsers (even if their browsers could cope perfectly well with the site), many browsers spoof their identity, typically pretending to be Internet Explorer. As a consequence, determining the actual identity of a browser can be very tricky.
    • Browsers improve. Just because a version of a browser did not support a feature, or otherwise failed to display your site well, this does not mean that it always will. Using browser detection means keeping track of an ever more complicated matrix of browsers and versions over time. And that’s without beginning to worry about mobile devices, gaming machines, TVs, eBook readers, web-ready refrigerators, and so on.

    Media Queries

    As we saw in Chapter 4, HTML has supported the ability to link to different style sheets based on the media type of the display (Screen, Print, Handheld, Projector, TV, and so on) since version 4. It was a good idea in theory, but not widely used in practice, largely because with the exception of the Print media type, the Projection media type in Opera, and a small number of mobile browsers with the Handheld media type, browsers haven’t really supported the technology.
    CSS3 introduces a much more sophisticated, flexible mechanism for targeting different media according to such features of a device as its width, height, orientation (portrait or landscape), and resolution. The media query mechanism is based on the same concepts and syntax as HTML 4 media types, and has been cleverly designed so as to be backward compatible with today’s browsers.
    It’s important to understand how this differs from browser-focused approaches to compatibility we’ve seen in earlier chapters. With media queries, we don’t target specific browsers. Rather, we tailor visual designs for a given media type, regardless of the browser being used to display the page. With this method, we can take into account small screen sizes in some devices, high-resolution screens in others, low-resolution screens in still others, and so on. We can even design for combinations of these features—for example, we might tailor a style sheet specifically for small, high-resolution, monochrome screens.

    How Yahoo Grades Browsers

    Yahoo Developer Network, home to some of the industry’s most thoughtful and influential web developers and many valuable open source projects like the Yahoo User Interface Library (YUI), has a “graded browser” approach, detailed at their development site: developer.yahoo.com/yui/articles/gbs.
    They have three levels of support:
    • C Grade: Browsers to which they deliver only semantic HTML—with no CSS or JavaScript delivered. About 3% of their visitors receive “C Grade” pages.
    • A Grade: These receive the full features of the site, delivered via HTML, CSS, and JavaScript. They claim 96% of site visitors receive this level of support.
    • X Grade: About 1% of browsers are not known to be either A or C Grade, due to their rarity. They are treated as A Grade.
    Here’s how media queries work: rather than simply specifying a targeted type of media from a limited predefined set (as in HTML 4 and CSS2), CSS3 media queries allow you to specify the characteristics of the device you are targeting. For example, you might want a specific style sheet for devices with a maximum screen width of 800px × 600px, that aren’t handheld devices, or one style sheet for printing to color printers, and another for printing to black-and-white printers.
    In addition to the familiar HTML 4 media types, such as Print, Screen, Handheld, and so on, CSS3 media queries introduce a number of media features including:
    • width: the width of the viewport—the viewport is typically the window, but for some devices, such as the iPhone (which has no windows), it’s the device width
    • height: the height of the viewport (see above)
    • device-width: the width of the entire screen—or in the case of print, the page); for devices like the iPhone, this will be the same as the width
    • device-height: the height of the device or page
    • resolution: the pixel density of the device—for example, the typical resolution for common operating systems is 72dpi for the Mac OS, 96dpi for Windows, 160dpi for the iPhone, and 163dpi for the iPod touch
    • color: the number of bits per color component (the value will be 0 for monochrome devices)
    • monochrome: the number of grayscale bits for the device (the value will be 0 for color devices)
    CSS3 media queries also include logical operators like and, not, and or, and the prefixes min- and max-. The media features, along with these operators, let us form expressions that narrow the scope of the HTML 4 media types. An example media query might be:
    (max-width: 600px) and (max-height: 800px)
    An expression is contained in brackets, and each expression is either true or false. A device with a width of 600px and a height of 900px won’t be targeted by the media query in the example above, because while it matches the first expression, it doesn’t match the second.

    Using Media Queries

    Like media types in HTML 4 and CSS2, media queries are used with either @media statements, or as the value of a media attribute of a link element in the head of an HTML document. In the media attribute or @media statement, we specify the criteria we want the media to meet in order for the @media statement or linked style sheet to be used.
    For example, we might want a style sheet to be served only when a page is to be printed in color. For this example, we’d use a statement like this:
    @media print and (color) {
    ...
    }
    The preceding example tells a device to use only the @media statement for printed media, and only for color devices.
    Similarly, if we want a linked style sheet to be used only when the window is greater than 800px wide, we can use the following:
    And if you wanted to use a linked style sheet only when the device window is less than 800px wide, you could use this:
    Media queries are cleverly designed so that older browsers can still use them to an extent. A browser which only recognizes the older keywords like “print” and “all” will recognize the first word it sees—for example, “screen”—but once it sees a keyword like “and,” it will ignore the rest of the statement. This allows us to use media queries for newer devices that recognize them, and older ones that don’t. Browsers that don’t support CSS3 media queries, but do support older style media statements will see @media print and (color), and treat it like a standard print style sheet.
    We can even use media queries to specifically target a device, such as the iPhone, by targeting its particular features. For example, this statement:
    @media only (device-width: 480px) {
    ...
    }
    targets the iPhone in landscape mode—and other devices with a device width of exactly 480px—while this:
    @media only (device-width: 320px) {
    ...
    }
    targets devices with a width of 320px, like the iPhone in portrait mode.
    Why the only, you ask? Well, all is the default value for a media type, so if we simply use this statement:
    @media (device-width: 320px) {
    ...
    }
    then older browsers might use this statement, seeing it as:
    @media all and (device-width: 320px) {
    ...
    }
    Similarly, we can hide a style sheet from a device with a maximum device-width of more than 480px (including, of course, the iPhone) using this code:
    @media only (device-width: 481px) {
    ...
    }
    We can also make our media queries even more specific. For example, if we wanted to specify only devices with a device width of exactly 480px in portrait mode, we could use:
    @media only (device-width: 480px) and
    (orientation: landscape) {
    ...
    }
    To bring all these examples together, media queries take the format of a comma-separated list of entries. Entries may be media types (like Print and TV, and so on, specified in CSS2 and HTML 4) or expressions comprising an optional media type (such as screen) plus a logical statement about the features the device must support to use this style sheet or @media rule (such as max-width: 480px). These logical expressions are contained within brackets, as in the preceding example:
    (device-width: 480px) and (orientation: landscape)
    @media rules are widely supported, and CSS3 media queries are currently supported by Safari 3 and higher (including Mobile Safari in the iPod touch and iPhone), Opera 9.5, and Firefox 3.5 or higher.
    Many of these features, like device-width, resolution, or color depth might seem to be fixed for each device, but that’s not necessarily true. Rotate a device like the Palm Pre or iPhone, and it changes page orientation from landscape to portrait—or vice versa—and takes on a new device-width at the same time. Similarly, although it’s more uncommon for users to change the resolution on a device, such as an external monitor, doing so will still change the device-width, even while a page is displaying. Even moving a browser window from one screen to another in a multi-monitor setup will almost certainly change the resolution, and quite possibly other features as well. And, of course, the width of a page can be changed on a desktop browser by resizing the window.
    Given this inherent instability in device characteristics, the question arises: if features change while a page is displaying, when will the browser redraw the page using the new value for the media queries? The specification is silent on this issue, so it’s up to the browser implementers to make a decision. Firefox 3.5 and Opera 10 beta generally redraw a page when the window is resized, regardless of which features are associated with a media query. Safari seems to redraw a page after the window is resized only when width is part of the media query—if other features (like resolution or device width) are part of a media query but width is not, Safari only redraws the page on reload. So we can’t rely on the browser to redraw the page based on a media query if features of the device change after the page is loaded. The sole exception seems to be device-width, which prompts Safari, Firefox, and Opera to redraw the page based on the media query when the window is resized.

    Compatibility

    CSS3 media queries are widely supported in Safari 3.1 and higher, Opera 9 and higher, and Firefox 3.5 and higher. Not every media feature of CSS3 media queries is supported in each of these browsers.

    But Is This Really Any Better Than User-Agent Sniffing?

    You may be wondering, Just how are these complicated-looking media queries any better than user-agent sniffing? Happily, the answer is simple. Whereas user-agent sniffing targets specific browsers or browser versions, media queries target specific media and—more importantly—device characteristics, regardless of what browser displays the page. After all, even today, Opera might be running on a laptop, a mobile device, the Wii, or a television. A WebKit-based browser might be running on a mobile device or laptop, as might Internet Explorer and Firefox. All other problems aside, user-agent sniffing just isn’t up to coping with the huge variety of user agents on the web.
    Furthermore, whereas user-agent sniffing is often used to work around buggy CSS support in specific browsers, media queries are used to deliver the appropriate style sheet to any browser based on the medium in use. This means that any browser that supports media queries will be able to use a style sheet specified for, say, color printing on US Letter pages, or for windows wider than 1024px, where the minimum resolution is 72dpi. There’s no need to continually update your matrix of browser support, since you’re not targeting browsers. As new browsers and browser versions are released, there’ll be no need to change anything to support them—your media queries will just...work. And, as we’ve seen, we can use media queries now with browsers that already support HTML 4 media-based linking and CSS2 @media rules, even if they don’t yet support features in media queries.

    These are notes I made after reading this book. See more book notes

    Just to let you know, this page was last updated Friday, Mar 29 24