The Book of CSS3: A Developer’s Guide to the Future of Web Design by Peter Gasston, PDF, EPUB, 1593272863

The Book of CSS3: A Developer’s Guide to the Future of Web Design by Peter Gasston

  • Print Length: 304 Pages
  • Publisher: No Starch Press
  • Publication Date: May 15, 2011
  • Language: English
  • ASIN: B005011IU0
  • ISBN-10: 1593272863
  • ISBN-13: 978-1593272869
  • File Format: PDF, EPUB

 

”Preview”

Foreword

CSS3 used to be a topic for people who were in it for the long haul. Back in 2006, I started CSS3.info, and Peter joined me in writing posts about the development of the standard and real-life examples of what it looked like in browsers. Although I started the site, Peter was always the most prolific writer, and it’s only fitting that while I wrote this foreword, he wrote the book.

CSS3 has finally gone mainstream. With the new age of browsers (such as Firefox 4, Google Chrome, and Internet Explorer 9), we as a web design community are finally getting the power and flexibility we’ve been waiting for. We can now manage media queries for different browsers, have smarter background images, and handle fonts in a way that doesn’t drive us nuts.

If you plan on using CSS3, this book is the most hands-on guide you’ll find. It shows you what works and what doesn’t, and no caveat is forgotten. Peter even provides a clear explanation for how transitions and transformations work. This is no small feat; as you’ll see for yourself when reading those chapters, the matrix functions are not for every user. Luckily you won’t have to use those when you’re taking advantage of the other—far more accessible—functions in CSS3.

More is to come: CSS3 is an ever-expanding standard that promises to help web designers do great things. I, for one, am very curious about where it will lead us. For now, though, this book is all you need to start uncovering the treasures within CSS3.

Joost de Valk

CEO and Founder, Yoast.com

Preface

This book is the culmination of five years’ writing about CSS3, both on the Web and in print. The browser and CSS landscape has changed a lot in that short time and continues to change today, bringing new features and implementations at a rate that’s difficult to keep up with. The CSS3 specification is written in (often dense) technical language that’s intended for implementers rather than end users, and my intent in writing this book was to bridge the gap between specification and web developer.

I wrote about the CSS properties in the earlier chapters of this book with certainty, because they’re well implemented and used on a daily basis. As I progressed through the book, I was able to learn more from experimentation and the work of pioneers and early adopters. By the final few chapters I had to rely on interpretation of the CSS3 specification to explain how future properties will behave. I would hope that there are few mistakes, but I accept that any that exist are based on my own misunderstanding.

In addition to the CSS3 specification itself, an invaluable resource was the Mozilla Developer Network (https://developer.mozilla.org/), a peerless collection of articles about anything web related—not least CSS—which is all the more amazing for being written by volunteers. The text used in many of the code examples is taken from books in the public domain which are available at http://www.gutenberg.org/. All images in the book that are not my own creations are credited in the relevant chapters.

This book would not have been possible without the guidance of the team at No Starch Press, especially Serena Yang and my editor, Keith Fancher, who made me write more clearly and helped me transition from blogger to author. I’d also like to thank Joost de Valk, who not only acted as my technical editor but also gave me my first opportunity to write about CSS3 when he created the website http://www.css3.info/ five years ago.

I’d also like to thank my colleagues at Preloaded and Poke for their support and encouragement, everyone at the many London web community meet-ups, my mum for teaching me the value of hard work, and my dad for buying me my first computer some almost thirty years ago—I promised I’d pay him back one day, and hopefully this book will go some way toward that debt.

Introduction

Let me tell you a little about who I think you are: You’re a web professional who’s been hand-coding HTML and CSS for a few years; you’re pretty comfortable with creating complex layouts, and you know not only your div from your span but also your bold from your strong; you’ve read a little about CSS3 and may even have started experimenting with some of its more decorative features like rounded corners, but you want to gain a deeper understanding of the fundamentals.

The Book of CSS3 helps you leverage the excellent knowledge you have of CSS2.1 in order to make learning CSS3 easier. I won’t explain the fundamentals of CSS (except for the occasional reminder) as I assume you know them already. I won’t talk you through step-by-step demonstrations of using CSS to make a listed navigation or an image gallery because I assume you can apply the examples in this book to anything you want to build on your own.

What I aim to do with this book is introduce you to what you can do with CSS3 now and what you’ll be able to do with it in the future. I want to take the dense technical language of the CSS3 specification and translate it into language that’s plain and practical.

In short, I want to give you some new tools for your toolkit and let you make cool stuff with them.

The Scope of This Book

CSS can be used across many types of media; almost any device that’s capable of displaying HTML or XML can also display CSS rules, albeit in a limited form sometimes. CSS3 has two modules devoted exclusively to paged media, such as PDF or printed materials, and also supports braille, handheld mobile devices (i.e., cellphones rather than smartphones), teletypes, and televisions. The range and breadth of possibilities is so vast that I can’t cover them all.

What this book focuses on is CSS for the computer screen. All of the demonstrations were written for (and tested in) the most common desktop browsers, and they’re optimized for users of desktop and laptop computers. Although many of the new features in this book will still work if you’re developing for other devices—especially smartphones and tablets—I make no guarantees or assurances that everything will display exactly as shown in the examples contained herein.

A Quick Note About Browsers and Platforms

I wrote the majority of this book—and, therefore, the majority of the demonstrations and examples—on a computer running Ubuntu 10.04 with Firefox, Chrome, and Opera installed. Other portions were written on a MacBook Pro with Safari installed. Tests for Internet Explorer were performed using Windows 7. (The exact versions of all of the browsers used can be found in the introduction to Appendix A.)

Throughout this book, I mostly make reference to Firefox and WebKit. The perspicacious among you will notice that Firefox is a type of browser, whereas WebKit is a type of layout engine, and wonder why I don’t refer to the Gecko layout engine used by Firefox or to any WebKit-based browser by name.

The reason is quite simple: Firefox is clearly the preeminent Gecko-based browser, whereas Chrome and Safari dispute the eminence of WebKit between them. As a simple space-saving exercise, I will say “WebKit” rather than “Chrome and Safari.” The exception to this rule is when a specific feature or syntax only appears in one type of WebKit browser—such as hardware-accelerated 3D transformations in Safari—in which case, I refer to the name of the browser in question.

The Appendices and Further Resources

At the end of this book are two appendices containing further information beyond what’s discussed in the various chapters. The first provides a quick reference guide to the implementation of the features included in this book across the different versions of browsers, and the second is a list of online resources, useful tools, and interesting demonstrations.

A website accompanies this book at http://www.thebookofcss3.com/; here I’ll keep updated versions of both appendices and all of the examples and demonstrations used in this book. God forbid I should make any mistakes, but on the super-rare possibility that I do, I’ll also keep a full list of errata.

In addition to the accompanying website, I write more about CSS3 (and other emerging web technologies) at my blog, Broken Links (http://www.broken-links.com/). Feel free to comment or get in touch with me through either of these websites.

Chapter 1. Introducing CSS3

In this first chapter, I’ll introduce a new CSS3 property in order to demonstrate the code conventions used in this book, but before getting to that, I’ll explain a little about the history of CSS3. Obviously, you don’t need to know its history in order to use CSS3, but I think having some context about the current state of CSS3 is important.

CSS3 is a specification in flux. Some parts of the spec are considered stable and have been well implemented in modern browsers; other parts should be considered experimental and have been partially implemented to varying degrees; yet others are still theoretical proposals and have not been implemented at all. Some browsers have created their own CSS properties that don’t belong in any CSS3 specification and perhaps never will.

All of this means that knowing how the standardization process works and the levels of implementation for each new property is vital to understanding how you can use CSS3 in your code both now and in the future.

What CSS3 Is and How It Came to Be

First, I want to discuss what CSS3 is—and isn’t—and the form it takes. The W3C’s approach to CSS3 is quite different from its approach to CSS2, so this overview should help you understand how and when you can use CSS3 and why it has such varied implementation across different browsers.

A Brief History of CSS3

The version of CSS in current use is CSS2.1, a revision of the CSS2 specification that was originally published in 1997. Despite ongoing development and review since that time, many people are surprised to learn that CSS2 hasn’t actually become an “official” recommendation of the W3C yet. (I’ll talk more about the recommendation process shortly.) More surprising still is the fact that Internet Explorer 8 (IE8)—released in 2009—lays claim to being the first browser to support the entire CSS2.1 specification fully.

In the last few years, the talk has been about the new revision—CSS3. I say “new,” but in fact work on CSS3 began back in 1998, the year after CSS2 was published. Browser implementation of CSS2 continued to be so frustratingly inconsistent, however, that the W3C decided to halt work on any new revision and work on CSS2.1 instead, standardizing the way CSS had been implemented in the real world. In 2005, all of the CSS3 modules were moved back to draft status, and the editing and review process began all over again.

For many years, Internet Explorer dominated the ever-expanding market of Internet users and showed no sign of wanting to implement CSS3. But int he last few years, a whole new range of browsers has appeared to compete for users, and this plethora of choice has led to a features arms race. One beneficiary of that arms race has been CSS3. Each of the browsers wants to offer developers and users the latest in web technologies, and with the CSS3 spec already mostly written, implementing and even adding new features has been a no-brainer.

So here we are today, with the CSS3 specification under active development, a broad range of browsers working on implementing it, and a community of interested developers building with it, studying it, and writing about it. A healthy situation, and one we couldn’t have foreseen just a few years ago.

CSS3 Is Modular

Being the default styling language for every markup-based document in the world is an enormous undertaking, and the W3C was aware that it would take many years to come to fruition. W3C members, conscious that they didn’t want to hold up some of the more obvious, in-demand features while they were considering and debating some of the more esoteric ones, made the decision to split CSS3 into various modules. Each of the modules could then be worked on by different authors at different paces, and the implementation and recommendation process—which I’ll discuss shortly—could be staggered.

This is why, instead of a single, monolithic CSS3 specification document, you have CSS3 Basic User Interface Module, Selectors Level 3, Media Queries, and so on. Some of these modules are revisions of CSS2.1, and some are newly created, but all fall under the banner of CSS3.

One of the few things I find irritating (I’m an easy-going guy) is that on many blogs you’ll hear people complaining, “I want to use CSS3, but it won’t be ready for years.” This is nonsense; some modules of CSS3 already have very stable implementation in all modern browsers, and many more are just months away from prime time. If you want to wait until all of the modules are 100 percent implemented across every browser in existence, you’ll be waiting a long time.

But CSS3 is here, and some of it is ready to use right now—you just have to be mindful about how you use it.

Module Status and the Recommendation Process

As I move through this book and discuss each of the different modules, I’ll also refer to that module’s status. Status is set by the W3C, and it indicates the module’s progress through the recommendation process; note, however, that status is not necessarily an indication of a module’s degree of implementation in any browser.

When a proposed document is first accepted as part of CSS3, its status is designated Working Draft. This status means that the document has been published and is now ready for review by the community—in this case, the community being browser makers, working groups, and other interested parties. A document may stay as a Working Draft for a long period, undergoing many revisions. Not all documents make it past this status level, and a document may return to this status on many occasions.

Before a document can progress from a Working Draft, its status changes to Last Call. This means the review period is about to close and usually indicates the document is ready to progress to the next level.

That next level is Candidate Recommendation, which means the W3C is satisfied that the document makes sense, that the latest reviews have found no significant problems, and that all technical requirements have been satisfied. At this point, browser makers may begin to implement the properties in the document to gather real-world feedback.

When two or more browsers have implemented the properties in the same way and if no serious technical issues have come to light, the document may progress to being a Proposed Recommendation. This status means that the proposal is now mature and implemented and ready to be endorsed by the W3C Advisory Committee. When this endorsement has been granted, the proposal becomes a Recommendation.

To reiterate what I briefly touched on before, the recommendation process and the implementation process do not always work in the same way. For example, later on in this book, I’ll introduce a set of modules proposed by the WebKit team a few years ago, which includes 2D Transformations (Chapter 12). Despite the proposal still having Working Draft status, the properties are already well implemented in Firefox, Opera, and WebKit.

As I mentioned earlier in this chapter, not even CSS2.1—which we’ve all been using for many years now—has reached full Recommendation status. Although CSS2.1 is as good as finished, a few matters of syntax and phrasing still need to be resolved. Obviously, that hasn’t stopped the browsers from implementing it fully and moving on to CSS3.

As a result, I’ve written this book in a loose order of implementation, rather than recommendation status. Earlier chapters discuss features that have full implementation across all browsers (or should by the time this book is released), later chapters cover features that are implemented in some browsers only—often with browser-specific prefixes—and chapters toward the end of the book deal with potential, speculative, or partial implementations of properties.

CSS3 Is Not HTML5

One of the current buzzwords around the Internet is HTML5. HTML5 is, of course, a genuine (and exciting) new technology that has somehow broken out of the technical press and through to the mainstream media. Just about everywhere you turn people are discussing it. On that journey, however, its correct meaning seems to have been lost.

Before I discuss what that real meaning is, I should point out that the media are not solely responsible for obfuscating the true meaning of HTML5. Many developers are falling over themselves to make flashy “HTML5 demos”; but if you look more closely at these demos (or view their source code), more often than not you’ll find they involve few-to-no actual new HTML5 features and an awful lot of CSS3 (yes, Apple, I’m looking at you: see http://www.apple.com/html5/).

Although HTML5 will bring a lot of cool new features to the Web, CSS3 is bringing the really fancy visual stuff: rotating, scaling, and animating in two and three dimensions; dynamic and decorative text effects; drop shadows; rounded corners; and gradient fill effects. All this is possible with CSS3 (and I’ll show you how to do it all in this book).

What the media refers to as HTML5 is really that new revision of the markup language combined with CSS3, SVG, and JavaScript—what many people (myself included) prefer to call part of the Web Stack (or, Open Web Stack).

Let’s Get Started: Introducing the Syntax

With the introductions and explanations out of the way, let’s get to the meat of CSS3. Throughout this book, I use a certain syntactical convention to demonstrate each of the new rules and properties. Rather than simply describe that convention, I thought you’d find it more interesting if I explain it at the same time as I introduce the first new CSS3 property.

The property is box-sizing, which allows you to set how an element’s dimensions are calculated. As you know, an element’s total width—without including its margin—is usually calculated from its stated (or inherited) width value, plus its left and right padding, plus its border-width. Let’s take as an example the following code, which should be very familiar to you.

div {

border: 10px solid black;

padding: 10px;

width: 150px;

}

In this example, the div has a total width of 190px—150px width plus 20px padding plus 20px border. This code is fine and uncontentious when you’re using absolute values for width, but it becomes problematic when you start mixing in percentages:

div {

border: 10px solid black;

padding: 10px;

width: 15%;

}

Now the width has become a lot harder to calculate because you first need to know the width value of the parent element before you can know how much 15 percent of that is and add the pixel values. Calculations can become very complicated very quickly, making percentage-based layouts tricky to manage properly.

At this point, the box-sizing property comes in handy. With this, you can set from which part of the box model—the content itself or the border—the width of the element is calculated. So now that I’ve covered the reason for the new property’s existence, I’ll begin the demonstration with a look at its syntax, using the convention that will be standard in this book:

E { box-sizing: keyword; }

In this code example, the selector is represented with E. Of course, in HTML, this selector doesn’t exist; I’m merely using it as an indicator that any selector can be used here. In the case of the examples used at the beginning of this section, the E represents the div element.

Next, you have the property itself: box-sizing. This property is implemented in all major browsers but with browser-specific prefixes in some: In Firefox, the property uses the -moz- prefix—that is, the property is -moz-box-sizing; and in WebKit, it has the -webkit- prefix, so it would be -webkit-box-sizing. Rather than obfuscate the code with all of the different prefixes, I use only the correct property name according to the CSS3 specification and note in the text when a prefix is required, as I’ve just done here. (I’ll explain more about these browser prefixes in the following section.)

The value of the declaration is the word keyword, but again the value is only an indicator; it represents a range of possible values. For box-sizing the permitted values are border-box and content-box.

With all of that in mind, if you used actual values, one possible real-world application of this new property might look like this:

div { box-sizing: content-box; }

So what does this property do? As mentioned, box-sizing sets the point of the element from which the width is calculated. The default is content-box, which means the stated width of the element applies to the content, and the padding and border values are added on as usual.

A value of border-box means the stated width value is the total width of the content, the padding, and the border—in other words, the entire box (without the margin). To illustrate this, let’s return to the previous example code and add the property:

div {

border: 10px solid black;

box-sizing: border-box;

padding: 10px;

width: 150px;

}

Now the width of 150px includes the padding and border. As each of those is 10px on both sides, the content of the div element has a calculated width of 110px—150px minus the 20px padding and 20px border.

Before illustrating the difference between the two values visually, I should also mention that Firefox (with its -moz-box-sizing property) has an extra permitted value that other browsers don’t: padding-box. Using this value, the width of the element is calculated from its padding and its content and doesn’t include the element’s border. Here’s an example:

div {

border: 10px solid black;

-moz-box-sizing: padding-box;

padding: 10px;

width: 150px;

}

In this code, the 150px width includes the padding, so the width of the content itself would be 130px. You can see the difference among the values when rendered in Firefox in Figure 1-1.

Moving through the examples from left to right: The first div has the default content-box value for box-sizing, so the stated width—150px—is the width of the content, and the border and padding are added to the content. In the second example, the value is border-box, meaning the 150px width includes the border and padding, making the content 110px wide. Finally, the div on the right uses Firefox’s own -moz-box-sizing property with the value of padding-box, so the 150px includes the content and padding but not the border, putting the content’s width at 130px.

Figure 1-1. The effects of different values on the box-sizingproperty

Please note that although I only discuss the width property in all of these examples, the exact same rules apply to an element’s height property. (You may also note that this works in exactly the same way as a browser that is put into “quirks” mode.)

NOTE

If you’re a younger developer you may not remember “quirks” mode. It’s a system that emulates the incorrect way that Internet Explorer 5.5 used to lay out web pages; you can read more about it on Wikipedia (http://en.wikipedia.org/wiki/Quirks_mode).

I use the box-sizing property in a few examples throughout this book, so if the effects (and benefits) aren’t immediately apparent right now, they should become clearer as you work through the rest of the chapters.

Browser-Specific Prefixes

In the previous section, I briefly discussed using browser-specific prefixes on the box-sizing property. As CSS3 is still in a state of change and revision, you’ll see these mentioned a lot throughout the rest of this book, so I’ll take some time to talk about these in more detail.

When a module is still under active review, as much of CSS3 is, a lot is subject to change; the syntax of a property may be revised, or properties may be dropped entirely. On occasion, even the wording of the draft itself is perhaps a little nebulous and open to interpretation.

At the same time, browsers need to implement these features so we can see how they work in practice. But consider the difficulties that would occur if two separate browsers implemented the same property but interpreted it slightly differently: Your code would appear differently—perhaps radically so—in each of the browsers. To prevent this from happening, each of the different browser engines prefixes a short code to the beginning of experimental properties. Let’s imagine a property called monkeys (I’ve always wanted a monkeys property), which is brand new in the specification, and that all of the browsers have decided to implement it to see how it works. In this case, you would use the following code:

E

{

-moz-monkeys: value ; /* Firefox */

-ms-monkeys: value ; /* Internet Explorer */

-o-monkeys: value ; /* Opera */

-webkit-monkeys: value; /* WebKit */

}

The amount of repetition may seem somewhat unnecessary, but the repetition is for our own good; the last thing you want is for all the browsers to implement the monkeys property differently, leading to total chaos. (You’ll see a great example of the benefits of prefixes when I discuss gradients in Chapter 11.)

Future-Proofing Experimental CSS

Quite often people will suggest that when using prefixed, experimental CSS properties, you also add the unprefixed property at the end:

E {

-moz-monkeys: value; /* Firefox */

-ms-monkeys: value; /* Internet Explorer */

-o-monkeys: value; /* Opera */

-webkit-monkeys: value; /* WebKit */

monkeys: value;

}

The theory is that this future-proofs the code; when the property is fully implemented in the browsers, you don’t need to go back and add the property to your stylesheets. I used to agree with this technique, but now I’m not so sure. I think future-proofing is okay if more than one browser has already fully implemented the property in a compatible way, as that usually means the specification is stable. However, if the spec is still under review, then the syntax is subject to change. Adding the unprefixed property could cause problems when browsers actually implement the updated syntax—or, indeed, it may not work at all.

Some properties in this book—such as background-size in Chapter 8—are semi-implemented, which is to say they are prefixed in some browsers, but unprefixed in others. In this case, you will obviously have to use a mixture of the two states if you want to use those properties across browsers. Others—like the aforementioned gradient properties in Chapter 11—are immature, still open to review, and far from final, so you should probably not use the future-proofing method with them just yet.

Getting Started

That should be everything you need to get started with this book—except, of course, an inquisitive nature. I have a lot of ground to cover in CSS3, so I’ll move fairly quickly, but each chapter should give you the knowledge you need to build your own tests, demonstrations, and sites that take advantage of the flexibility and rich features that CSS3 provides.

We’ll begin with a look at one of the simplest—and yet potentially the most disruptive (and I mean that in a good way)—new features: Media Queries.

Chapter 2. Media Queries

Back when the World Wide Web was some thing you only accessed via a browser on your desktop or laptop, writing CSS was fairly straightforward. Although you had to consider cross-browser and cross-platform issues, at least you knew with reasonable certainty that everyone was using fundamentally similar devices to view your website. Over the last few years, however, we’ve seen an explosion of new devices for accessing the Web—from game consoles to mobile devices such as the iPhone or iPad. Presenting your content to everybody in the same way no longer makes sense when they could be viewing your website on a widescreen desktop monitor or a narrow handheld screen.

CSS has had a way to serve different styles to different media types for quite some time, using the media attribute of the link element:

<link href=”style.css” rel=”stylesheet” media=”screen”>

But using this is like wielding a pretty blunt instrument when the screen in question can be between 3.5 inches and 32 inches in size. The CSS3 solution to this problem is the Media Queries Module (http://www.w3.org/TR/css3-mediaqueries/). Media Queries extend the media types by providing a query syntax that lets you serve styles far more specifically to your user’s device, allowing a tailored experience. The description may sound quite dry, but this feature is actually one of the most revolutionary in the entire CSS3 specification. Media Queries give you the freedom to make websites that are truly device-independent and give your users the best possible experience no matter how they choose to visit your site.

The Media Queries Module has Candidate Recommendation status so is considered ready for implementation. The module is already well implemented in Firefox, WebKit, and Opera, and will be in Internet Explorer from version 9.

The Advantages of Media Queries

As a quick demonstration of the power and flexibility of Media Queries, I want to show an example of how websites can be optimized for mobile browsers without requiring a great deal of extra development.

People visiting your site on a mobile device may well struggle to use it: The text may appear too small, and zooming in means a lot of scrolling to find navigational elements; those navigational elements may involve drop-down functionality that is triggered by hovering over them, an action that often doesn’t exist on mobile devices; large images may take a long time to download over a weak data connection and use a substantial portion of your monthly bandwidth allowance. Some sites plan for this by providing mobile-friendly versions, but these generally involve a lot of development work. A subdomain has to be set up with stylesheets and HTML templates that differ from the parent site, images have to be resized to better fit small screens, and a script has to be created to detect whether a mobile browser is being used and to redirect to the mobile site accordingly. This approach can cause problems: Your script has to be kept up to date with all mobile browser versions, and maintenance often involves duplication to keep both mobile and desktop versions in sync.

Media Queries address many of these issues. For a start, they detect devices based on their attributes, so no browser-sniffing scripts are required. They allow you to target stylesheets directly for a device’s capabilities, so if a device with a small screen is detected, CSS rules will be tailored to that screen size, removing extraneous elements from the screen, serving smaller images, and making text clearer.

For example, take a look at the website of the dConstruct conference from 2010 (http://2010.dconstruct.org/), as shown in Figure 2-1.

When viewed in a desktop browser, the site features large images of the speakers, and text is displayed in columns laid out horizontally. Through the power of Media Queries, when you see the same site viewed in a narrower browser—as smartphones such as the iPhone would use—the speaker images are removed, the links to the speakers’ pages are more prominent, and all of the text on the page is moved into a single column, which is ideal for scrolling down.

Figure 2-1. The dConstruct website viewed in a desktop browser (left) and a mobile browser (right)

Of course, the Web is appearing on more than just desktop and smartphone devices, and we really need to be working toward an era of websites optimized for any device. I urge you to read Ethan Marcotte’s article, “Responsive Web Design” (http://www.alistapart.com/articles/responsive-web-design/), which provides a great introduction to this new paradigm of web design.

And if you want to see what other people have been doing with Media Queries there’s a great gallery online at http://www.mediaqueri.es/, which showcases some of the better examples of what’s possible.

Syntax

A Media Query sets a parameter (or series of parameters) that displays associated style rules if the device used to view the page has properties that match that parameter. You can use Media Queries in three ways, all of which match the different ways that CSS can be applied to a document. The first is to call an external stylesheet using the link element:

<link href=”file” rel=”stylesheet” media=”logic media and (expression)”>

The second is to call an external stylesheet using the @import directive:

@import url(‘file’) logic media and (expression);

The third is to use Media Queries in an embedded style element or in the stylesheet itself with the extended @media rule:

@media logic media and (expression) { rules }

This method is the one I’ll use throughout the rest of this chapter, as it’s clearer for demonstration purposes. Which method you use will largely depend on your own preference and the demands of your existing stylesheet structure.

Now that I’ve introduced the declaration methods, let’s explore the syntax. You should already be familiar with the media attribute—it declares the media types that the styles are applied to, just as in the HTML link tag:

<link href=”style.css” rel=”stylesheet” media=”screen, projection”>

As with the current syntax, you can use a comma-separated list to choose multiple media types.

The first new attribute for the @media rule is logic. This optional keyword can have the value of either only or not:

@media only media and (expression) { rules }

@media not media and (expression) { rules }

The only value is used if you want to hide the rule from older browsers that don’t support the syntax; for browsers that do support it, only is effectively ignored. The not value is used to negate the Media Query; you use not to apply the styles if the parameters you set are not met.

The next attribute is expression, which is where the main selection takes place. You declare expression by using the and operator and use it to set parameters beyond the media type. These parameters are known as Media Features, and they’re critical to the power of Media Queries. That being the case, let’s explore them in detail.

Media Features

Media Features are information about the device that’s being used to display the web page: its dimensions, resolution, and so on. This information is used to evaluate an expression, the result of which determines which style rules are applied. That expression could be, for example, “apply these styles only on devices that have a screen wider than 480 pixels” or “only on devices that are orientated horizontally.”

In Media Queries, most Media Feature expressions require that a value be supplied:

@media media and (feature:value) {rules}

This value is required to construct the example expressions I just mentioned. In a few cases, however, the value can be left out and just the existence of the Media Feature itself tested against:

@media media and (feature) {rules}

Expressions will become clearer as I talk through the Media Features and explain when values are required or optional.

With the syntax covered, let’s meet some of the more prominent Media Features. The ones I introduce next are the most applicable to color display screens used for accessing the Web and are the ones you’re most likely to use on a day-to-day basis. Other Media Features are available, but they’re more likely to be used for alternative devices such as TVs or fixed-grid terminals.

Width and Height

The width Media Feature describes the width of the rendering viewport of the specified media type, which, in practice, usually means the current width of the browser (including the scroll bar) for desktop operating systems. The basic syntax requires a length value:

@media media and (width:600px) { rules}

In this case, the rules are applied only to browsers that are set to be exactly 600px wide, which is probably far too specific. width also accepts one of two prefixes, however, max- and min-, which allows you to test for a minimum or maximum width:

@media media and (max-width:480px) {rules}

@media media and (min-width:640px) {rules}

The first query applies the rules in browsers that are no wider than 480px, and the second in browsers that are at least 640px wide.

Let’s look at a practical example. Here, I’ll take advantage of browser window sizes by providing a decorative header for wider windows:

@media screen and (min-width: 400px) {

h1 {

background: black url(‘landscape.jpg’) no-repeat 50% 50%;

color: white;

height: 189px;

margin-bottom: 0;

padding: 20px;

}

}

This Media Query is testing for browser windows that are at least 400px wide and applying a background image to the h1 element when that is the case. If my browser window is at least 400px wide, I see the image; if I resize it to be narrower, only a text header is shown. You can see this example illustrated in Figure 2-2.

Figure 2-2. Different style rules applied with the width Media Query

The height Media Feature works in the same way, except that it targets browsers based on their height instead of width. The syntax is the same as width and also permits using max- and min- prefixes:

@media media and (height:value) {rules}

@media media and (max-height:value) {rules}

@media media and (min-height:value) {rules}

Because of the prevalence of vertical scrolling, however, height is used much less frequently than width.

Device Width and Height

The device-width Media Feature functions in a similar way, but it describes the width of the device that is rendering the page. When dealing with web pages, the device width is the width of the screen that’s displaying the page rather than the width of the browser window. As with width and height, the basic syntax requires a length value and can be prefixed in the same way:

@media media and (device-width:1024px) {rules}

@media media and (max-device-width:320px) {rules}

@media media and (min-device-width:800px) {rules}

device-width becomes most useful when designing for mobile devices, which have smaller display areas. Using this feature, you can cater your designs to those smaller devices without having to create a whole new version of the site designed for the mobile web.

For example, I’ll optimize some content for display on two different devices. I’ll use two boxes of content that, by default, will be floated to sit next to each other on the horizontal plane. For smaller devices (I’ll use an iPhone in this example) the boxes will not be floated and, instead, will sit one on top of the other, making better use of the narrower device. Here’s the code:

.container { width: 500px; }

.container div {

float: left;

margin: 0 15px 0 0;

width: 235px;

}

@media only screen and (max-device-width: 320px) {

.container { width: auto; }

.container div {

float: none;

margin: 0;

width: auto;

}

}

By default, I have a 500px container element, with two floated div elements inside it that are 235px wide and have horizontal margins of 15px. Then I create a Media Query (using the only operator to hide it from older browsers) that applies only to devices with a maximum width of 320px (the default iPhone width). This query sets rules that remove the explicit values from the width and margin properties and prevents the boxes from floating. You can see the results in Figure 2-3. The content is more appropriately formatted for its target device, without losing any readability or requiring a special “mobile version.”

Figure 2-3. The device-width Media Query displays content differently on a desktop (left) and iPhone (right).

NOTE

iOS (iPhone, iPad, etc.) and Android devices measure device-width by the shorter pair of the four screen sides; that is, given a device with dimensions of 320×480, the device-width will be 320px, regardless of whether you’re viewing it in portrait or landscape mode.

The device-width feature also has a counterpart device-height, which operates as height does to width. Once more, device-height uses a similar syntax, also with max- and min- prefixes:

@media media and (device-height:value) {rules}

@media media and (max-device-height:value) {rules}

@media media and (min-device-height:value) {rules}

Much like height, device-height is used less frequently than device-width because vertical scrolling is easier than horizontal scrolling.

Using Media Queries in the Real World

In the examples thus far, I’ve tended to create a site that is optimized for larger browsers or devices first, with Media Queries used to provide different styles for smaller (mobile) devices. This has been useful for demonstration purposes, but in your own sites you’ll probably want to do this the other way round.

The reason for this is because of the way that some browsers load page assets, such as images, that are included in stylesheets. Some early adopters of Media Queries would write their code the way we’ve seen in my examples, using large background images and then setting a value of display: none to hide them from mobile devices. However, those background images can still be downloaded and held in the cache even though they aren’t displayed. This increases the page’s load time and can consume bandwidth allowances—neither of which is good for mobile device users without wireless connections.

A better way to create your pages is to make a basic stylesheet for your mobile audience first and then one with larger assets for desktop or tablet users that is loaded using a Media Query such as device-width:

<link href=”basic.css” rel=”stylesheet” media=”screen”>

<link href=”desktop.css” rel=”stylesheet”

media=”screen and (min-device-width: 480px)”>

When the stylesheets are separated in this way, the file desktop.css won’t be loaded for devices with a screen width of less than 480px, so none of those large assets will be downloaded in the background.

This will work for the great majority of browsers from the past few years; any really old browsers will get the basic stylesheet instead, which is probably better for them as they won’t be able to cope with the advanced features I’ll be teaching throughout the rest of this book.

The big exception to this is Internet Explorer (get used to that sentence; you’ll be reading it a lot). While IE9 does have Media Query support, previous versions don’t. To get around that you just need to load the desktop file using a conditional comment that only Internet Explorer recognizes:

<link href=”basic.css” rel=”stylesheet” media=”screen”>

<link href=”desktop.css” rel=”stylesheet” media=”screen

and (min-device-width: 480px)”>

<!—[if lt IE 9]>

<link href=”desktop.css” rel=”stylesheet” media=”screen”>

<![endif]—>

This simply means: “If you’re using Internet Explorer below version 9, load the file desktop.css.” It’s a small bit of repetition, but it will solve this problem and let you build your websites in a progressive way.

Orientation

If you’re less concerned with the actual dimensions of the viewing device but want to optimize your pages for either horizontal (like a typical web browser) or vertical (like an ebook reader) viewing, the Media Feature you need is orientation. Here is its syntax:

@media media and (orientation:value) {rules}

value can be one of two options: landscape or portrait. The landscape value applies when the width of your browser is greater than its height, and the portrait value applies when the opposite is true. Although orientation can certainly be applied to desktop browsers, you’ll find it most useful when dealing with handheld devices that the user can easily rotate, such as the new generation of smartphones and tablets.

For example, you can use orientation to display a navigation menu hori zontally or vertically, depending on the visitor’s browser orientation. The code looks like this:

ul { overflow: hidden; }

li { float: left; }

@media only screen and (orientation: portrait) {

li { float: none; }

}

By default, the li elements have a float value of left, making them stack horizontally across the page. If the same page is viewed in a portrait orientation—either by resizing the browser to be taller than it is wide or by viewing the page in a device with a portrait orientation—the float is removed and the li elements stack vertically instead. You can see the result in Figure 2-4.

Figure 2-4. The orientation Media Query on an Android browser: landscape (left) and portrait (right)

As only two values are possible for the orientation feature, if you apply differentiating rules using one value, then the other tacitly becomes the opposite. In this example, I only used the portrait value, so, by default, all of the rules outside of that function apply to the landscape orientation.

Aspect Ratio

You can also create queries that apply when a certain width-to-height ratio is met. Use aspect-ratio to test the browser’s aspect ratio or device-aspect-ratio to test the device’s aspect ratio. Here is the syntax for these two features:

@media media and (aspect-ratio:horizontal/vertical) {rules}

@media media and (device-aspect-ratio:horizontal/vertical) {rules}

The horizontal and vertical values are positive integers that represent the ratio of the width and height (respectively) of the viewing device’s screen, so a square display would be 1/1 and a cinematic widescreen display would be 16/9.

Selecting by aspect ratio is potentially fraught with caveats. For example, some device manufacturers define widescreen as 16:9, some as 16:10, and some as 15:10. This variation means you have to include all of these as parameters if you want to apply a “widescreen” set of rules.

Pixel Ratio

In general, the CSS Pixel unit (px) is a measurement of a single pixel on the computer screen—if your screen is 1024×768 resolution and you give an element a width of 1024px, you expect it to fill the screen horizontally. This is not always the case with smartphone and mobile devices, however. Reading websites on their small screens often involves zooming in, and this magnification causes a screen pixel to be larger than a CSS pixel. For example, magnifying a page by 100 percent means 1 CSS pixel is displayed on the screen by 4 device pixels (2×2).

Magnification is fine for scalable content such as text and vector graphics, but bitmap images can suffer badly from a loss of quality when magnified. To get around this problem, many devices now have screens with higher pixel density ratios, which allow for the display of high-resolution content without any loss of quality. The iPhone 4, for example, has a pixel density of 2, meaning every CSS pixel is displayed on screen by 4 device pixels (as in the example in the previous paragraph), allowing for 100 percent zoom without any loss of detail.

A Media Feature is available that lets you target devices based on their pixel density. The feature is device-pixel-ratio, and it’s implemented in Mobile WebKit with the -webkit- prefix:

@media media and (-webkit-device-pixel-ratio: number) {rules}

The number is a decimal that represents the device’s pixel density. For example, the Samsung Galaxy S has a pixel density of 1.5; to target screens similar to that, you would use:

@media screen and (-webkit-device-pixel-ratio: 1.5) {rules}

As with the other Media Features, you can also detect maximum and minimum pixel ratios:

@media media and (-webkit-max-device-pixel-ratio: number) {rules}

@media media and (-webkit-min-device-pixel-ratio: number) {rules}

This flexibility makes serving higher-resolution images to browsers with higher pixel density easier, as you can see in this code:

E { background-image: url(‘image-lores.png’); }

@media screen and (-webkit-min-device-pixel-ratio: 1.5) {

background-image: url(‘image-hires.png’);

background-size: 100% 100%;

}

The first rule () means browsers on devices with a “standard” (or low-resolution) pixel ratio will use the standard image (image-lores.png), whereas devices with a pixel ratio of at least 1.5 will use the high-resolution image (image-hires.png) instead (). Note the use of the background-size property here (); this property should be used with high-resolution images to ensure they aren’t displayed larger than the element they are applied to (I introduce background-size fully in Chapter 8).

Pixel ratio detection should also be available in the Firefox Mobile browser (which is still in beta at the time of this writing), albeit with a different syntax for the maximum and minimum media features:

@media media and (-moz-device-pixel-ratio: number) {rules}

@media media and (max—moz-device-pixel-ratio: number) {rules}

@media media and (min—moz-device-pixel-ratio: number) {rules}

Multiple Media Features

You can chain multiple queries together on the same media type by adding expressions with the and operator:

@media logic media and (expression) and (expression) {rules}

This syntax tests that both expressions are matched before applying the selected rules. For example, to make sure all permutations of widescreen are covered, as mentioned in the previous section, you would create this query:

@media only screen and (aspect-ratio: 15/10) and (aspect-ratio: 16/9) and

(aspect-ratio: 16/10) {rules}

You can also set different expressions on multiple media types:

@media logic media and (expression), media and (expression) {rules}

Here a different expression would be used for each media type, for example, setting some rules to all landscape devices and portrait projection devices:

@media all and (orientation: landscape), projection and (orientation: portrait) {rules}

You can also, of course, create any combination of the above syntaxes.

Mozilla-Specific Media Features

As part of the work on Firefox Mobile, the Mozilla team has introduced a number of proprietary new media features, many of which are very specific to Gecko (the Firefox rendering engine), but some of which may be proposed to the W3C as official features. You can see all of these at https://developer.mozilla.org/En/CSS/Media_queries#Mozilla-specific_media_features.

Perhaps the most interesting is -moz-touch-enabled, which allows you to apply rules to elements specifically on touchscreen devices, for example, for making buttons bigger to suit fingers rather than a stylus or mouse. Here’s the syntax:

@media media and (-moz-touch-enabled) {rules}

A device is either touch enabled, in which case it has a value of 1, or isn’t, in which case the value is 0. As such, you don’t need to state a value parameter and can use the feature keyword only.

Summary

Their syntax may be simple, but Media Queries have the capacity to be extraordinarily powerful. With the mobile web explosion of recent years, designers and developers are beginning to realize they have the power to tailor their content to the user without employing the old techniques of browser sniffing or separate (and completely different) mobile versions of their sites.

Media Queries are already being recognized and hailed by some of the leading lights of web development, and talks are being given about their use at all of the big web conferences. This enthusiasm is largely due to the desire to overcome the constraints of browsing the Web on handheld devices with small screens but is now also being driven by the excitement of early iPad adopters.

With careful consideration and clever use of Media Queries, you can create websites that scale perfectly for users, however they access the Web.

Media Queries: Browser Support

WebKit

Firefox

Opera

IE

Media Queries

Yes

Yes

Yes

No (expected in IE9)

Chapter 3. Selectors

Selectors are the heart of CSS, and although the original CSS1 specification had only 5 or 6, CSS2 expanded the range with 12 more. CSS3 goes further still, roughly doubling the number of available selectors.

Selectors can be broadly separated into two categories. The first are those that act directly on elements defined in the document tree (p elements and href attributes, for example); this category contains class, type, and attribute selectors. For the sake of expediency, I’ll group these together under the banner of DOM selectors. The second category contains pseudo-selectors that act on elements or information that sits outside of the document tree (such as the first letter of a paragraph or the last child of a parent element). I’ll cover pseudo-selectors in the next chapter—here I’ll discuss DOM selectors.

CSS3 provides three new attribute selectors and one new combinator—that is, a selector that joins other selectors together, such as the child combinator (>) from CSS2. These are defined in the Selectors Level 3 Module (http://www.w3.org/TR/css3-selectors/), which currently has the status of Proposed Recommendation. This status means the module already has widespread and stable implementation across most browsers (with the current exception of Internet Explorer, though full support is planned for IE9). The Selectors Level 3 Module is also expected to be one of the first to obtain Candidate Recommendation status. As long as you make provisions for Internet Explorer’s lack of support, you can start using CSS3 selectors right away—many sites already do.

Attribute Selectors

Attribute selectors were introduced in CSS2, and, as you may expect from the name, they allow you to specify rules that match elements based on their attributes—such as href or title—and the values of those attributes. The four selectors defined in CSS2 are:

E[attr] {} /* Simple Attribute Selector */

E[attr=’value’] {} /* Exact Attribute Value Selector */

E[attr~=’value’] {} /* Partial Attribute Value Selector */

E[attr|=’value’] {} /* Language Attribute Selector */

Before moving on to the new selectors in CSS3, a quick recap of how each selector is utilized is worthwhile. For this, I’ll use the following markup, which is a (very short) contact list:

<ul>

<li><a href=”” lang=”en-GB” rel=”friend met”>Peter</a></li>

<li><a href=”” lang=”es-ES” rel=”friend”>Pedro</a></li>

<li><a href=”” lang=”es-MX” rel=”contact”>Pancho</a></li>

</ul>

The Simple Attribute Selector applies rules to elements that have the specified attribute defined, regardless of that attribute’s value. So given the following code:

a[rel] { color: red; }

all of the a elements in my markup have a rel attribute, despite their having different values. In this case, therefore, all elements have the rule applied. If you want to be more specific, you can use the Exact Attribute Value Selector to define a value:

a[rel=’friend’] { color: red; }

This code applies the rule only to the second a element in our markup () because it selects only elements that have the exact value of friend. If you want to select both of the elements that contain the value of friend, you would use the Partial Attribute Value Selector:

a[rel~=’friend’] { color: red; }

This code looks for the value of friend as part of a space-separated list (in most cases, a word) in any rel attribute and so applies the rule to elements and .

The final selector, the Language Attribute Selector, applies rules to elements based on their lang attribute. The example markup has two Spanish names, although one is from Spain and the other is from Mexico. To select both of these, you use this code:

a[lang|=’es’] { color: red; }

This code selects all lang attributes whose value begins with es, regardless of their country values—that is, elements and .

New Attribute Selectors in CSS3

You’ve seen how useful attribute selectors can be for finding exact or partial values in selectors, but what if you want even more flexibility? CSS3’s new selectors provide it with the power to match substrings within an attribute value. This feature makes them especially useful for applying rules to XML documents, which have more arbitrary attributes than HTML—though they are still quite useful for HTML developers as well.

Beginning Substring Attribute Value Selector

The first new attribute selector—which, to avoid having to repeat that mouthful of a title, I’ll refer to as the Beginning Selector—finds elements whose chosen attribute begins with the string supplied to it as an argument. It uses the caret (^) symbol to modify the equals sign in the property. Here’s the full syntax:

E[attr^=’value’] {}

This code looks for the supplied value at the beginning of the specified attribute. For example, if you use the following rule:

a[title^=’image’] {}

and apply it to this markup:

<p>Lorem <a href=”http://example.com/” title=”Image Library”>ipsum</a></p>

<p>Lorem <a href=”http://example.com/” title=”Free Image Library”>ipsum</a></p>

the rule will be applied to the a element in the first paragraph since the title attribute string begins with the word image. However, the rule will not be applied to the a element in the second paragraph because its title attribute string contains those characters but does not begin with them.

NOTE

In HTML documents, the attribute selector value is case insensitive; for XML documents, however, the value is case sensitive.

The Beginning Selector is especially useful when you want to add visual information to hyperlinks. Here’s an example of a typical hyperlink to an external website:

<p>This is a <a href=”http://example.com/”>hyperlink</a>.</p>

When you see this link in your browser, you can’t immediately tell whether it’s a link to a page on the same website or to an external URI. With this new attribute, however, you can pass the protocol (http) as the argument and add an icon to signify external links clearly:

a[href^=’http’] {

background: url(‘link-go.png’) no-repeat left center;

display: inline-block;

padding-left: 20px;

}

The result is shown in Figure 3-1.

Figure 3-1. An icon applied with the Beginning Selector

Of course, you can extend this to cover many other web protocols, some of which are used in this example:

a[href^=’mailto’] { background-image: url(’email_go.png’); }

a[href^=’ftp’] { background-image: url(‘folder_go.png’); }

a[href^=’https’] { background-image: url(‘lock_go.png’); }

With the different protocols provided as values for the selector, you can apply it to this example markup:

<p>Lorem ipsum dolor <a href=”mailto:email@example.com”>email</a> sit amet.</p>

<p>Nulla lacus metus <a href=”ftp://example.com”>FTP server</a> luctus eget.</p>

<p>Etiam luctus tortor <a href=”https://example.com”>secure server</a> quis.</p>

The results of the output are shown in Figure 3-2.

Figure 3-2. More examples of link icons with the Beginning Selector

Of course, the Beginning Selector also has many applications with attributes that accept more verbose values, such as alt, cite, and title. And with the introduction of HTML5 and a whole range of new form elements and attributes, this selector and its soon-to-be-introduced siblings will become much more flexible.

Consider, for example, the proposed datetime attribute. This attribute accepts date-string values such as 2010-03-11, so you could use the Beginning Selector to apply styles to all elements meeting a supplied year value, which is very handy for calendar or archiving applications.

Ending Substring Attribute Value Selector

The Ending Selector, as I’ll call it, works exactly like the Beginning Selector—just the other way around! That is, you use it to select attributes that end with the supplied value. The syntax differs by just one character: This time you use the dollar character ($) to modify the equal sign (=). Here’s the full syntax:

E[attr$=’value’] {}

Let’s return to the first example in this chapter, which used this markup:

<p>Lorem <a href=”http://example.com/” title=”Image Library”>ipsum</a></p>

<p>Lorem <a href=”http://example.com/” title=”Free Image Library”>ipsum</a></p>

And apply the new rule to it with a new value:

a[title$=’library’] {}

This time the rule applies to both a elements because they both end with the word library.

As with the Beginning Selector, you can use this selector to provide visual clarity to hyperlinks. But this time, instead of using the protocols at the beginning of the href attribute, you use the file types at the end. The code here shows rules for many popular file-type extensions:

a[href$=’.pdf’] { background-image: url(‘pdf.png’); }

a[href$=’.doc’] { background-image: url(‘word.png’); }

a[href$=’.rss’] { background-image: url(‘feed.png’); }

And here’s a markup snippet containing a list of links to files:

<ul>

<li>Lorem ipsum dolor <a href=”/example.pdf”>PDF</a> sit amet.</li>

<li>Lorem ipsum dolor <a href=”/example.doc”>MS Word</a> sit amet.</li>

<li>Nulla lacus metus <a href=”/example.rss”>RSS Feed</a> luctus eget.</li>

</ul>

When the stylesheet is applied to the markup, an appropriate icon is applied to each of the a elements, as shown in Figure 3-3.

Figure 3-3. Link icons applied with the Ending Selector

To achieve this effect using CSS2, you would have to apply set class values to the markup (class=”pdf”, for example). The advantage of using the Ending Selector is that links to files can be detected automatically, without an end user having to apply a particular class. The disadvantage is that sometimes the file-type suffix is not at the end of the URI. However, the next new selector helps get around that shortcoming.

Arbitrary Substring Attribute Value Selector

The final new attribute selector—which I’ll call the Arbitrary Selector—works in the same way as the previous two, but it searches for the provided substring value anywhere inside the specified attribute string. This selector uses the asterisk (*) character. Here’s the new syntax:

E[attr*=’value’] {}

To demonstrate this selector, I’ll once again use the markup from my first example:

<p>Lorem <a href=”http://example.com/” title=”Image Library”>ipsum</a></p>

<p>Lorem <a href=”http://example.com/” title=”Free Image Library”>ipsum</a></p>

and provide a value to the new selector:

a[title*=’image’] {}

As with the Ending Selector, the rule applies to both a elements. However, this time it’s applied because they both contain the word image in their title attributes, even though the word appears in a different position in each example.

You may notice that this selector is somewhat similar to the Partial Attribute Value Selector from CSS2, and, indeed, in this example they are interchangeable. But the two selectors differ in a major way. In the example markup, with CSS3, I can also use just a small piece of the string:

a[title*=’im’] {}

And the rules are still applied. The Partial Attribute Value Selector requires that the user enter a value that matches a full item in a space-separated list—in the example that would be either free, image, or library—so the im value would not be found anywhere in the markup in CSS2.

To continue with the examples provided for the first two attribute selectors, the Arbitrary Selector is also useful for adding file-type icons to URIs that have parameters at the end. Consider this fairly typical URI:

<a href=”http://example.com/example.pdf?something=something”>Lorem</a>

If you use the Ending Selector with a value of pdf, this element would not be recognized as a valid target, even though the file type is a PDF, because the value does not appear at the very end of the string. Providing the same value using the Arbitrary Selector does the trick, however:

a[href*=’.pdf’] { background-image: url(‘pdf.png’); }

The .pdf substring value occurs within the specified attribute, so the icon is applied. You can see this illustrated in Figure 3-4.

Figure 3-4. Link icon applied with the Arbitrary Selector

This selector is the most flexible of the three new attribute selectors as it takes a more wildcard approach to searching within strings. But the extra flexibility means you must take more care when defining the values provided to the selector; simple combinations of letters are far more likely to occur when you can match anywhere within a string.

Multiple Attribute Selectors

You can also chain multiple selectors together, which allows you to be very specific. Using multiple selectors, you can create rules to apply to attributes with values defined for the start, end, and anywhere in between. Imagine, for example, that you had links to two files with identical names but that were located in different folders:

<p><a href=”http://example.com/folder1/file.pdf”Lorem ipsum</a></p>

<p><a href=”http://example.com/folder2/file.pdf”Lorem ipsum</a></p>

If you want to specify a rule to apply to only the second p element, you can chain some selectors together:

a[href^=’http://’][href*=’/folder2/’][href$=’.pdf’] {}

This code looks for a elements that have an href attribute beginning with http://, ending with .pdf, and with /folder2/ in the middle. Very specific!

The General Sibling Combinator

Our final new DOM selector in CSS3 is a combinator, which you’ll recall means that it joins together more than one selector. The General Sibling Combinator is an extension of the Adjacent Sibling Combinator, which was introduced in CSS2. The syntaxes differ by just a single character:

E + F {} /* Adjacent Sibling Combinator */

E ~ F {} /* General Sibling Combinator */

The difference between the two is subtle but important: Adjacent Sibling selects any element (F) that is immediately preceded by element (E) on the same level of the document tree, but General Sibling selects any element (F) that is preceded by element (E) on the same level of the tree, regardless of whether it is immediately adjacent.

If that still sounds confusing, I’ll try to explain with an example. Let’s start with this CSS:

h2 + p { font-weight: bolder; } /* Adjacent Sibling */

h2 ~ p { font-style: italic; } /* General Sibling */

And apply it to the following markup (truncated for clarity):

<p>Next we’re going to discuss…</p>

<h2>Ren&eacute; Descartes</h2>

<p>A highly influential French philosopher…</p>

<p>He once famously declared:</p>

<blockquote>

<p>I think, therefore I am.</p>

</blockquote>

<p>However, this presumes the existence of the speaker.</p>

You can see the outcome in Figure 3-5. In the CSS, I’m using the Adjacent Sibling Combinator to bold the p element immediately adjacent to the h2 element—that is, element . I’m using the General Sibling Combinator to italicize all the p elements following the h2 element, which applies to elements and .

Elements and have no rules applied to them. Why not? Element precedes the h2 element, and element is inside a blockquote element and, therefore, on a different level (the level below) in the document tree, so neither is affected by the rules.

To achieve the desired effect of only italicizing the paragraphs on the same level as the h2 element in CSS2, without the General Sibling Combinator, you would need to set all p elements to display in italics and then add an extra rule for the p inside the blockquote to overrule the inheritance:

p { font-style: italic; }

blockquote p { font-style: normal; }

Figure 3-5. Showing the difference between the Adjacent Sibling and General Sibling Combinators

You probably won’t need to use the General Sibling Combinator often because much of its function overlaps with the basic DOM selectors. That said, you will still discover plenty of occasions where this can save you a little bit of code (and time).

Summary

Although attributes are a key feature of HTML4, most of them accept only a limited range of values, so many of them do not really require the use of the attribute selectors I’ve introduced in this chapter. Aside from the href attribute, only a handful of attributes accept more verbose values (alt, class, id, rel, and title are the ones that spring to mind). But, as I mentioned before, HTML5 is on the horizon and is set to introduce new attributes like datetime and pubdate that will allow you to be more creative with selectors.

The new selectors introduced in this chapter, along with those from previous versions of CSS, provide ways to traverse the document tree based on defined elements and attributes. Of course, on occasion the markup alone isn’t sufficient for your purposes, and then you need to add classes or nonsemantic elements to act as hooks to hang your styles on. In the next chapter, you’ll discover how CSS3 removes that need.

Selectors: Browser Support

WebKit

Firefox

Opera

IE

Attribute Selectors

Yes

Yes

Yes

Yes

General Sibling Combinator

Yes

Yes

Yes

Yes

Chapter 4. Pseudo-classes and Pseudo-elements

The very first CSS specification, CSS1, introduced the concepts of pseudo-classes and pseudo-elements. These are selectors that act upon information about elements that extends (or sits outside of) the document tree, such as the state of a link or the first letter of a text node. A pseudo-class differentiates among an element’s different states or types; these include—but are not limited to—those that provide information about link states: :hover, :visited, :active, and so on. A pseudo-element provides access to an element’s subpart, which includes those pseudo-elements that select portions of text nodes, for instance, :first-line and :first-letter.

Though the selectors just mentioned have been around since CSS1, CSS2.1 added a handful more—although pseudo-element support has not been well implemented, if at all, until recently. CSS3 builds on these foundations with an expanded range of pseudo-classes, as well as a (slightly) tweaked syntax to differentiate pseudo-elements.

The advantage of having more methods for traversing documents should be clear: Fewer styling hooks are required. Markup like this is most likely familiar to you:

<ul>

<li class=”first odd”><span>L</span>orem ipsum</li>

<li>Lorem ipsum</li>

<li class=”odd”>Lorem ipsum</li>

<li class=”last”>Lorem ipsum</li>

</ul>

The markup contains class names to describe each element’s position in the document tree: first () and last () show that the li elements are the first and last children of the ul element, and odd () is used for the odd-numbered li elements. An extra span () is included around the first letter of the first li element.

You mark up code like this when you want to add styles to alternating elements, set different values on the first and last elements, or add special formatting to the first letter of a text node. This markup detracts from the clarity and semantic meaning of your code, but in many cases you need it to provide the hooks to hang your styles on.

CSS3’s new methods allow you to achieve the same visual results without muddying the markup with unnecessary classes and nonsemantic elements:

<ul>

<li>Lorem ipsum</li>

<li>Lorem ipsum</li>

<li>Lorem ipsum</li>

<li>Lorem ipsum</li>

</ul>

This change takes CSS a big step closer to achieving its stated goal: the separation of content and presentation.

Structural Pseudo-classes

As I stated in the introduction to this chapter, a pseudo-class provides a way to select an element based on information that is not specified in the document tree. Various subtypes are available, the most common of which is the structural pseudo-class. These subtypes are used to select elements that are not accessible using simple selectors. Take, for example, the following markup:

<div>

<p>Lorem ipsum.</p>

<p>Dolor sit amet.</p>

</div>

The first of the two p elements is the first child of the div element. That’s obvious from the document tree, but the document tree doesn’t provide any information that would allow you to apply a rule to that element only. CSS2 introduced the :first-child pseudo-class for exactly that reason:

E:first-child {}

This pseudo-class allows you to make a selection based on information that exists but isn’t provided as an attribute of the element—the exact purpose of a pseudo-class. Since :first-child was introduced in CSS2, it has been the only pseudo-class of its type. But CSS3 extends the range greatly with the introduction of 11 new structural pseudo-classes.

The nth-* Pseudo-classes

Four of the new pseudo-classes are based on a count value used to find an element’s position in the document tree; for this count, you use the syntax nth-*. Note that I’ve used the asterisk here in place of a number of different values, each of which I’ll introduce throughout the rest of this chapter.

The basic syntax of the nth-* pseudo-classes is quite straightforward. By default, n represents a number that begins at 0 and increments by 1 (1, 2, 3, etc.). Another integer can be passed into it as a multiplier. For example, 2n is every multiple of 2 (2, 4, 6, etc.), 3n is every multiple of 3 (3, 6, 9, etc.), and so on:

E:nth-*(n) {}

E:nth-*(2n) {}

E:nth-*(3n) {}

The first example uses the default value n, so all elements of type E would be selected; in practice, this is the same as using a simple element selector. The next example selects every other E element, and the final example selects every third element of type E.

You may also use the mathematical operators for plus (+) and minus (−). So 2n+1 would be every multiple of two plus one (1, 3, 5, etc.), 3n-1 would be every multiple of three minus one (2, 5, 8, etc.):

E:nth-*(n+1) {}

E:nth-*(2n+1) {}

E:nth-*(3n-1) {}

The first example selects every element of type E except for the first instance; the count for this would be 2, 3, 4, 5, etc. The next example selects every odd-numbered E element (1, 3, 5, etc.). The final example, as mentioned above, selects elements in the sequence 2, 5, 8, etc.

Two special keyword values, even and odd, are also available; these can be used to replace 2n and 2n+1, respectively:

E:nth-*(even) {}

E:nth-*(odd) {}

With the basic syntax out of the way, let’s move on to the pseudo-classes themselves.

nth-child and nth-of-type

Most of the new structural pseudo-classes allow you to select elements based on either their position in the document tree in relation to their parent element (-child) or their classification (-of-type). Often these definitions overlap, but there are crucial differences between them.

The simplest examples of these pseudo-classes are nth-child and nth-of-type. The first, nth-child, selects an element based on its position in a count of the total number of children in its parent element; nth-of-type bases its count not on the total children, but only those of the specified element type.

E:nth-child(n) {}

E:nth-of-type(n) {}

E:nth-child(2n) {}

E:nth-of-type(2n) {}

In this example, rules and are equivalent because the count value (n) is left at the default; both of these simply select all child elements of type E. The difference reveals itself in the later examples: in , nth-child(2n) selects all elements of type E from a count that includes all its siblings but only where those elements are even-numbered. In , by comparison, nth-of-type(2n) selects all even-numbered elements of type E from a count that includes only those elements.

These rules are much easier to demonstrate than they are to explain. Take a look at these two rules:

p:nth-child(2n) { font-weight: bolder ; }

p:nth-of-type(2n) { font-weight: bolder; }

I’ll demonstrate the difference between them using this markup (text has been truncated for clarity):

<div>

<h2>The Picture of Dorian Gray</h2>

<p>The artist is the creator…</p>

<p>To reveal art and conceal the artist…</p>

<p>The critic is he who can translate…</p>

</div>

The div element has a total of four children: one h2 element and three p elements. The result of my first example rule () is shown in Figure 4-1. The nth-child(2n) selector makes bold every second child (the first and third paragraphs). Compare that to the result of my second example rule () in Figure 4-2. The nth-of-type(2n) selector ignores the h2 and applies a bold weight to every second instance of the three elements of type p—that is, only the second paragraph.

Figure 4-1. The result of using the nth-child selector

Figure 4-2. The result of using the nth-of-type selector

As I mentioned before, and as you can no doubt deduce from the previous examples, nth-child and nth-of-type have a fair bit of overlap, and you can often use them interchangeably, as I do in the following example.

Figure 4-3 is a table showing the five-day weather forecast for London (so temperatures are given in degrees Celsius; 0°C equals 32°F). These figures were taken in January—it’s not always this cold here! All of the information I want to convey is in the table, but without any kind of visual formatting the table is difficult to read.

Figure 4-3. HTML table of a weather forecast

Now compare this table to the one shown in Figure 4-4. Here, I used zebra striping to aid the eye along the row and center-aligned the numeric values below their column headings for legibility.

Figure 4-4. Weather forecast table formatted for readability

All of the formatting was done with a few CSS3 declarations:

tbody tr:nth-of-type(even) { background-color: #DDD; }

thead th, tbody td { text-align: center; }

thead th:nth-child(-n+2), tbody td:first-of-type { text-align: left; }

An extract of markup for this table appears next; so as not to obfuscate the example, I’m only showing the heading row and one row of the table proper:

<table>

<thead>

<tr>

<th>Day</th>

<th>Weather</th>

<th>Max. Day (°C)</th>

<th>Min. Night (°C)</th>

<th>Wind (mph)</th>

</tr>

</thead>

<tbody>

<tr>

<th>Sun</th>

<td>Sunny</td>

<td>8</td>

<td>4</td>

<td>8</td>

</tr>

</tbody>

</table>

I achieved the zebra striping using nth-of-type to change the background color of the even rows to a light gray. (I could also have used nth-child for this, as in my table markup, all of the tr elements are the only siblings on the same level of the document tree.) Then I used standard element selectors to center-align all of the head and body elements, before using nth-child (with a negative value) and first-of-type (which I’ll discuss shortly) to left-align the cells containing text.

The negative value (-n) increments the count negatively—it starts at 0 and then counts down to −1, −2, and so on. This technique is useful when used with a positive second value—I’ve used +2 here—so the count effectively begins at 2 and counts down, allowing me to select the second and first elements that are children of the thead element.

I’ll use this technique again in the first example of the next section.

nth-last-child and nth-last-of-type

The nth-last-child and nth-last-of-type pseudo-classes accept the same arguments as nth-child and nth-of-type, except they are counted from the last element, working in reverse. For example, say that I want to use some visual shorthand to show in my weather table that the forecasts for days four and five are less certain than for the preceding days, as in Figure 4-5.

Figure 4-5. Extra formatting using nth-last-child

In Figure 4-5, I italicized the characters in the last two rows by using the nth-last-child pseudo-class (although, once again, nth-last-of-type would serve just as well in this example), passing an argument of −n+2:

tbody tr:nth-last-child(-n+2) { font-style: italic; }

I used the negative value (-n) here to increment the count negatively, which has the effect of acting in reverse. Because nth-last-child and nth-last-of-type count backward through the tree, using a negative value here makes the count go forward! The count starts at the last tr element in the table and counts up in reverse order, so the last and penultimate lines are the first two counted and are, therefore, italicized. This may seem counterintuitive, but it’ll become second nature as you traverse the document tree.

first-of-type, last-child, and last-of-type

In the example code I used for Figure 4-4, I introduced first-of-type. This is similar to first-child, which was introduced in CSS2, and indeed, for the example I provided, you could use them in the same way. In practice, however, they are as different as nth-child and nth-of-type.

As you’re no doubt aware, the first-child pseudo-class is a selector used to apply rules to an element that is the first child of its parent. As with nth-of-type, however, first-of-type is more specific, applying only to the element that is the first child of the named type of its parent. A pair of counterpart pseudo-classes is also available, last-child and last-of-type, which—as you might have guessed—select the last child element or the last child element of that type, respectively, of the parent.

I’ll show two examples to demonstrate the difference. Both of the examples will be applied to the same chunk of markup (I’ve truncated the text for clarity):

<div>

<h2>Wuthering Heights</h2>

<p>I have just returned…</p>

<p>This is certainly…</p>

<p>In all England…</p>

<h3>By Emily Bronte</h3>

</div>

In the first example I’m going to use first-child and last-child, as shown here:

first-child { text-decoration: underline; }

last-child { font-style: italic; }

The result is shown in Figure 4-6. The h2 element is the first child of the div, so it has an underline applied to it. The last child of the div is the h3 element, so that is italicized. All quite straightforward.

Figure 4-6. Applying the first-child and last-child selectors

Now let’s see the difference when we use the first-of-type and last-of-type selectors:

:first-of-type { text-decoration: underline; }

:last-of-type { font-style: italic; }

Take a look at the result in Figure 4-7. You’ll notice that three elements— h2, h3, and the first p—are underlined. This is because they are the first instance of that element type. Likewise, the h2, h3, and last p are all italicized. Again, this is because they are all the last element of that type; the h2 and h3 are both the first and last of their type, and so both rules are applied to them.

Figure 4-7. Applying the first-of-type and last-of-type selectors

As with all of the *-type and *-child pseudo-classes, the distinction is subtle, and sometimes the last child element is also the last of its type, so the selectors are interchangeable. But as I’ve just shown, at times, they have different applications.

only-child and only-of-type

These two pseudo-classes are used to select elements in the document tree that have a parent but either no sibling elements (only-child) or no siblings of the same element (only-of-type). As with many of the previous pseudo-classes, these two overlap substantially in function, but the following example should illustrate the difference between them. Take the following style rules:

p:only-of-type { font-style: italic; }

p:only-child { text-decoration: underline; }

And then apply them to this markup:

<h2>On Intelligence</h2>

<p>Arthur C. Clarke once said:</p>

<blockquote>

<p>It has yet to be proven that intelligence has any survival value.</p>

</blockquote>

You can see the result in Figure 4-8.

Figure 4-8. Comparing only-child and only-of-type

Both p elements are the only elements of their type in their level of the document tree, so the only-of-type rule selects both and italicizes them. The p element inside the blockquote, however, is also the only child in its level, so it’s also subject to the only-child rule that applies the underline.

Using only-of-type allows you to pick an element from among others, whereas only-child requires the element to sit alone.

Other Pseudo-classes

In addition to the structural pseudo-classes discussed so far in this chapter, CSS3 introduces a number of pseudo-classes that allow you to select elements based on other criteria. These include link destinations, user interface elements, and even an inverse selector that permits selection based on what an element isn’t!

target

On the Web, sites don’t just link between pages but also provide internal links to specific elements. A URI can contain a reference to a unique ID or a named anchor. For example, if you had the following markup in a page:

<h4 id=”my_id”>Lorem ipsum</h4>

you could refer to it with the following link:

<a href=”http://www.example.com/page.html#my_id”>Lorem</a>

The target pseudo-class allows you to apply styles to the element when the referring URI has been followed. If you want to apply styles to the example element when the example URI is clicked, you would use:

#my_id:target {}

A popular style is to highlight the subject of an internal link visually to provide a clear cue to the user. Consider, for example, the standard pattern for blog comments, which are somewhat like this simplified markup:

<div class=”comment” id=”comment-01″>

<p>Thanks for this scintillating example!</p>

<p class=”author”>N.E. Boddy, April 13</p>

</div>

And another fairly common pattern is to include links to individual comments:

<p><a href=”#comment-02″>Latest comment</a></p>

Using the target pseudo-class, you can easily highlight the comment that the user wants to read:

.comment:target { background-color: #DDD; }

Figure 4-9 shows a list of comments in two states: on the left, as they appear before the referring link has been clicked, and on the right, after clicking the link the element that the link refers to has had its background color changed by the target selector.

Figure 4-9. Highlighting applied with the target pseudo-class

empty

The empty pseudo-class selects an element that has no children, including text nodes. Consider this markup:

<tr>

<td></td>

<td>Lorem ipsum</td>

<td><span></span></td>

</tr>

If you apply this CSS rule:

td:empty { background-color: red; }

the rule would be applied to only the first td element, as the other two contain a text node and a child element, respectively.

root

The root pseudo-class selects the first element in a document tree, which is only really useful if you’re adding a stylesheet to XML documents—in HTML, the root will always be the html element. One small advantage of using root in HTML is that you can use it to give a higher specificity to the html element, which could be useful if you need to override the simple type selector:

html {} /* Specificity: 1; */

html:root {} /* Specificity: 2; */

Let’s say you’re creating a base stylesheet and want to set a property on the html element, which shouldn’t be altered; in this case, you would use something like this:

html:root { background-color: black; }

The higher specificity gives precedence over any other properties applied to the html element, such as:

html { background-color: white; }

It’s unlikely that you’ll need to use this in most situations, however.

not

The negation pseudo-class (not) selects all elements except those that are given as the value of an argument:

E :not(F) {}

This rule selects all children of element E except for those of type F. For example, to color all the immediate child elements of a div, except for p elements, you would use this:

div > :not(p) { color: red; }

To see how useful not is, consider a situation where you have the following markup:

<div>

<p>Lorem ipsum dolor sit amet…</p>

<p>Nunc consectetur tempor justo…</p>

<p>Nunc porttitor malesuada cursus…</p>

</div>

Now imagine you want to italicize all of the child p elements except for the first one.

To do this with CSS2, you would apply a style to all the p elements and then apply a further style to reset the first element back to its previous state:

p { font-style: italic; }

p:first-child { font-style: normal; }

With not, you can reduce that to a single rule:

p:not(:first-child) { font-style: italic; }

The argument that’s passed into not must be a simple selector—therefore combinators (such as + and >) and pseudo-elements (which I’ll discuss later in this chapter) are not valid values.

UI Element States

UI element states are used to select user interface (UI) elements based on their current state. Although HTML5 proposes a new range of UI elements (such as command), in HTML4, only form elements are able to have states:

<textarea disabled=”disabled”></textarea>

<input checked=”checked” type=”checkbox”>

The textarea has a disabled attribute, and the input of type checkbox has a checked attribute. No enabled attribute exists—elements that are not disabled are, by definition, classed as enabled, so an enabled pseudo-class is also available, giving you three user-state pseudo-class selectors:

:checked {}

:disabled {}

:enabled {}

To see the effect of these, consider the following style rules:

input[type=’text’]:disabled { border: 1px dotted gray; }

input[type=’text’]:enabled { border: 1px solid black; }

I’m going to apply these rules to a form that has two text input elements, one of which has a disabled attribute (the form isn’t valid as I don’t have labels for the inputs, but that only clouds the issue in this demonstration):

<form action=””>

<fieldset>

<legend>UI element state pseudo-classes</legend>

<input type=”text” value=”Lorem ipsum” disabled>

<input type=”text” value=”Lorem ipsum”>

</fieldset>

</form>

You can see the results in Figure 4-10.

Figure 4-10. Disabled and enabled element states

As you can see, the disabled form element has grayed-out text (which is done automatically by the browser) and a gray dotted border (which I set in the stylesheet). I set a solid black border around the enabled element.

I haven’t given a demonstration of the checked state here, as most browsers have very different interpretations of which style rules can be applied to checkbox inputs. For a comprehensive overview of cross-browser styling of form elements, I highly recommend “Styling Form Controls with CSS” from the blog 456 Berea Street (http://www.456bereastreet.com/lab/styling-form-controls-revisited/).

The specification notes that an idea is under consideration by the W3C to feature a fourth UI element state of indeterminate, which would be used in the occasional circumstance in which an element could be either enabled or disabled or has not yet been set into one of these states. At the time of writing, indeterminate is not an official part of the CSS3 specification.

 

 

CSS3 is the technology behind most of the eye-catching visuals on the Web today, but the official documentation can be dry and hard to follow. Luckily, The Book of CSS3 distills the heady technical language of the CSS3 specification into plain English, so you can get started on your next project right away.

With real-world examples and a focus on results, The Book of CSS3 shows you how to transform ordinary text into stunning, richly detailed web pages fit for any browser. You’ll master the latest cutting-edge CSS features, like multi-column layouts, borders and box effects, and new color and opacity settings. You’ll also learn how to:

  • Stylize text with fully customizable outlines, drop shadows, and other effects
  • Create, position, and resize unlimited background images on the fly
  • Spice up static web pages with event-driven transitions and animations
  • Apply 2D and 3D transformations to text and images
  • Use linear and radial gradients to create smooth color transitions
  • Tailor a website’s appearance to smartphones and other devices

From the simplest blog layout to the most feature-rich web portal, The Book of CSS3 puts the whole wide world of web design at your fingertips. The future of web design is now—what will you create with it?

5 Reasons to Start Using CSS3 from the Author
Device-responsive pagesThe big growth area of web browsing is on smartphone and tablet devices such as Android, iPhone and iPad. New media features and page layout modules in CSS3 let you make pages which respond to the capabilities of the device that’s viewing them, automatically optimizing your content for multiple screen sizes and giving your visitors a tailored experience.

Eye candy!
CSS3 brings web documents to life without complicated JavaScript. Rotate, scale and skew page elements in both two and three dimensions, add smooth transitional animations to elements when their values change, and go even further with keyframe animations which give you fine control over the behavior of your page elements.

A better reading experience
The web was made for reading text, but for years we’ve had to use a handful of fonts in a very conservative way. CSS3 brings the power to use any font you wish, to decorate the text with drop shadows and outlining, plus new ways of laying out the text such as in multiple columns, like a newspaper or magazine.

Easier to maintain
Using CSS2.1 usually means adding images (and extra markup) to your documents in order to achieve what should be simple effects. Something as basic as adding rounded corners to an element can mean using up to four extra empty elements to accommodate the graphics required to fake the appearance. CSS3 was created to address just these problems, so you can add rounded corners, drop shadows, gradient backgrounds and much more without writing unnecessary markup or creating multiple image files — meaning a lot less work to make and maintain your documents.

Cleaner code
The greatly expanded range of selectors in CSS3 means you can add special formatting to links depending on their destination, loop through long tables and lists, even select form elements depending on their current state — all without having to clutter your code with surplus class attributes.

 


Related posts

SAP S/4 HANA for Financial Accounting Associates : SAP Certified Application Associate by S Matiana, PDF 1545316171
Digital Video Quality Vision Models and Metrics by Robert Elder, PDF 1975794435
Mastering Data Visualization With Microsoft Visio Professional 2016 by David J Parker, PDF 178588266X
The Interactive Past: Archaeology, Heritage, and Video Games by Aris Politopoulos, PDF 9088904375
Effects of Age on Smartphones Based on Eye-Movements and gestures by Suleyman Al-Showarah, PDF 3330021705
Malware Detection in Cloud Computing by Safaa Atatabbi, PDF 3330053259

Leave a Reply

Your email address will not be published. Required fields are marked *