Chris Mills Practical CSS3 Develop and Design 2012 PDF
Chris Mills Practical CSS3 Develop and Design 2012 PDF
CSS3
Chris Mills
Practical CSS3
DEVELOP AND DESIGN
Chris Mills
Peachpit Press
1249 Eighth Street
Berkeley, CA 94710
510/524-2178
510/524-2221 (fax)
Find us on the Web at: www.peachpit.com
To report errors, please send a note to: [email protected]
Peachpit Press is a division of Pearson Education.
Copyright 2013 by Chris Mills
Acquisitions Editor: Rebecca Gulick
Development and Copy Editor: Anne Marie Walker
Technical Reviewers: Peter Gasston, Bruce Lawson
Production Coordinator: Myrna Vladic
Compositor: David Van Ness
Proofreader: Patricia Pane
Indexer: Valerie Haynes-Perry
Cover Design: Aren Howell Straiger
Interior Design: Mimi Heft
Notice of Rights
All rights reserved. No part of this book may be reproduced or transmitted in any form by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior written permission of the publisher. For information on getting permission for reprints and excerpts, contact [email protected].
Notice of Liability
The information in this book is distributed on an As Is basis, without warranty. While every precaution has
been taken in the preparation of the book, neither the author nor Peachpit Press shall have any liability to any
person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the
instructions contained in this book or by the computer software and hardware products described in it.
Trademarks
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as
trademarks. Where those designations appear in this book, and Peachpit was aware of a trademark claim, the
designations appear as requested by the owner of the trademark. All other product names and services identied throughout this book are used in editorial fashion only and for the benet of such companies with no
intention of infringement of the trademark. No such use, or the use of any trade name, is intended to convey
endorsement or other aliation with this book.
ISBN-13: 978-0-321-82372-4
ISBN-10:
0-321-82372-9
9 8 7 6 5 4 3 2 1
Printed and bound in the United States of America
ACKNOWLEDGMENTS
Id like to give a shout out to all the sping chaps and chapesses of awesomeness
and beauty that have helped and inspired me during this time, and driven me to
get this book written!
My colleagues and friends at Opera for being almost like a second family, for
teaching me so much, for helping me x my code, and for making web standards
fun. ODevRel2012: Andreas, Bruce, Daniel-san, Karl, Luz, Mike, Patrick, Shwetank,
Tiany, Vadim, and Zi Bin. And thanks to all the other talented people who make
Opera a great place to work.
My allies in the wider web dev community for giving me much inspiration and
smiles, mainly on Twitter: Jake74, Dan Donald, Phil Sherry, Shaun/Leslie JensenInman, Doug Schepers, Jon Hicks, Chris Murphy, and the rest of the Irish posse,
Remy Sharp, Anna Debenham, Mark and Emma Boulton, and the rest of the FSS
crew, Henny Swan, and the W3C Web Education Community Groupphew. If
Iforgot your name on this list, please abuse me on Twitter: @chrisdavidmills.
Peter Gasston for an awesome tech review job on this book. I owe you mate.
Anne Marie Walker, Rebecca Gulick, and the rest of the Peachpit crew for kicking my ass into delivering this thing and helping to shape it.
Conquest of Steel (Vic/DD/Dan/Claymore) for being almost like a third family,
or maybe more like having four whinging girlfriends. Cheers guys for the 15 years
and counting of heavy metal. \m/
My friends in other far-ung places for always giving me love and support, even
if they didnt understand this interweb thing.
My parents for bringing me up proper. I love you both very dearly.
And most of all Id like to give thanks and love to Kirsty, Gabriel, Elva, and Freida
for putting up with me for four months while ignoring them to write this book, and
for being the main reason I get out of bed in the morning.
ACKNOWLEDGMENTS
III
CONTENTS
CHAPTER 2
CHAPTER 3
IV
PRACTICAL CSS3
CHAPTER 4
CHAPTER 5
CHAPTER 6
CONTENTS
CHAPTER 7
CHAPTER 8
BONUS CHAPTER
CHAPTER 9
VI
PRACTICAL CSS3
ONLINE RESOURCES
Throughout this book I use several third-party, online resources that include scripts
and stylesheets, and I present and reference many examples that I wrote to illustrate
the concepts in this book. The third-party resources are referenced where appropriate, so youll be able to nd them when needed. To nd my examples is even
easier: You can download them all athttp://peachpit.com/practicalcss3.
But thats not all! Also available at http://peachpit.com/practicalcss3 are the
following:
A cheat sheet. This reference document details the syntax of all the new
CSS3 features I use in this book and how they are supported in browsers.
Print it out and hang it on your wall as an at-a-glance guide! Ill update this
reference as the data changes.
ONLINE RESOURCES
VII
WELCOME TO CSS3
CSS3 provides you with exciting new tools for your web development toolbox, allowing
you to accomplish many styling tasks in a much easier, more exible, and less hackish
manner than youve been used to when working with CSS2. The following chapters will
introduce you to the most useful, new CSS3 features and show you how to use them in real
VIII
PRACTICAL CSS3
THE LATEST,
GREATEST BROWSERS
OLDER, LESS-CAPABLE
BROWSERS
ALTERNATIVE
BROWSING DEVICES
DEBUGGING
ENVIRONMENTS
A DECENT TEXT
EDITOR
1
INTRODUCTION TO
CSS3 AND MODERN
WEB DESIGN
WHY CSS3?
CSS3 has been around for longer than you might think. In fact, work had started
on the earliest parts ofCSS3 at about the same time as the CSS2 spec was being
nished in the late 1990s. CSS2 has many very powerful features, and you can do a
lot with it, but it was clear all those years ago that despite this a number of features
were missing from the spec. This was evidenced by the fact that web designers tried
to do many tasks using weird and interesting hacks or unusual techniques, often
involving lots of nested <div>s or other semantic backstabbery, images, or even
proprietary technologies like Flash. Some examples that spring to mind include:
CHAPTER 1
Font embedding. Downloading custom fonts for use on websites has been
available in Internet Explorer (IE) since version 4 but wasnt standardized
until years later with CSS3 web fonts. Before web fonts gained popularity and cross-browser support, web developers used to rely on all kinds
of weird replacement techniques, such as image replacement and siFR
(Scalable Inman Flash Replacementsee http://en.wikipedia.org/wiki/
Scalable_Inman_Flash_Replacement) if they wanted custom fonts in
headings.
Bulletproof CSS. Back in the late 1990s and early 2000s a lot of pioneering
techniques started to spring up for creating CSS UI features that wouldnt
break if the text was resized. The text wouldnt spill messily out of its
containers; instead, the design would expand along with it. These techniques were referred to as Bulletproof CSS, and they worked well if done
properly. But often they required a number of nested <div>s, each with
a single background image hung o it. Bulletproof rounded corners on a
container required four nested <div>s! Such designs were inexible as well.
If you wanted to then change the color of the background, youd have to
go back into your preferred graphics editor and update all the background
images each time. This is exactly the kind of problem that properties like
border-radius were created to x.
Multiple column layouts. It is very common to use CSS oats to create multiple column layouts; this everyone knows. But this is somewhat of a hack.
Floats were never originally intended for this purpose. They were intended
for simple magazine layout image oats.
Dynamic UIs. Many dynamic UI features, such as layouts that automatically adapt to dierent screen widths and smooth animations and transitions for user feedback, have been traditionally done using JavaScript. There
was no way to achieve them using CSS alone until recently; hence, the rise
of DHTML in the late 1990s (yuck!) and more recently, the overwhelming
popularity of JavaScript libraries, such as jQuery and Dojo.
And the list goes on. CSS3 was created not to give users a completely new set of
amazing features to play with and create spangly web innovations (a great design
agency name if ever there was one), but more to provide users with standardized,
more exible ways of solving existing problems.
There are now more than 40 modules in CSS3 at various stages of completion
and browser support. The modular system is benecial in many ways. It makes
CSS3 easier to write by the spec teams and implement by the browser vendors: It
is always easier to tackle small chunks than a single giant monolith. It also makes
it easier for web designers and developers to get their heads around, and in my
opinion, it makes it easier to sell to clients who may have issues about using
unnished technologies in their sites (yes, CSS 2.1 was technically only nished
in 2011, but hey).
WHY CSS3?
FIGURE 1.1
Its highly impressive to be
able to create web pages like
this, just using open standards
(see http://operasoftware.
github.com/Emberwind and
http://helloracer.com/webgl).
I am a great supporter of CSS and the rest of the open standards landscape. The last
couple of years have been very exciting for open standards. Youve seen browsers
leap forward in terms of rendering speed, feature support, and so on. New web
technologies like CSS3 and HTML5/WebGL really do allow you to create some
amazing digital experiences (Figure 1.1).
CHAPTER 1
But everyone needs to take a step back when considering such innovations and
not lose sight of the original qualities and best practices that made the web great,
such as accessibility, usability, and graceful degradation.
USABILITY NEXT!
Once your users have managed to access your content and services, can they make
sense of it and glean the information they wanted from it? This is a simple, perhaps
obvious point to make, but Ive lost count of the times Ive gone to a company
website and scratched my head in vain while trying to nd contact details, opening
times, or an address. Instead, I nd nothing useful amidst the sea of marketing BS,
cheesy videos, and other propaganda being presented.
Why do people not think more about what information is most useful to people
viewing their websites and how to present that information in an easily digestible
way? A simple, well-written, and clearly available bit of copy is nearly always more
eective than reams of ashy, whizzy, technical stu.
My mantra for usability (and many other peoples, too) is dont make me think.
Dont make your users think about how to get what they want. If youve not already
read it, Steve Krugs book Dont Make Me Think: A Common Sense Approach To Web
Usability, 2nd Edition is essential reading.
CHAPTER 1
These are design philosophies that I have always held dear. They have not
always been easy to uphold, because you often meet clients who are obsessed
with pixel perfection across all browsers or some similar weird fetish. But they
are certainly becoming cool again, especially with all the CSS3 features to make
use of and lots of mobiles and other alternative browsing devices to make your
content work across. Oh, and IE6, 7, and 8 still have signicant market share and
often need to be supported.
The wide variety of new devices you have to support these days (mobile phones,
tablets, TVs, etc.) actually makes things easier in terms of clients craving pixel perfection across all devices: It is impossible for sites to look and function the same
across all desktop and mobile platforms, and indeed it doesnt make sense (as aped
by dowebsitesneedtolookexactlythesameineverybrowser.com, seen in Figure 1.3).
It is all about context. What makes sense on a standard desktop computer might
well provide a bad user experience on a touchscreen mobile device or tablet.
The good news is that CSS3 is fairly easy to progressively enhance and gracefully
degrade, and otherwise get to work OK across old browsers. Most of the features,
if used in the right way, will degrade gracefully so that the base content will still
be accessible in nonsupporting browsers. Also, there are mechanisms that allow
you to build in support or provide alternative content if need be.
10
CHAPTER 1
You should constantly look at making content work for as many users as possible by:
1. Keeping graceful degradation/progressive enhancement in mind.
2. Providing alternatives for inaccessible content using built-in features
(e.g., alt text, transcripts for video).
3. Building in your own alternatives when no built-in mechanisms
exist (e.g., feature detection and provision of alternative styles using
Modernizr).
4. Using polylls to provide support for features where none exists.
The rule I used for deciding what to cover in this book was to include a CSS3
feature only if it has support across at least two major browsers and if you can
make designs employing it work in older browsers that dont support it via polylls,
alternative content, graceful degradation, and so on. Ive broken this rule a few
times, but only when I thought a feature was very signicant and likely to have
more implementations soon, and when nonsupport didnt completely break sites.
TIP: A great site to consult for quick summaries of which CSS3
and HTML5 features are ready to use on production sites, and
whether fallbacks and the like should be provided is http://html5please.us
by Divya Manian, Paul Irish, et al.
11
Lets look at a brief roundup of the major CSS3 modules youll be utilising and their
main features. You can nd more details on the latest status of each module at the
W3C CSS Current Work page atwww.w3.org/Style/CSS/current-work.en.html. As
youll see, many of the modules are not yet nished, but this shouldnt stop you from
using some of those features. Many such features are already supported in browsers, albeit with vendor prexes (see the section Vendor Prexes for more details).
The major CSS3 modules featured in this book include:
12
CHAPTER 1
Backgrounds and Borders Level 3 (www.w3.org/TR/css3-background). Backgrounds and Borders denes anything to do with background and borders,
including rounded corners (border-radius), drop shadows (box-shadow),
and fancy border eects (border-image).
13
To whet your appetite, lets now look at some general CSS3 features. These features are grouped together because they are general features that youll meet time
and time again throughout dierent chapters: They are useful in many dierent
circumstances.
VENDOR PREFIXES
Vendor prexes are not exactly specic CSS3 features, but at the time of this writing
(and for some time after), youll meet them repeatedly when working with CSS3.
The reason is that many of the modules youll be using features from arent nished.
The idea is that before a CSS feature is completely nished (e.g., the spec is
not quite stable, and changes may be made before the nal version), it can still be
implemented inside browsers. At this stage, browser vendors add their own vendor prex to the start of the feature and use the prexed version. This allows each
vendor to support the feature inside its own sandbox, as it were, so if the spec
changes and future versions work dierently, this wont result in a single property
that works dierently across dierent browsers. As an example, CSS transitions
are currently supported across browsers with vendor prexes. A sample block of
code might look like this:
a:link {
background-color: #666666;
-webkit-transition: 1s all;
-moz-transition: 1s all;
-ms-transition: 1s all;
-o-transition: 1s all;
transition: 1s all;
}
a: hover {
background-color: #ffffff;
}
14
CHAPTER 1
A PREFIXED NIGHTMARE?
Ive put the prefixed properties in my example in the order they are in for two reasons. First, it looks
aesthetically pleasing to have the widest prefix first and the narrowest last.
Second, at the time of this writing, a number of non-WebKit browser makers were discussing adding
support for -webkit- prefixed versions of some properties, as well as their own prefixed versions. By putting
-webkit- first, you can make sure that if this happens, such browsers will end up using their own prefixed
version if it is present, not -webkit-, because the others all appear afterwards in the cascade.
Using the correct prefixed property will always be better and more accurate than relying on faked -webkitsupport, especially considering that in some cases you might feed the different browsers different property
values because of varying support. For example, at the time of this writing Opera does not yet support 3D
transforms, so you could provide Opera with this 2D transform that would work:
-webkit-transform: rotate3D(1,0,0,10deg) translateX(300px);
-o-transform: translateX(300px);
Why are other browsers considering adding -webkit- support? Because so many developers have been harboring an ill-conceived idea that WebKit is the only browser engine worth supporting. So they were using
lots of CSS3 features only with the -webkit- prefix, thereby making those features arbitrarily fail in other
browsers that support them. As far as users are concerned, it is the browsers that are at fault. The average site visitors dont know any better, and neither should they be expected to. Messy as it is, non-WebKit
browsers adding -webkit- support is a somewhat desperate potential measure to try to fix this browser
support mess to some degree.
To sum up, it may sound nightmarish having to include five different versions of the same property in such
situations. Quite a few people think that you shouldnt use vendor prefixes at all in production projects,
and that they are only for testing purposes (this is the W3Cs official stance too). But dont let that stop you.
As youll discover throughout this book, it is easy in most cases to retain an acceptable user experience in
browsers that dont support those properties, as long as you give it a bit of forethought!
If you want to use prefixed CSS3 features, please do so responsibly and use all the different prefixes for all
supporting browsers. And dont make your sites dependent on a particular feature that doesnt have crossbrowser support!
15
this writing, you need to include these so the eect will work in Chrome and other
WebKit-based browsers (-webkit-), Firefox and other Gecko-based browsers (-moz-),
IE (-ms-), and Opera (-o-). Ive also included the fthprexlessproperty so
that when browsers start to support the prexless version instead of their own
specic prexed property, the code will still work for them, and you wont have to
update it unless the spec has changed since then.
There is no single correct way to order the vendor prexes in your code, and
dierent people have dierent opinions about how it should be done. Im just
presenting my opinion of what I think works best.
CSS3 COLORS
The new CSS3 Color units (www.w3.org/TR/css3-color) are most useful, particularly because they allow you to programmatically dene transparency for colors.
This allows you to create advanced graphics and features that blend nicely into
each other and their backgrounds without having to create loads of transparent
PNGs all the time.
Table 1.1 shows what current support looks like.
TABLE 1.1 Browser Support for CSS3 Color Units
16
CHAPTER 1
Opera
Since 10
Firefox
Since 3.0
Safari
Since 3.1
Chrome
Since 4.0
Internet Explorer
Since 9
iOS
Since 3.2
Android
Since 2.1
Mobile Chrome
Since beta
Opera Mobile
Since 10
Opera Mini
Since 5
RGB (actually available since CSS2) works in a similar way to hex values. You dene
red, green, and blue channels, but you do it using numbers between 0 and 255, not
pairs of hexadecimal numbers:
rgb(255,0,0).
rgb(255,255,255).
RGBA takes this a step further, adding a fourth value that species the alpha
channel, or the opacity of the color. This value is between 0 and 1; 0 is completely
transparent, and 1 is completely opaque:
rgba(255,0,0,1).
rgba(255,0,0,0.5).
rgba(255,0,0,0.2).
hsl(0,100%,50%).
hsl(0,0%,100%).
The rst valuehuetakes a value between 0 and 360. Its basically a point
around a standard color wheel circle.
The second valuesaturationtakes a value of 0100% and refers to how
bright the color is; 100% is full color, and 0% is greyscale.
The third valuelightnesstakes a value of 0100% and refers to how light
the color is; 100% is completely light/white, and 0% is completely dark/black.
17
HSL makes sense in a lot of ways; for example, you could select complementary shades of red to go with the preceding red color, just by varying the lightness,
like this:
hsl(0,100%,30%)
hsl(0,100%,40%)
hsl(0,100%,50%)
hsl(0,100%,60%)
HSLA works in the same way as RGBA. You just add the alpha channel value
to the existing color like this: hsla(0,100%,50%,0.5), which results in full red but
is 50 percent transparent.
OPACITY
A separate opacity property is available in CSS3. You can add it to any element to
set a level of transparency for that entire element and everything within it, including all child elements. As youd expect, it takes a value of 01:
opacity: 0;
18
CHAPTER 1
h1 {
font-size: 3em;
}
p {
font-size: 1.4em;
}
This is simple CSS. You start with the tried and tested 62.5% font setting to
take the base font size for the whole document down to 10px (62.5% of 16px, the
standard default body text font size in all browsers). Then you set the <h1> size
19
to three times that, which results in a computed size of 30px. The <p> is set to 1.4
times the size of the base font, or 14px.
The trouble starts when you try to resize children of those elements. If you
wanted to, say, size your <code> element at 11px, how would you do that with
ems? Well, 1.1em wouldnt work, because it would be 1.1em of 14px (the size of its
parent element). The actual value you need is 11/14 = 0.786em. Extrapolate this
to more complicated and precise designs, and youre looking at a whole load of
complicated math and hair pulling.
Rems make text sizing a lot easier. If you instead used rems for these text sizes,
everything would be relative to the font-size on the <html>. So getting 11px code
font would be a matter of using the following:
code {
font-size: 1.1rem;
}
Table 1.2 shows the current state of browser support for rem units.
TABLE 1.2 Browser Support Matrix for Rem Units
20
CHAPTER 1
Opera
Since 11.6
Firefox
Since 3.6
Safari
Since 5.0
Chrome
Since 6.0
Internet Explorer
Since 9
iOS
Since 4.0
Android
Since 2.1
Mobile Chrome
Since beta
Opera Mobile
12
Opera Mini
No
IE only supports rems since version 9, so support for older versions needs
some attention. The best way to handle this is to provide fallbacks in pixel sizes
so older IE versions at least get the same sizing, albeit with a lesser degree of exibility. For example:
code {
font-size: 11px;
font-size: 1.1rem;
}
TIP: IE6 and IE7 dont resize text set in pixels, so for accessibilitys
sake, if you are planning on using rems for text sizing, you might
want to consider bumping up the text size just for these browsers using
an IE conditional stylesheet (see Chapter 2.)
CSS3 SELECTORS
CSS3 features an entire toolbox of new selectors that allow you to select more specic elements for styling while nullifying the need for a lot of those arbitrary IDs
and classes you tend to often include to select the last item in the list, or the rst
paragraph in the post that always contains the introduction, or even the twelfth
div across on the 17th shelf because I want it to be the prettiest.
I wont discuss every selector exhaustively. If you want a detailed reference
for each one, consult a resource such as www.w3.org/community/webed/wiki/
Advanced_CSS_selectors. Instead, Ill provide a quick reference in Table 1.3 for all
the selectors, and then showcase some of the most powerful and interesting ones
(as well as some seldom-explored selectors rst included in CSS2) to give you a
good avor of what selectors are now capable of.
21
SELECTOR
EXAMPLE
DESCRIPTION
BROWSER
SUPPORT
Universal
All
Attribute
img[alt]
Not IE6 or
earlier.
img[src="alert.gif]
Not IE6 or
earlier.
img[src^="alert"]
Not IE6 or
earlier.
img[src$="gif"]
Not IE6 or
earlier.
a[href*="uk"]
Not IE6 or
earlier.
Not IE6 or
earlier.
22
CHAPTER 1
Not IE6 or
earlier.
SELECTOR
EXAMPLE
DESCRIPTION
BROWSER
SUPPORT
Descendant
nav a
All.
nav li a.
Child
body>header
Not IE6 or
earlier.
body>header>p.
Adjacent sibling
h1 + p
Not IE6 or
earlier.
General sibling
h1 ~ img
Selects the element on the right only if it is a sibling (at the same nesting level) as the element on
the left. Its great for setting that indent mentioned
previously on each paragraph after a heading or
giving a special styling only to images inside an
article at the same level as a heading.
Not IE6 or
earlier.
UI element
pseudo-classes
a:link
All.
a:visited
All.
img:hover
All.
input:focus
All.
a:active
All.
23
SELECTOR
EXAMPLE
DESCRIPTION
BROWSER
SUPPORT
UI element
pseudo-classes
(continued)
input:valid
Not supported
in IE.
input:invalid
Not supported
in IE.
input:enabled
All.
input:disabled
All.
input:in-range
Not supported
in IE.
input:out-of-range
Not supported
in IE.
Negation selector
Language selector
p:lang(en-US)
Not IE6 or
earlier.
Target selector
article:target
Not IE8 or
earlier.
24
CHAPTER 1
Not IE8 or
the simple selector(s) inside the parentheses. This is earlier.
useful in cases where you have several similar elements and want to select them all except for one
of two. For example, when laying out a form youll
want to give most of the inputs an equal width
but not the submit or file inputs. You can include
multiple selectors to negate inside the parentheses in a comma-delimited listfor example,
input:not([type="submit"], [type="file"]).
SELECTOR
EXAMPLE
DESCRIPTION
BROWSER
SUPPORT
Structural
pseudo-classes
:root
Not IE8 or
earlier.
li:nth-child(2n+1)
Not IE8 or
earlier.
li:nth-last-child(2n+1)
Not IE8 or
earlier.
p:nth-of-type(3)
Not IE8 or
earlier.
:nth-last-of-type(1)
Not IE8 or
earlier.
p:first-child
Not IE8 or
earlier.
p:last-child
Not IE8 or
earlier.
p:first-of-type
Not IE8 or
earlier.
p:last-of-type
Not IE8 or
earlier.
li:only-child
Not IE8 or
earlier.
25
SELECTOR
EXAMPLE
DESCRIPTION
BROWSER
SUPPORT
Structural
pseudo-classes
(continued)
section p:only-of-type
Not IE8 or
earlier.
:empty
Not IE8 or
earlier.
p:first-letter
Not IE6 or
earlier.
p:first-line
Not IE6 or
earlier.
a:before
Not IE7 or
earlier.
a:after
Not IE7 or
earlier.
Pseudo-elements
NOTES: The word All in Table 1.3 means all the browsers youll likely need
to support in most projects.
Some interesting new selector developments are in the CSS4 Selectors
module, so keep checking www.w3.org/TR/selectors4 for the latest.
Lets move forward and look at a few cases in point to illustrate why CSS3
selectors are useful.
26
CHAPTER 1
CSS3 extends the basic attribute selector functionality by allowing you to select
elements based on strings within attribute values. For example, you could select
and style <img src=alert.gif> using the following:
img[src^=alert] {
border: 1px solid #000000;
}
The ^ character dictates that this selector should select <img> elements only if
they have the string alert at the start of the src attribute value.
<img src=alert.gif> could also be styled like this:
img[src$=gif] {
border: 1px solid #000000;
}
The $ character dictates that this selector should select <img> elements only
if they have the string gif at the end of the src attribute value. This is really
useful for styling links that point to specic types of resources: You could perhaps
add specic icons to dierent links depending on whether they link to PDFs, Word
documents, and so forth.
You could also style <img src=alert.gif> like this:
img[src*=ert] {
border: 1px solid #000000;
}
The * character dictates that <img> elements with the string ert anywhere
within the src attribute will be selected.
27
The negation pseudo-class can be used to explicitly apply styles to elements that
are not selected by a simple selector. Lets say you wanted to apply a specic width
to a number of form elements but not the submit. You could do this:
input[type=text], input[type=url], input[type=email],
p select, textarea, etc, etc {
width: 15em;
}
But this code is a total messy pain. The :not selector allows you to do this:
input:not([type=submit]) {
width: 15em;
}
You can put multiple simple selectors inside the parentheses separated by
commas, like so:
input:not([type=submit], [type=file])
CSS3 PSEUDO-CLASSES
Pseudo-classes dont just select elements; they select elements in certain statesfor
example, a {} to select links, but then a:hover {} to select links only when they
are being hovered over by the mouse.
CSS3 introduces some new pseudo-classes for you to sink your teeth into. My
favorite, :target, allows you to select elements that are the target of the current
page URL. This is very useful and allows for some cool eects, because it eectively
lets you set styles to be applied when links are clicked. For example:
<a href=#target>Click me</a>
<div id=target>Woot!</div>
28
CHAPTER 1
The page URL targets the <div> when the link is clicked. To style it in this state,
you could use this:
div:target {
...
}
Note that you can see a real working example of CSS-only tabs using :target
inside the target-demo folder in the chapter1 code download folder.
New pseudo-classes are also available for styling form inputs when the data
is valid and invalid (see Chapter 2 for more about HTML5 forms). Funnily enough,
they are:
input:valid { color: green; }
and
input:invalid { color: red; }
:nth-child allows you to select a repeating pattern of elements inside a continuous seriesfor example, several list items or several paragraphs or articles
next to one another. Lets look at an example:
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
<li>Fifth</li>
<li>Sixth</li>
<li>Seventh</li>
<li>Eighth</li>
<li>Ninth</li>
<li>Tenth</li>
</ul>
29
To select just the odd or even list items, youd do this (a very easy way to create
the infamous zebra-striped table eect):
li:nth-child(odd)
li:nth-child(even)
To create the same zebra stripes, lets look at some other formula examples:
li:nth-child(4n+1). Selects every fourth list item, and then adds 1 to each
30
CHAPTER 1
31
PSEUDO-ELEMENTS
first-letter and first-line. You can select the rst letter inside a given
element using the first-letter pseudo-element and the rst line using
first-line. In my King Arthur blog example (introduced in Chapter 2 and
found in the king-arthur-blog-example code download folder), Ive created a rather cool drop cap and rst-line eect using both of these pseudoelements in tandem (see Figure 1.4 for the result):
#main>article>p:first-of-type:first-line {
font-variant: small-caps;
}
#main>article>p:first-of-type:first-letter {
font-size: 400%;
float: left;
/* loads more styling! */
}
32
CHAPTER 1
Generated content using :before and :after. You can use the :before and
:after pseudo-elements to specify that content should be inserted before
and after the element you are selecting. You then specify what content you
want to insert or generate. As a simple example, you can use the following
rule to insert a decorative image after every link on the page:
a:after {
content: url(flower.gif);
}
You can also use the attr() function to insert the values of attributes of the
elements after the element. For example, you could insert the target of every link
in your document in brackets after each one using the following:
a:after {
content: ( attr(href) );
}
This is a great technique to use in a print stylesheet where you want to just
show the URLs in the document rather than having them hidden inside links
(useless on a printed page).
CSS3 PSEUDO-ELEMENT DOUBLE-COLON SYNTAX
Note that the new CSS3 way of writing pseudo-elements is to use a double colon
for example, a::after { ... }, to set them apart from pseudo-classes. CSS3, however, also still allows for single colon pseudo-elements for the sake of backward
compatibility. This is what Ill be using throughout the book, although you might
want to use double-colon syntax for better future proong; it is really up to you.
33
As youll have gathered, many of the new selectors available dont work in those
irksome older versions of IE that are still hanging around (like someones rhythmically challenged dad on the dance oor at a wedding reception). So what hope do
you have of using these selectors in the real world?
As luck would have it, for situations in which you really need old IE support,
JavaScript can come to the rescue in the shape of Keith Clarks Selectivizr (http://
selectivizr.com). It sits on top of an existing JavaScript library and adds support to
IE 68 for many of the new selectors.
To add it in, download Selectivizr and apply it to your site. Then make sure you
also have one of the compatible libraries detailed on the Selectivizr site applied
to your page (Im using NWMatcher in my example). The code will look something like this (again, check out my king arthur blog example in the chapter2 code
download folder):
<script src=http://s3.amazonaws.com/nwapi/nwmatcher/
p nwmatcher-1.2.5-min.js></script>
<!--[if (gte IE 6)&(lte IE 8)]>
<script type=text/javascript src=script/
p selectivizr-min.js></script>
<![endif]-->
And there you go! This CSS3 selector support for IE 68 works like a charm!
34
CHAPTER 1
WRAPPING UP
By now Im sure youve conceded that CSS3 is awesome, and that you should start
to embrace it as soon as possible. Youve read about the philosophy and general
approach youll be adopting for this book, reviewed the main CSS3 modules youll
be dipping into along the way, and learned about some general CSS features to whet
your appetites. With all this information under your belt, youre ready for the next
chapter, which focuses mainly on markupriveting material.
WRAPPING UP
35
2
BUILDING A SOLID
CROSS-BROWSER
TEMPLATE WITH
HTML5 AND
JAVASCRIPT
37
STARTING WITH
SEMANTIC HTML5
The rst part of your toolset for working with CSS3 will be clean, semantic HTML,
also referred to as POSH (plain old semantic HTML). Not only is it advantageous
in many ways (e.g., better for search engine optimization, more accessible, easier
coding and maintenance), but it is essential for success when you start applying
advanced CSS techniques to your content. Trying to work out a system for using
advanced selectors to style copy or using multiple animations in a sane fashion is
more dicult if all you have to play with is horrible, old-fashioned spaghetti code
(to see an example of horrible spaghetti code, look at the source of pretty much
any CMS or Wiki page).
And because one of this books goals is to provide a forward-facing approach
to web design, youll use HTML5 for all the markup in this book.
38
CHAPTER 2
Originally termed DHTML (dynamic HTML), such kludges have more recently
been handled in better ways using JavaScript libraries and the like. But the fact still
remains that they are kludges for the following reasons:
These kludges are used to create very common use cases: It seems ridiculous
for you to have to resort to hacks and overcomplicated custom implementations to implement them.
New semantic elements for dening common page regions, such as headers,
footers, primary navigation, distinct articles of content, gures, and so on.
<canvas> and its associated API for creating complex scripted graphics,
like animations.
Error handling to dene what should happen when badly formed markup
is used (missing closing tags, etc.)
39
HTML plays nicely with other open standards, so you can style your video
or other features with CSS or directly enhance their functionality with
JavaScript. With Flash, youd have to access and open the .a le and update
the code directly, because it doesnt communicate well with open standards.
A Flash movie is just a black box as far as the browser is concerned: It doesnt
understand the individual components inside the movie.
Having to download a Flash plug-in before you can start using content is no
big deal for tech-savvy geeks, but it can present a user-experience hurdle
for someone like my grandma.
In addition, most of the important HTML5 features have good support across
modern browsers, and you can provide alternatives and fallbacks for nonsupporting
browsers in many cases. Therefore, much of HTML5 is usable now in real-world
projects. Whats good enough for youtube.com is good enough for you, right?
Youll look at HTML5 features in more detail later in the chapter.
40
CHAPTER 2
BUILDING A TEMPLATE
At this point, lets start building a simple template that you can use to build your
CSS3 examples in. Start by creating a blank HTML le (you can see the nished
template in the example le template.html in the chapter2 code download folder).
HTML5 DOCTYPE
The rst line you need to add, as always, is the DOCTYPE. The HTML5 DOCTYPE
is a rather shorter proposition than youll traditionally be used to in HTML 4.01
and earlier. Get ready for it, wait, go!
<!DOCTYPE html>
Well, that was easy, wasnt it? As you know, traditionally DOCTYPEs have been
long shambling strings containing URLs, Klingon words, and other such unmemorables. For example, look at the HTML 4 Strict DOCTYPE:
<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01//EN
p http://www.w3.org/TR/html4/strict.dtd>
Why was it like this? Well, as far as I know the W3C had various interesting
ideas about what DOCTYPEs might empower you and the browser to do. But in
the end all DOCTYPEs really did was to put browsers in standards mode when
rendering a page of markup. The writers of HTML5 recognized this and decided
to whittle down the DOCTYPE to the shortest valid string of characters that would
put browsers in standards mode.
41
This should look familiar, although I want to draw your attention to the lang
attribute on the <html> element. It is good practice to set an overall language for
the entire document like this for accessibility purposes: Screen readers will handle
various languages dierently. For example, six is pronounced six in English
but seees in French.
You can also set the language of individual parts of the document by putting
the lang attribute on any element that it makes sense to do so. For example:
<p>As the French say, <span lang=fr>cest la vie</span>.</p>
Notice the two parts to the rst language example you saw: en-gb. The rst part
is called the primary language code, which unsurprisingly sets the overall language.
You can nd a full list of over 8000 of these codes at the IANA Language Subtag
Registry at www.iana.org/assignments/language-subtag-registry. The optional
second part sets a dialect of the primary language. So, for example:
You can set your own experimental languages using the x experimental primary
code:
<html lang=x-millsian-nonsense></html>
In HTML5 this line has been reduced to the following, which older browsers
will also understand: Add it just below the opening <head> tag:
<meta charset=utf-8>
42
CHAPTER 2
All you are interested in is the character set; hence, the HTML5 spec has been
written to allow this version. You dont need to specify that this is a content-type,
and you dont need to specify the mime-type if you are working with HTML5.
NOTE: Mime-types specify what type of content a file contains
for the benefit of browsers trying to understand what content it
is they are dealing with: in this case, text/html for HTML.
Here youve specied UTF-8, a universal character set that allows all characters
from all languages, or just about. It is best to stick to this character set unless you
have a very good reason not to.
Youll be using HTML but sticking to some XHTML syntax rules. Youll be
closing all open elements using lowercase for all elements and attributes,
and including quotes around most attribute values.
You dont need to write out attribute values in full for attributes whose values are the same as the attribute namefor example <input type=text
required>, not <input type=text required=required>.
You dont need to include trailing slashes to close empty elements, so youll
use the format <meta charset=utf-8>, not <meta charset=utf-8 />.
BUILDING A TEMPLATE
43
NOTE: Because the HTML5 spec is still not complete, it may change
to include or remove various elements; therefore, the HTML5
element fix may well need to be updated to remove elements or
include additional ones in the future.
44
CHAPTER 2
This ensures that all browsers should basically do what you want with your
CSSwell, except for IE. IE versions 68 need more help, because they wont style
unknown elements at all! For IE versions 68 to recognize unknown elements,
you need to create an instance of each unknown element in the DOM. Something
like this will do:
<script>
document.createElement(abbr);
document.createElement(article);
document.createElement(aside);
document.createElement(audio);
document.createElement(mark);
// add more elements as required
</script>
Notice that here youre not only dealing with block-level HTML5 elements, but
are also dealing with inline HTML5 elements like <mark> and HTML 4 elements
that simply arent supported in older versions of IE, such as <abbr>.
If you need to add a lot of these elements, there is a better way to deal with your
script. Replace the preceding script block with the following:
<!--[if lt IE 9]>
<script src=http://html5shiv.googlecode.com/svn/trunk/html5.js>
</script>
<![endif]-->
This applies the HTML5 shiv to your code, which is a script written by the
diminutively statured but huge-hearted Remy Sharp and hosted at Google Code.
It does the work of all the JavaScript described earlier, and more. Because it is
hosted at Google Code, you just have to link to it: You dont need to understand
the contents or worry about hosting it yourself and upgrading to the latest version
when it is updated.
BUILDING A TEMPLATE
45
To make the code even better, youve also put the <script> element inside an
IE conditional comment, so that only IE8 and earlier versions will download the
script (Ill talk a bit more about conditional comments later in the chapter). IE9
and 10 have much better HTML5 support; other browsers are unlikely to need it.
So for all those browsers, you can skip downloading the script and avoid an unnecessary HTTP request.
NOTE: Remys HTML5 shiv now also includes Jonathan Neals IE Print
Protectora script that fixes IEs problems with printing HTML5 content.
46
CHAPTER 2
VALIDATING HTML5
As you know, it is always a good idea to validate your nished HTML5 structure
before going further in your work to catch any DOM errors and the like that may
cause problems when you apply script and style to your content.
Henri Sivonen has created an experimental but perfectly usable HTML5
(+ WAI ARIA + SVG 1.1 + MathML 2.0) validator, which you can use to validate
your HTML5 documents regardless of the markup style used. You can nd this
validator at http://html5.validator.nu. Unfortunately, it doesnt pick up on specic
syntax stylesfor example, the XHTML style I recommend in this book. It wont
pick up on missing attribute quotes, attribute values, or closing slashes because
thats all valid in HTML5!
To mitigate this problem, I recommend that you add an extra step to your validation for now until available validators catch up. Visit the HTML Lint site athttp://
lint.brihten.com (Figure 2.1) to check your markup against several style options.
To check against the style I recommend in this book, check the following options:
Never omit closing tags. All nonempty elements must have a closing tag
(but empty elements dont need the trailing slash).
Simple booleans. Minimised attributes are allowed (those with a value the
same as the attribute name can be shortened to just the name: I showed the
example required instead of required=required earlier).
VALIDATING HTML5
47
Lets look at the HTML5 elements youll be using in this book, plus a few more for
good measure. An exhaustive treatment of HTML5 features is beyond the scope of
this book because youll be working with CSS3 styling, so most of the HTML5 APIs
are pretty much irrelevant in this context. Yes, you could build a fully functional
UI inside an HTML5 <canvas> element, but you wont be able to style it with CSS,
and youd be committing most of the same accessibility, usability, and SEO crimes
that Flash developers used to when building full Flash websites and the like. So,
dont even think about it!
In addition, most of the new elements youll look at are pretty self-explanatory,
and I know you are a clever bunch. All of the elements described in this section
are supported across all modern browsers with the exception of the Form elements,
which have been a bit slower to catch on.
NOTE: If you want a deeper treatment of HTML5, look no further than
Bruce Lawson and Remy Sharps excellent book, Introducing HTML5, 2nd
Edition (New Riders, 2011). For free tutorials, check out the Opera developer
community at http://dev.opera.com or the fantastic http://html5doctor.com.
CHAPTER 2
A controls attribute, which tells the browser to include the default controls
for the video. If you dont include this attribute, you can create your own
controls instead using the media elements API.
width and height attributes to specify the width and height of the video.
These work similarly to those for <img> except that if you specify dierent
values to the videos intrinsic values, the video doesnt resize; instead, it
letterboxes.
The <source> attributes point to the video les you want to play. You can instead
put a single src attribute on the <video> element to just point to one video le to
play, but this is currently a bad idea, because dierent browsers support dierent
video formats (for reasons too boring to get into here.) IE and Safari prefer MP4,
whereas Opera, Firefox, and Chrome prefer WebM. Therefore, you use two <source>
elements to point to both formats, and the browser loads the one it recognizes.
You dont have to include the type attributes, but it is a good idea to do so, because
these tell the browser what type of video each element points to, and it can select
the one it wants instantly. If you dont include the type attributes, the browser has
to download a few bytes of each le to identify one it recognizes, which is a waste
of time and eort.
NOTE: To easily convert between video formats, a good (and free)
choice is Miro Video Converter (www.mirovideoconverter.com).
49
<video> and <audio> both work in a similar way, however note that <audio>
doesnt include the attributes not relevant to it, like poster, width, and height.
Here is an <audio> example:
<audio controls>
<source src=audio/heavymetal.mp3 type=audio/mp3>
<source src=audio/heavymetal.ogg type=audio/ogg>
<!-- fallback content here -->
</audio>
The audio example produces a display like the one shown in Figure 2.3.
The fallback content implied by the HTML comments in the preceding examples
can be anything you like, whether it is a message telling users their browser doesnt
support HTML5 video/audio with a direct link to download the media, or better, a
Flash video/audio player fallback that can play the MP4/MP3 versions of your media.
Many other parts of HTML5 allow you to build in fallback content in this manner or will at least gracefully degrade to simpler content that people with older
browsers will still be able to use.
NOTE: Check out Simple HTML5 video player with Flash fallback and custom controls
by Bruce Lawson and Vadim Makeev (http://dev.opera.com/articles/view/simple-html5video-flash-fallback-custom-controls) to see the Flash fallback technique in action.
Or, check out Everything you need to know about HTML5 video and audio by
Simon Pieters (http://dev.opera.com/articles/view/everything-you-need-to-knowabout-html5-video-and-audio) for more details on <video> in general.
HTML5 <video> and <audio> represent a very exciting area that has many new
features to keep an eye out for (coming soon in a browser near you!); for example,
elements such as <track> for adding text tracks like subtitles, APIs for accessing
web cams and microphones (getUserMedia), APIs for generating and manipulating
sound (Web Audio API), and more.
50
CHAPTER 2
51
This is all well and good, but all these <div>s are semantically anonymous; the
browser doesnt see them as a main content column, dierent Tweets, and so on.
It just sees them as divs inside divs. You could upgrade this to HTML5, like so:
<section id=main>
<article>
<!-- post summary -->
</article>
<article>
<!-- post summary -->
</article>
<!-- etc. -->
</section>
<section id=tweets>
<article> ... </article>
<article> ... </article>
<article> ... </article>
</section>
Here, a supporting browser immediately knows that this contains two distinct
sections of content. Both contain distinct articles, which could quite sensibly be
syndicated separately, for example, in an RSS feed. This gives you a hint as to the
dierence between <section> and <article>. Both elements are for containing
content, but
52
CHAPTER 2
For more details and examples covering these elements and other HTML5
semantics, read New structural elements in HTML5 by Bruce Lawson and my
bad self at http://dev.opera.com/articles/view/new-structural-elements-in-html5.
53
Pretty much every website or app has these. The header (or masthead) contains the site logo, title, and so on, and the footer contains site-wide content like
copyright, accessibility statement, and so forth. The HTML5 creators recognized
this and introduced the following unambiguous semantic elements to do the job:
<header></header>
<footer></footer>
If you refer back to my sample blog pages, youll see some examples of <header>
and <footer> usage. Note that there are some inside <article>s and <section>s.
This is perfectly allowed: You can do this to specify headers and footers just for
subsections of your content rather than the whole site. You can therefore have
multiple <header>s and <footer>s in a single document.
<ASIDE>
The <aside> element is really a special kind of <section>, specically tasked
with containing secondary information related to the main content of the site
that doesnt t within the main ow. Good examples include a biography of the
author of that page, a mini interview with the author, or a bibliography/references
and further reading. It can, however, also be secondary content on the site, like
a typical sidebar, a blogroll, or a list of other blog posts on the site you might be
interested in (even if they are not posts related to the main content). The list of
Tweets in my previous example is suitable as an <aside>.
54
CHAPTER 2
You can also quite happily use an <aside> element inside an <article> too, as
long as it contains content tangentially related to just that article. A biography of
the author of just that article or further reading to go on to after youve nished
that article would be suitable. The element simply looks like this:
<aside></aside>
<NAV>
The <nav> element was created to house the documents primary navigation,
whether that is a standard list-o-links nav bar, a drop-down menu, or even a
search box. It shouldnt be used for secondary navigation bars, related reading links,
and so on. You can put it anywhere you like in your markup that makes sense. In
my main blog site example, its inside the <header>:
<header>
<nav>
...
</nav>
</header>
There are many advantages to having the documents primary navigation inside
an unambiguous semantic element. For example, when browsers and screen readers start to recognize this element, it will make accessibility hacks like skip to
navigation links a thing of the past.
55
<HGROUP>
<hgroup> has been created with one specic purposeto allow you to put two (or
more) headings right next to one another and have them count as only one heading
for the purposes of the document structure/hierarchy (the group will be counted
as a single heading of the same rank as the highest-ranked heading in the group).
This is especially useful in a situation in which you want to mark up a heading
with a subtitle or strapline above or below it, because you can now do so without
breaking the document structure:
<hgroup>
<h1>Cats and dogs</h1>
<h2>Your local store for pets and pet supplies</h2>
</hgroup>
NOTE: Heading levels in HTML5 are determined not by the number after the h (<h1>, <h2>,
etc.) but by their level of nesting inside so-called sectioning elements, worked out by the
HTML5 outline algorithm. For more information about HTML5 sectioning and outlines, read Mozillas excellent article Sections and Outlines of an HTML5 Document
(https://developer.mozilla.org/en/Sections_and_Outlines_of_an_HTML5_document).
56
CHAPTER 2
But this feels a bit dirty, a bit grubby, and a bit amoral. It is almost completely
semantically devoid, with nothing to let a browser or screen reader know this is a
gure and caption, and certainly nothing to associate the caption with the gure!
HTML5 oers a much better solution:
<figure>
<p><img src=figure.png alt=This is a picture containing
p important content></p>
<figcaption>This is a very important picture.</figcaption>
</figure>
This code provides a consistent, semantic way of dening a gure and associating a caption with it. Note that the gurethe image in this casecan be
anything you want. It could be a few images, videos, a <canvas>, or a combination
of content types.
<TIME>
<time> quite simply provides you with a decent semantic way of marking up a date
The datetime attribute contains an ISO-standard date and time, which is unambiguous and machine-readable. The text inside the tags, on the other hand, can
be any representation of the time and date you want and thus can be customized
to suit the style of your site. You could also write:
<time datetime=1978-06-27>June 27 1978</time>
<time datetime=1978-06-27>My birthday</time>
<time datetime=1978-06-27>Nineteen seventy-eight, June the
p twenty-seventh</time>
57
In addition, you can add a time zone adjustment. To make the previous example
Central European Time (CET), youd do this:
<time datetime=1978-06-27T23:58Z+01:00>Two minutes to midnight,
p on my birthday, CET</time>
There is one last bit of <time> syntax to discuss, which is particularly useful
to the blog example: If you want to specify that a declared time is the publication
date of the content it resides within, you can use the pubdate attribute, like so
(although the removal of this attribute from the spec is being debated at the time
of this writing, so it might disappear):
<time datetime=1978-06-27 pubdate>27th June 1978</time>
A number of people complained in the past that they were not able to mark
up imprecise times using <time>, like you would in documents like museum catalogues. This has been updated to mitigate this problem somewhat: Now you can
do things like this:
58
CHAPTER 2
<MARK>
The <mark> element is designed to highlight words inside a section of content that
dont require emphasis in their meaning; for example, they arent important keywords that need <strong> or technical terms that would typically be pronounced in
an alternate voice. But they do require highlighting to indicate their signicance in
another context. A very good example is highlighting search terms in a list of search
results, or tags on a site, or particularly useful parts of a set of quotes contained
within some research documents. For example, if you were using a music search
application, you might want to mark up a results page like this (see mark-example.
html in the chapter2 code download folder):
<h1>Results for search term <mark>love</mark>:</h1>
<ul>
<li><a href=/songs/allyouneedislove/>All you need is
p <mark>love</mark></a> by The Beatles</li>
<li><a href=/songs/lovewilltearusapart/><mark>Love</mark> will
p tear us apart</a> by Joy Division</li>
<li><a href=/songs/lovehatelove/><mark>Love</mark>, hate,
p <mark>love</mark></a> by Alice in Chains</li>
</ul>
For more information about <mark>, read Mike Robinsons article Draw attention with mark (http://html5doctor.com/draw-attention-with-mark).
59
HTML5 also adds a few specialized text inputs, which expect more specic
types of data:
<input type=url>
<input type=email>
<input type=tel>
60
CHAPTER 2
These dont look very interesting in desktop browsers until you combine them
with HTML5s built-in data validation. Although if you try them on a mobile platform, such as iOS or Android, youll notice that they give you special sympathetic
keypads more tailored to lling in those types of dataa nice usability plus for
your users.
You can specify that any form input must be lled in before the form can be
submitted by adding the required attribute:
<input type=text required>
The dierent types of text input will accept dierent types of data, automatically feeding back errors to the user when the data isnt correct for those inputs
upon submission (as shown in Figures 2.7 and 2.8):
<input type=text required>
<input type=url required>
You can also narrow down the range of data that will be accepted in a form
input using the min, max, and pattern attributes:
<input type=number min=1 max=100>
<input type=text pattern=[1-6]{3}>
61
Figure 2.9 shows usage of the new number input type and another simple text
eld. The rst example will accept as valid data any number between 1 and 100,
whereas the second one has a custom regular expression specied so that only
three concatenated digits of between 1 and 6 will constitute valid data.
I added some rudimentary styling to my example so that it looks a bit less horrible than the standard HTML form looks. Youll notice as you play with it that
when you enter data into the form, it turns green as it becomes valid but is black
otherwise. I did this using the :valid CSS3 pseudo-class, which youll learn more
about in Chapter 9.
NOTE: For more information on HTML5 form elements, read
New form features in HTML5 by Patrick Lauke and me at
http://dev.opera.com/articles/view/new-form-features-in-html5.
<CANVAS>
Last but not least in this section, youll briey explore HTML5 <canvas>, which
allows you to manipulate bitmap graphics via script. The <canvas> element doesnt
do much on its own. It creates a static space on the screen with dimensions that
you specify (see simple-canvas.html in the chapter2 folder):
<canvas id=canvas width=480 height=320>
<!-- fallback content here -->
</canvas>
62
CHAPTER 2
This code creates a blank bitmap image, which you can draw on and manipulate using the Canvas API. The magic comes when you target the canvas using
JavaScript via its ID:
var c = document.getElementById(canvas);
You then get the drawing context of the canvasin this case a two-dimensional
imageusing the following line (you can also draw 3D images in <canvas> using
WebGL):
var context = c.getContext(2d);
You can then start using properties of the context youve created to draw onto
the canvas. For example:
context.fillStyle = rgb(0,0,200);
context.fillRect (100, 50, 100, 150);
Here you select a blue color and draw a lled rectangle of that color that is
100px by 50px in size at coordinates (100,150) on the canvas. The top-left corner
of the canvas (0,0) is the origin (Figure 2.10).
TIP: Canvas has many more primitives available, such as full-text drawing capabilities and the ability to import images and video frames, among many others. Covering
more of these primitives is beyond the scope of this book. For good <canvas> tutorials, hop on
over to Mozillas Canvas tutorial page (https://developer.mozilla.org/en/Canvas_tutorial).
For more on WebGL, a good place to start is Luz Caballeros article An introduction to WebGL
(http://dev.opera.com/articles/view/an-introduction-to-webgl).
63
Many people favor the use of CSS resets in their work to get rid of the annoying
dierences between browser default styles. Such pieces of style are usually only tiny
but still annoying when trying to get CSS layouts to work consistently. And some
are not so tiny; for example, the dierences between default form styling across
browsers or margins and padding on the <html> and <body> elements, which you
inevitably need to remove to get rid of unsightly spacing on the outside of your page.
CSS resets have traditionally been the answer to these style issues. CSS resets
remove most or all default CSS styling, leaving you to add your own styles and be
condent that you are much less likely to get weird behavior between browsers.
However, they are not perfect. CSS resets tend to be overzealous, removing
every default style and leaving you with more work to add a lot of necessary styles
back in. In addition, they inevitably clutter your styles: You can hide them in an
external stylesheet, but youll still see loads of crazy declarations when it comes
to debugging your CSS using a debugging tool.
A much better option is to use normalize.css, which was written by Nicolas
Gallagher (http://nicolasgallagher.com/about-normalize-css). Instead of removing
everything, normalize.css makes default styles more consistent across browsers,
xes bugs, and makes subtle improvements.
You simply download the le from https://github.com/necolas/normalize.css,
attach it to your page, and voil! For those interested in learning more, the About
page referenced previously and the CSS le contain extensive comments and
examples.
Ive included this le in the template, and it is used in most of the examples
in this book.
64
CHAPTER 2
Youve done a lot so far in the chapter in terms of building up a template you can
use to write HTML5 and CSS3 into with condence, and going on a quick tour of
the new HTML5 elements available to you. Lets now return to further building up
your toolkit for the coming events that shall unfold as you journey through the
book. In this section youll look at the dierent JavaScript libraries youll be using
to build in support for various CSS3 features that lack support in older browsers,
most notably older IE versions. These libraries are often referred to as Polylls.
NOTE: I suggest that you consult the websites of these different projects,
download the libraries so they are ready for you to start experimenting with
(many of them have online copies available that can be linked to, but it
is also useful to have them available for offline experimentation), and
check out the available documentation. I wont include all of these in my
default template, because you wont need all of them in each project.
CSS3-MEDIAQUERIES-JS
css3-mediaqueries-js is a nifty little library written by Wouter van der Graaf, which
transparently adds support for Media Queries to browsers that dont have them
natively. The transition is a bit clunky when you trigger a media query by resizing
a browser window; but dont worry, users are very unlikely to ever do this or in
fact know what a browser is (or care). For information about css3-mediaqueries-js,
check out these sites:
Home. http://code.google.com/p/css3-mediaqueries-js
Download. http://code.google.com/p/css3-mediaqueries-js/downloads/list
Respond.js, written by Scott Jehl, is another library for adding in Media Query
support to nonsupporting browsers. It specically adds support for min-width
and max-width Media Queries. Find out more about it at its Github page: https://
github.com/scottjehl/Respond.
65
CSS3PIE
CSS3PIE adds support for CSS3 bling features to older versions of IE that dont
support them. It is part of Sencha Labs and was originally developed by Jason
Johnston. The current feature support list includes:
FIGURE 2.11 A typical, simple
website directory structure.
border-radius
box-shadow
border-image
The .htc le works by being applied to the CSS properties you want to aect in
the form of a behavior property. Youd think that youd need to do this by going
up a level and then down a level again to get from .css to .htc:
behavior: url(../script/PIE.htc);
But you dont. The .htc le is referenced from the CSS but actually acts on the
HTML le after the CSS has been applied to it, so you need to reference it as if it
were being referenced from the HTML le, like so:
behavior: url(script/PIE.htc);
66
CHAPTER 2
Documentation. http://css3pie.com/documentation
MODERNIZR
Modernizr is the daddy of all feature-detection libraries. It allows you to detect
support for desired HTML5 and CSS3 features, and then serve up alternative styles
and scripts to optimize the user experience in nonsupporting browsers. Created by
Faruk Ate, Paul Irish, and Alex Sexton, it has extensive documentation available,
and Modernizr 2.0 and later allow you to download a customized version that only
contains the feature tests you need for your particular project.
For information about Modernizr, check out these sites:
Home. http://modernizr.com
Documentation. http://modernizr.com/docs
Download/customize. http://www.modernizr.com/download
SELECTIVIZR
Written by Keith Clark, and mentioned in the previous chapter, Selectivizr is a small
utility that sits on top of an existing JavaScript library, such as jQuery or MooTools,
and adds support for CSS3 selectors/pseudo-classes to nonsupporting versions of
IE (68). The Home/Download page is at http://selectivizr.com.
67
IE CONDITIONAL COMMENTS
Many people saw IE conditional comments as bad, because they are a proprietary feature invented by Microsoft to allow developers to target HTML, CSS, and
JavaScript just at specic versions of IE. These conditional comments could be used
for all kinds of evil and represent the sort of feature that was probably originally
invented by He-Mans arch nemesis, Skeletor (he also invented IE behaviors, the
IE6 rendering engine, and soap operas).
But they are also very useful for modern web development practices if you
need to target some CSS specically at older versions of IE to x rendering bugs
and want to prevent browsers that dont need those xes from wasting bandwidth
or HTTP requests. Here is a reminder of what they look like. In my template Ive
included this code:
<!--[if lt IE 9]>
<script src=http://html5shiv.googlecode.com/svn/trunk/html5.js>
</script>
<![endif]-->
version of IE.
if lte IE 8. Gives the content to the specied version of IE and all earlier
versions.
68
CHAPTER 2
You can also use gt and gte (greater than and greater than or equal to) in
the same way, but you will be much less likely to use these. Most likely, youll use
IE conditional comments to:
Serve CSS to x IE-specic CSS bugs that threaten to make your lovingly
crafted layouts crumble. The most obvious xes that spring to mind are
serving older IE versions dierent width and height values to compensate
from the broken box model and giving various layout features hasLayout
to make those features behave properly in IE.
Bruce Lawson has written a great article that expands this topic further called
Supporting IE with conditional comments (http://dev.opera.com/articles/view/
supporting-ie-with-conditional-comments). There is also an article on MSDN
called About Conditional Comments (http://msdn.microsoft.com/en-us/library/
ms537512.aspx) that contains some pretty dreadful outdated web development
ideas but provides a good reference for all of the IE conditional syntax available.
NOTE: IE10 completely ignores conditional comments, so you cant
use them to direct code only to IE10. This isnt as bad as it sounds:
IE10 has really good standards support, worthy of a modern browser,
so chances are you wouldnt need conditional comments anyway.
WRAPPING UP
After reading this chapter, you are up to speed on your markup structures and have
built a toolkit you can rely on. Now you can stretch and relax a bit.
When youre ready to continue your work and start looking into CSS3 enhancements for text and fonts, turn the page when you hear the tone. (If youve not bought
the interactive version of the book, invent your own tone and hum it to yourself.)
WRAPPING UP
69
3
SPICING UP YOUR
FONTS AND TEXT
71
UP THE PYTHONS!
In my quest to create examples for this book that were informative and entertaining, and at least remotely based in the real world, I created a tribute site for Monty
Pythons take on the familiar Arthurian legend, Monty Python and the Holy Grail
(Figure 3.1).
Youll nd a rather chaotic but entertaining nished version in the king-arthurblog-example folder in the code download. Lets walk through how I applied custom
fonts to the site.
72
CHAPTER 3
For years, the lack of web-safe fonts available for web designers to use on their
sites was a complete nightmare. Fonts like Times New Roman, Arial, Courier New,
and Georgia can go quite a long way, but for custom headings or logos, you had to
resort to tricky techniques like image replacement or even siFR or Cufon (which
replaced text using Flash movies or SVG containing custom fonts).
Like a ray of sunshine, CSS2.1 introduced Web Fonts. Then it was dropped due
to lack of agreement from browser vendors. Then it was reintroduced in the Web
Fonts module, which was later subsumed into the Fonts module (www.w3.org/TR/
css3-fonts), and lo, there was much rejoicing. This module contains functionality
that allows you to specify custom font les to download along with your website,
and then use them in the same way as any other font. You rst need to specify the
font to download using a @font-face block, like so:
@font-face {
font-family: myfont;
src: local(myfont),url(myfont.ttf),url(myfont.woff);
font-weight: bold;
font-style: italic;
}
A src declaration to point to the actual font(s) you want to use. This can
point to a single font le or a comma-delimited list of as many dierent fonts
as you want. The browser will go through the list until it can nd a format
it recognizes. The fonts can be local, such as local(foo), or external
downloadable fonts, such as url(http://example.com/path/to/foo.ttf).
73
will be used; otherwise, setting bold will have no eect, and you should set
it to normal instead or not include it.
Of course, nothing is ever this simple in web design. Those dastardly browser
vendors havent been able to agree on a single font le format to support until
recently, and you also need to think about older browsers, which use older font
formats. Table 3.1 gives you an idea what current font format support looks like
across browsers.
TABLE 3.1 Browser Support Matrix for Font Formats
BROWSER/
FONT FORMAT
SUPPORT @
FONT-FACE
TRUETYPE
(.TTF)
OPENTYPE
(.OTF)
EMBEDDED
OPENTYPE (.EOT)
SVG
Opera
Since 10
Yes
Yes
No
Yes
Yes
Firefox
Since 3.5
Yes
Yes
No
No
Yes
Safari
Since 3.1
Yes
Yes
No
Yes
Yes
Chrome
Since 4
Yes
Yes
No
Yes
Yes
Internet
Explorer
.eot since 4,
.woff since 9
No
No
Yes
No
Yes
iOS
SVG up to 4.1
Yes
Yes
No
Yes
Yes
Android
Since 2.2
Yes
Yes
No
Yes
No
Chrome Mobile
Since beta
Yes
Yes
No
Yes
Yes
Opera Mobile
Since beta
Yes
Yes
No
Yes
Yes
Fortunately, all browser vendors have now agreed on supporting the new W3C
WOFF standard (www.w3.org/TR/WOFF), which is a container/compression format
for OpenType and TrueType fonts that can also contain licensing information and
suchlike. It is a winner all around, resulting in smaller le sizes and happier font
foundries. It has been supported for ages in Firefox and Chrome, Safari since version 5.1, Opera since version 11, and Internet Explorer (IE) since version 9.
74
CHAPTER 3
Older versions of most browsers dont matter as much anymore because they
tend to be updated regularly. However, older versions of IE still need to be supported; many IE installs wont be updated anytime soon (49 percent of the worlds
computers still run Windows XP, which can only run IE version 8 and earlier).
The good news is that IE has supported Microsofts proprietary Embedded
OpenType format since version 4, meaning that old versions of IE can work with
custom fonts quite well.
dafont.com
myfonts.com
fontsquirrel.com
I eventually settled on three from Font Squirrel that would work out for this
demo:
(www.fontsquirrel.com/fonts/UglyQua)
(www.fontsquirrel.com/fonts/Kells-SD)
(www.fontsquirrel.com/fonts/Genzsch-Et-Heyse)
You might think that creating syntax and dierent font formats to provide
cross-browser support would be a nightmare, given what I said earlier. But Font
Squirrel provides two great features that will help you out here. The rst one is
the ready-made @font-face kits page (www.fontsquirrel.com/fontface), which
contains all the font les and code youll need to get fonts working cross-browser.
But what if you want to customize one of Font Squirrels fonts or make one
of your own fonts work cross-browser? The second featurethe @font-face
generatorwill come to your rescue. Just follow these steps to create what you need.
75
1. Download some fonts you want to use. Generally, they will be in .otf or .ttf
format, but either will do.
2. Go to the @font-face generator at www.fontsquirrel.com/fontface/generator.
3. Click the Add Fonts button, and select one of your font les. Repeat this
step until youve added all the fonts you need to the list.
4. Select the Yes, the fonts Im uploading are legally eligible for web embedding check box. The fonts I chose from Font Squirrel are free for commercial
web use, but youll nd many that are not, so be careful here.
5. Click the Download Your Kit button, and save the resulting ZIP download
to a location youll remember.
At this point youll have a ZIP le full of dierent format fonts, HTML, CSS, and
other shizzle. For each font you want to use, copy the font les (.eot, .svg, .ttf, and
.wo) to a fonts subdirectory in your working directory. Then open stylesheet.css
and copy all the CSS from there to the top of your CSS. It needs to be at the top so
the fonts will be available when you apply them later on. At the top of main-style.
css in my King Arthur example, youll nd one of these structures for each font:
@font-face {
font-family: GenzschEtHeyseRegular;
src: url(genzschetheyse-webfont.eot);
src: url(genzschetheyse-webfont.eot?#iefix)
p format(embedded-opentype),
url(genzschetheyse-webfont.woff) format(woff),
url(genzschetheyse-webfont.ttf) format(truetype),
url(genzschetheyse-webfont.svg#GenzschEtHeyseRegular)
p format(svg);
font-weight: normal;
font-style: normal;
}
76
CHAPTER 3
This looks slightly scary compared to the simple @font-face example you
saw earlier, but dont worry; you dont really need to know exactly what is going
on here. It is termed the Bulletproof font syntax, and it is guaranteed to support
most if not all browsers youd need to support. If you want more details on why
this structure works, read Bulletproof @font-face syntax by Paul Irish athttp://
paulirish.com/2009/bulletproof-font-face-implementation-syntax.
With the font specied in this manner, you can then use it in your code in the
standard way:
h1 {
font-size: 6em;
font-family: GenzschEtHeyseRegular, serif;
}
77
WEB-FONT PROBLEMS
Unfortunately, web fonts are not without their problems. If you really want a professional look to your sites text, you need to consider your font choices carefully
and test them thoroughly. The following problems need considerable thought.
FLASH OF UNSTYLED TEXT (FOUT)
FOUT refers to the way some browsers behave (namely Opera, Firefox earlier than
version 4, and IE earlier than version 10) when they encounter a web font; that is,
they rst render the text without the font applied. Then they download the font
le and apply it to the text. This can create a rather jarring and unsightly eect,
which youve probably witnessed at some point.
There are a couple of solutions to this problem. One solution is the webfont
loader from Google (http://code.google.com/apis/webfonts/docs/webfont_loader.
html), which is a JavaScript API with quite a few features available. You can include
it in your page using the following script:
<script src=//ajax.googleapis.com/ajax/libs/webfont/1/
p webfont.js></script>
You then need to point to the fonts in question by putting scripts like the following in your documents <head>; the scripts need to be included before your
style declarations:
<script>
WebFont.load({
custom: {
families: [MEgalopolisExtraRegular,
p SansationRegular],
}
});
</script>
78
CHAPTER 3
The JavaScript targets the fonts and the stylesheets that refer to them. It adds
classes to the documents <html> tag to indicate dierent stages of web-font loading.
Before a web font has loaded, the class wf-loading is included. During this stage,
you could hide the text using a descendant selector:
.wf-loading h1, .wf-loading p {
visibility: hidden;
}
When the font has nished loading and is ready to be used, the wf-loading
class is removed, and a series of -active classes are included instead. Now you
can include the fonts as desired, like so:
.wf-megalopolisextraregular-n4-active h1 {
visibility: visible;
font-family: MEgalopolisExtraRegular, arial, sans-serif;
}
.wf-sansationregular-n4-active p {
visibility: visible;
font-family: SansationRegular, arial, sans-serif;
}
If the font fails to load for some reason, a class of wf-inactive is included
instead, and you can point to a fallback font:
.wf-inactive body {
visibility: visible;
font-family: sans-serif;
}
79
ADDED BANDWIDTH
Web fonts have many advantages over image replacement in terms of exibility
and the power you have to control your designs. They can also result in a smaller
le size, depending on your situation. But you really need to think carefully about
using them if, for example, you are only using a single font for a single heading at
the top of your site.
In King Arthurs blog I only used the Genzsch Et Heyse font for the <h1> on
each page. The EOT and TTF versions are 66 kb; the WOFF version is 41 kb; and
the SVG version is a whopping 209 kb (although this is only needed by users of
old versions of iOS). Some single font les can range in size from 300 to 400 kb.
And this is made worse by the fact that some browsers erroneously download
more fonts than they need (see the Browser bugs section later in this chapter).
This problem will be mitigated as time goes onas old IE versions die out and
all browsers support WOFF. But it wont go away completely. Some font les will
just be very big, especially when you consider CJK (Chinese, Japanese, Korean)
languages, which can feature literally thousands of characters; such fonts can
weigh in at several megabytes.
NOTE: If font file size is a problem in your situation, you could create a font
file containing just the characters you need using a program called Fontforge
(http://fontforge.sourceforge.net). In addition, a property in the spec called
unicode-range allows you to specify which characters you want to load from
the font file, making the bandwidth problem even easier to solve. But at
the time of this writing, unicode-range was only supported in WebKit, so I
decided not to talk about it in detail.
So determine whether you really need a web font or if youd be better o with
image replacement, or even a web-safe font, such as Times New Roman. Just
because you can use web fonts doesnt mean you have to!
80
CHAPTER 3
Another problem youll come across with web fonts fairly frequently is that web-font
rendering can be pretty awful with certain fonts on certain browsers, especially
IE on Windows.
Windows uses a technology called ClearType, which uses subpixel rendering
to make font rendering appear smoother. If this option is not enabled, the font
will look worse on Windows, and its not something you can control. That said,
this technology has been around forever (it is turned on by default in most modern Windows systems but not XP, unfortunately), but it still doesnt look appealing for larger font-size rendering compared to Apples anti-aliasing on Mac OS X
(Figure 3.3). For more on this rendering problem, be sure to read Jon Tans excellent
post Display type and the raster wars (http://jontangerine.com/log/2008/11/
display-type-and-the-raster-wars).
Some modern browsers do font anti-aliasing as well, which can help when
rendering. Chrome, IE, and Safari use the operating system default, whereas Firefox
seems to use its own font-smoothing system. Opera doesnt do any anti-aliasing
of its own.
Because there are so many variables, the only way to approach this rendering
problem is to do a decent amount of testing across Windows XP, Vista, Windows7
and later versions, including the full gamut of modern browsers, as well as IE68.
See if the quality of the font rendering is acceptable to you and your clients, and
explain the potential problems with Windows.
81
FIGURE 3.4 Glyphs that dont appear inside your web font will
be rendered in the system default, if youve specified it as a
fallback in your font stack.
If your headings look ghastly, one potential solution is to set the heading font
sizes in pixels just on the problem browsers. This has been known to help. You
could do this via an IE conditional comment perhaps or by using browser sning.
Another tip is that when you generate your @font-face kit in Font Squirrel, as
you saw earlier, you should click the Expert option, and then choose Rendering>
Apply Hinting > Improve Win rendering.
QUALITY AND WIDESPREAD USAGE
Free fonts are all well and good, but the really decent fonts are few and far between.
Many free fonts have a small range of glyphs included in them, which is not too
bad if you are using the glyphs for headings that you can control, but it can be
disastrous if you are using them on user-generated content, like a blog. If you
have specied a fallback font, the characters that dont appear in your web font
will appear in the fallback font. For example, in Figure 3.4 Ive replaced the K in
Knights in my examples <h1> with a registered trademark symbol that doesnt
appear in the GenzschEtHeyseRegular font.
If you dont specify a fallback font stack, certain characters could easily be
rendered as horrible little blank spaces or ugly squares (Figure 3.5), because the
web font does not contain those glyphs.
82
CHAPTER 3
In addition, the good free fonts are likely to be used a lot. For example, Museo
and Chunk Five (Figure 3.6) have been used so many times that they are becoming
tiresome, which is a shame because they are great fonts.
If font quality and overuse are problems in your work, you could consider
using a paid font service for better quality and more varied fonts (see the later
section Commercial Font Services). That old adage of you get what you pay for
was never truer than today.
BROWSER BUGS
At the time of this writing (and perhaps for a good while after), browser bugs can
impair the eciency of web-font usage, so you should be mindful of them as you
work with @font-face. Lets quickly look at the bulletproof @font-face syntax
again:
@font-face {
font-family: myfont;
src: url(myfont.eot);
src: url(myfont.eot) format(embedded-opentype),
url(myfont.woff) format(woff),
url(myfont.ttf) format(truetype),
url(myfont.svg#myfont) format(svg);
font-weight: normal;
font-style: normal;
}
83
IE9 and later support the WOFF format, but they also support EOT. If you
are using syntax like that in the preceding code, IE9 and later will download the EOT le and use it (browsers go through the list and use the rst
font they recognize). You can nd a more detailed reference for xing IE9
font problems at www.fontspring.com/blog/xing-ie9-font-face-problems.
If your web fonts are failing in Firefox or IE and you are serving your fonts
from a dierent domain, it might be because they have a stricter sameorigin policy than most. A workaround is to serve the fonts using the
Access-Control-Allow-Origin HTTP header dened in CORS (see http://
dev.opera.com/articles/view/dom-access-control-using-cross-originresource-sharing for more details).
If you are using WOFF and your fonts are being served from IIS, youll need
to add a MIME type: WOFF doesnt have a MIME type, but font/x-woff
will work.
Never declare @font-face rules for fonts you dont end up using: IE 68
will download them all anyway.
Opera 11.5 and earlier on the Mac, unfortunately, download the EOT font as
well as the WOFF font that it actually uses, wasting some bandwidth. Lets
hope this will be xed soon.
84
CHAPTER 3
If you want to buy fonts outright and host them yourself, there are a number
of dierent shops to visit, but the ones Id recommend are:
Myfonts.com
Fontspring.com
Fontshop.com
The three best options for commercial-hosted font services at the time of this
writing are
WebType (www.webtype.com). Another quality font service set up in collaboration between a number of type experts.
All the hosted font services work in roughly the same way: You sign up for the
service, specify which domain(s) you want the fonts used on, paste some custom
JavaScript and/or CSS into the <head> of the pages you want the fonts used on, and
then choose the fonts you want to use on the web interface of the service.
Youll then be given all the CSS you need; they are very easy to use. Another
useful feature of all three is that you are free to test them to a certain degree. Fontdeck gives you full access to all font services free of charge, but only the rst 20
IP addresses that access your sites will see your fonts. Typekit allows you to use a
limited set of its fonts on one website with limited page views. WebType gives you
a 30-day free trial with each font.
When you start using these services, the benets become very clear: You have
access to high-quality fonts with full glyph sets and multiple weights and variants.
For example, you can make proper use of the following and more:
font-weight: 200;
font-weight: 300;
font-weight: light;
font-weight: black;
85
You can achieve a lot using dierent weights of just one typeface, as evidenced
by excellent sites, such as Simon Collisons personal site, colly.com (Figure 3.7).
All the fonts have agreed licenses for using them on the web. The font les are
optimized as much as they can be to reduce le size, and although your users will
still have to download them to use them, you can place the server burden on the
font service, which reduces your bandwidth burden.
Each service has advantages and disadvantages: I prefer Fontdeck because it
is slightly more intuitive to use than the others. Also, the restrictions are not as
limited for testing purposes; you pay per font, and it doesnt require JavaScript like
Typekit does. It might work out to be slightly more expensive, but the costs are
pretty minor either way.
NOTE: You can see some examples of Typekit and Fontdeck in action athttp://
people.opera.com/cmills/css3book/typekit_example.html and http://people.
opera.com/cmills/css3book/fontdeck_example.html. Ive also included these
examples in the chapter3 code download folder, but youll only see the
font examples working on the preceding URLs, because my Fontdeck and
Typekit examples were tied to that domain at the time.
86
CHAPTER 3
Now that youve gone through @font-face in some detail, including cross-browser
support and mitigation of potential problems, and looked at commercial and free
font supply options, lets have even more fun and look at some of the rather cool
text eects CSS3 oers. (Ill cover the CSS3 typography details at the end of the
chapter, because typography is a bit more experimental and cutting edge.) Table3.2
shows the browser-supported CSS3 text features.
TABLE 3.2 Browser Support Matrix for CSS3 Text Features
BROWSER
TEXT-SHADOW
TEXT-OVERFLOW
WORD-WRAP
HYPHENATE
Opera
Since 9.5
Since 10.5
No
Firefox
Since 3.5
Since 7
Since 3.6
Safari
Since 3.1
Since 3.2
Since 3.1
Chrome
Since 4
Since 4
Since 4
No
Internet Explorer
Since 10
Since 6
Since 5.5
iOS
Since 3.2
Since 3.2
Since 3.2
Android
Since 2.1
Since 2.1
Since 2.1
No
Chrome Mobile
Since beta
Since beta
Since beta
No
Opera Mobile
Since 10
Since 10
No
Opera Mini
No
Since 5
No
TEXT SHADOWS
The CSS3 text-shadow property allows you to programmatically create drop shadows on text and is supported across all modern browsers without prexes. It is
very useful to be able to create a exible drop shadow on text without relying on
JavaScript, text duplication, or any other such silliness. You can use drop shadows
for a variety of eects but generally for highlighting text, giving it depth, and making it stand out.
87
The rst two unit values set the horizontal and vertical oset of the shadow
from the original text, respectively. Positive values move the shadow right and
down, whereas negative values move the shadow left and up. You can pretty much
use any CSS units for these values. But generally, using pixels is recommended,
because ems and percentages can make shadows move, and you probably dont
want the eect varying with the font size in most cases.
The third unit value sets the amount of blur applied to the shadow. You can
set this to a large value to produce an indistinct shadow below the text or set it to
1px to just make it act as an outline highlight (in which case you could just delete
the third value altogether, because it defaults to 1px when not specied explicitly).
Lets run through a couple of examples. The preceding code is used in my King
Arthur blog example to give the <h2>s not appearing in a background a contrasting
highlight to make them more visible (Figure 3.8).
88
CHAPTER 3
You can also use a more subtle color that blends better with the background
behind the text to give the text an embossed eect, and use negative oset values
to change the light direction (Figure 3.9):
h2 {
text-shadow: -1px -1px 1px gray;
}
Or perhaps create a much bigger blur and oset the text to make it look like it
is about to y o into space (Figure 3.10):
h2 {
text-shadow: 5px 5px 10px black;
}
Youll be ecstatic to know that you can also use multiple text shadows on the same
selector, like so:
text-shadow: 0
0
0
0
0
0
0
0 2px #000,
0 2px #aaa,
0 4px #999,
0 6px #888,
0 8px #666,
6px 6px rgba(0,0,0,0.5),
8px 20px rgba(0,0,0,0.5);
89
You just write each additional text shadow one after the other inside the same
property separated by commas. The preceding example produces a rather pleasing, raised 3D text eect (Figure 3.11), which blends in well with any backgrounds
behind it because RGBA colors are used for the outermost shadows.
90
CHAPTER 3
+ overflow: hidden;
+ text-overflow: ellipsis
FIGURE 3.13 The effect of
word-wrap: break-word;.
91
FIGURE 3.14
text-align: justify
CONTROLLING HYPHENATION
Hyphenation has long been a sore point on the web. If you want a body of text
to sit neatly in a containing box, the obvious solution in print would be to justify
the text and hyphenate words as required to make the column work without too
many long gaps. This is standard fayre, especially in newspapers and magazines.
But on the web, this treatment is dicult to achieve: You cant just hyphenate
words and add line breaks as needed unless you can control the exact copy, fontsize, font, containing box, and so forth. And this will almost never be the case; it
just isnt how the web works! Instead, you have to settle for left, right, or centred
text; text-align: justify usually looks terrible, especially if you have lots of big
words in your copy. Figure 3.14 illustrates this perfectly.
CSS3 comes to the rescue with the hyphens property. The three possible values
include:
92
CHAPTER 3
manual . Words are hyphenated onto separate lines, only there are linebreaking characters present within them (like a hyphen character or a soft
hyphenfor example, ­).
FIGURE 3.15
Witness the power of my
automatic hyphens!
Ive hidden the overowing text and set text-overflow: ellipsis as with
previous examples. However, this time Ive also set the text to be justied and set
automatic hyphens. This produces an eect like that shown in Figure 3.15.
NOTE: In the future youll be able to specify exactly which character the
browser uses for its automatic hyphens using the hyphenate-character
property; for example, hyphenate-character: \2010;. The values are
unicode references to glyphs.
93
CSS3 TYPOGRAPHY
Lets turn our attention to the typographic control features detailed in the CSS3
Fonts module thats starting to become available across browsers. The following
features are not available everywhere yet, but Im including them because none of
them will cause any major disruption in browsers that dont support them. Youll
also get to see some attractive ourishes in browsers that do! It is a breath of fresh
air to start to see web browsers directly supporting the advanced features contained inside font les, although some would say it is long overdue. Table 3.3 shows
browser support for the font features discussed in this section.
TABLE 3.3 Browser Support Matrix for CSS3 Text Features
BROWSER
TEXT-RENDERING:
OPTIMIZELEGIBILITY
FONT-FEATURE-SETTINGS
Opera
No
No
Firefox
Since 8
Safari
Since 5.1
No
Chrome
Since 13
Internet Explorer
Since 10
iOS
No
No
Android
No
No
Chrome Mobile
Since beta
No
Opera Mobile
No
No
Opera Mini
No
No
NOTE: Other properties inside the CSS3 Fonts module support programmatic creation and control of features like ligatures and kerning, but none
of them seem to have any concrete browser support at the time of this
writing (a recent Chrome Beta has support for font-variant-ligatures
and font-kerning). At least this section of the chapter can act as a
tasterfor things to come.
94
CHAPTER 3
This turns on ligatures, which are very attractive but require a bit of extra
processing power to render. Keep this in mind if you are desperate to tweak performance as much as possible.
In terms of browser support, youll be able to see the ligatures in Safari 5.1+,
Firefox 4.0+ (uses ligatures automatically anyway, regardless of this property),
IE10+, and Chrome 13+.
CSS3 TYPOGRAPHY
95
Figure 3.17 shows further examples. You can also see them at http://people
.opera.com/cmills/css3book/fontdeck_example.html.
One detail to note is that the point of the text-rendering property is not just
to control ligatures, but to dictate how special font features are rendered in the
interests of legibility versus speed and geometric precision. The intended values
for text-rendering include:
sion. Generally, ligatures and other font hints will be turned on.
hints will be turned o. This has no eect in Firefox due to it using ligatures
automatically.
and other font hints will be turned on, depending on what produces the
best shape forms.
auto. The browser makes the rendering decision, depending on the current
96
CHAPTER 3
IE and Chrome use a slightly newer version of the syntax, which hopefully
Mozilla and other browsers will adopt soon after this book is published:
-webkit-font-feature-settings: dlig 1, kern 1, frac 1
-ms-font-feature-settings: dlig 1, kern 1, frac 1;
Fonts will often have dierent sets of the same feature availablefor example,
multiple dierent styles of kerning. You can access these by changing the number
after the declarationfor example, dlig 0 (in some cases), dlig 1, dlig2,
dlig 3.
With that, lets go forward and explore the dierent font features available
toyou!
CSS3 TYPOGRAPHY
97
Youve already met ligatures, but there are also discretionary ligaturesextra
ourishes that can make your text look more attractive. These features are enabled
like so:
-webkit-font-feature-settings: liga 1, dlig 1;
-moz-font-feature-settings: liga=1, dlig=1;
-ms-font-feature-settings: liga 1, dlig 1;
liga basically just acts as a dierent way to enable ligatures than using textrendering, although at the time of this writing, the latter had better browser support. dlig produces eects like those shown in Figure 3.18.
OpenType fonts often contain some great features for numbers. Consider the
following example:
-webkit-font-feature-settings: onum 1, tnum 1, frac 1;
-moz-font-feature-settings: onum=1, tnum=1, frac=1;
-ms-font-feature-settings: onum 1, tnum 1, frac 1;
98
CHAPTER 3
tnum. Tabular numerals swap out numbers (and other text, in fact) for the
most legible ones available. This generally means they are evenly spaced,
uniform height, and not old style (Figure 3.19).
ing, for example, 1st or 3rdor old-style numerals, which are not always
the same height and dont always t exactly on the baseline. (Ive found
websites that claim one or the other is true) (Figure 3.20).
frac. When used, these fractions automatically allow you to use fraction
CSS3 TYPOGRAPHY
99
FIGURE 3.22 Browser-calculated small caps are on the left; proper small caps are on the right
and are much better! (Font is Magneta Book Italic from Fontdeck.)
You can also use another variant called petite caps, which is basically just
more stylized capitals (Figure 3.23):
-webkit-font-feature-settings: pcap 1;
-moz-font-feature-settings: pcap=1;
-ms-font-feature-settings: pcap 1;
100
CHAPTER 3
KERNING
Kerning refers to altering the horizontal spacing between characters to make it
look more even. Kerning is turned on using a single declaration:
-webkit-font-feature-settings: kern 1;
-moz-font-feature-settings: kern=1;
-ms-font-feature-settings: kern 1;
The need for kerning is most evident when you have a curved capital with a
compact lowercase letter and no ascender or descender follows itfor example,
in the word Woman (Figure 3.24).
CSS3 TYPOGRAPHY
101
FIGURE 3.25 Stylistic set examples (font is Majestic Mishmash Regular from Fontdeckstandard, ss01, and ss02).
FIGURE 3.26 Stylistic swashes (font is Trilogy Fatface Regular from Fontdeck).
ss01. Stylistic sets specify the usage of an alternative set of glyph styles for
swsh. Stylistic swashes specify the use of stylistic swashes where available,
which are often similar to stylistic sets, although the latter tend to be more
wide-ranging in terms of the kinds of changes they include (Figure 3.26).
102
CHAPTER 3
cswh. Contextual swashes are similar to stylistic swashes except that these
calt. Contextual alternatives are alternative letter forms available for use,
Missing from the typographical puzzle seems to be how to determine which fonts
include the font features Ive been discussing in this section so that you can use
them. At this time, it will take a bit of trial and error. When looking for a font to use,
my advice is to create a sample type template that includes all the potential letter
sequences you might want, and then apply a simple stylesheet to it that includes
all available ligatures and other font features. Then try applying dierent fonts to
it and observe the results. A service such as Fontdeck makes this very easy to do.
In Firefox 8 or IE10, try viewing the following example: http://people.opera.com/
cmills/css3book/fontdeck_example.html.
CSS3 TYPOGRAPHY
103
Youll probably not want to use advanced font features on all of your type. It would
just be overkill! Most likely, youll just apply such features to headings, single
characters, or small strings of characters near the start or end of your lines of text.
In addition, you could consider using a subset of your fonts that just contains
the font features you want to style your headings and other text elements. This
will reduce bandwidth as well:
h1, .flourish {
font-family: my posh font subset, fallback, fallback;
-webkit-font-feature-settings: dlig 1, swsh 1;
-moz-font-feature-settings: dlig=1, swsh=1;
-ms-font-feature-settings: dlig 1, swsh 1;
}
104
CHAPTER 3
WRAPPING UP
In this chapter you investigated the new text and font features available in CSS3
and learned about usage and common problems youll encounter. You also looked
at free and commercial font solutions. By now, you should be comfortable making
good choices for fonts and text styling on your site.
For more in-depth information on fonts and to keep up with the latest on
web fonts and text, be sure to read the blogs of such talented typography fanatics as Rich Rutter (clagnut.com), Jon Tan (jontangerine.com), and Mark Boulton
(markboulton.co.uk).
WRAPPING UP
105
4
ENHANCING BOXES
WITH CSS3 BLING
One of the overriding general problems that CSS3 works toward solving
is reducing the number of images (and the inexibility of
those images) you are called upon to use to prettify your
websites. This chapter groups together all such CSS3 features
(like box shadows, gradients, and border images) that have strong
browser support under the moniker bling boxes.
In this chapter youll learn new ways to (tastefully) add graphical
eects to your sites programmatically without having to use millions of background images. Youll start by looking at some basic
isolated examples and then advance to more involved implementations. So put on your sequined disco clothes, jangle your change,
and prepare to strut your funky stu.
107
A BRIGHT FUTURE
WITH CSS3 BLING
Most of you will have a good idea of the kinds of CSS3 features Im referring to by
bling boxes: Drop shadows, rounded corners, linear and radial gradients, and alpha
transparency are exemplary examples. Also, a number of properties still require
the use of images but allow you to use them in a more exible way!
The advantages of such features should be obvious, but just in case, lets briey
review them before moving on:
Easier maintenance of graphical eects. You can now vary colors, dimensions, and so on by just changing some CSS syntax rather than having to
open Photoshop and manually alter image les.
Less spaghetti code. Back in the day, so-called bulletproof CSS solutions
typically involved multiple images and multiple nested <div>sa double
disappointment of extra complexity of design time and unsemantic cruft
code. If you wanted to create bulletproof rounded corners on a content box
to allow it to ex horizontally and vertically, youd need three extra nested
<div>s for holding all the necessary images. If you had only one container
available, youd have to settle for an inexible, one-size box, which was
usually rendered useless when content changed. CSS3 features, such as
rounded corners and multiple background images, change all this.
Fewer Photoshop ninja skills required. Creating such bling eects in code
is a lot easier and more intuitive for non-Photoshop experts.
Of course, the main disadvantages at this time are that some of these CSS3 features are not supported in older browsers (usually meaning Internet Explorer 68),
and they are often used with vendor prexes. Table 4.1 gives you an at-a-glance
reference of browser support for the properties covered in this chapter.
108
CHAPTER 4
TABLE 4.1 Browser Support Matrix for CSS3 Bling Box Features
BROWSER
RGBA/
HSLA
Borderradius
Boxshadow
Multiple
backgrounds
Gradients
Backgroundclip
Box-decorationbreak
Opera
version 10.5
version 10.5
version 10.5
version 10.5
11 with -o-
version 10.5
version 10.5
Firefox
version 3
3 with -moz-, 4
prefixless
version 3.6
3.6 with
-moz-
version 4
3.5 with
-moz-
version 4
Exact details
unknown
Safari
version 3.1
version 3.1
5.1 with
-webkit-
version 5
3.1 with
-webkit-
version 5
Exact details
unknown
Chrome
version 4
4 with -webkit-,
5prefixless
10 with
-webkit-
version 4
15 with
-webkit-
version 4
Exact details
unknown
Internet
Explorer
version 9
version 9
version 9
version 9
10 with
-ms- *
version 9
10 with
-ms-
version 9
Exact details
unknown
iOS
version 3.2
version 4
version 3.2
5.0 with
-webkit-
version 5
3.2 with
-webkit-
version 5
Exact details
unknown
Android
version 2.1
version 2.1
4 with
-webkit-
version 2.1
2.3 with
-webkit-
version 2.1
Exact details
unknown
Opera
Mobile
version 10
version 11
version 11
version 10
11 with -o-
version 10
Exact details
unknown
Opera Mini
version 5
no
no
version 5
no
no
version 5
Exact details
unknown
Background- Bordersize
image
version 5.0
109
Rounded corners are vital for street cred, critical for keeping with the Web 2.0 cool
school, and essential if you want to impress your signicant other.
These elements are such a commonly requested design feature that the spec
writers added the border-radius property to the Borders and Backgrounds module
(www.w3.org/TR/css3-background). The syntax is very simple to use (see borderradius-examples.html in the code download for many examples). You can specify
a single value for the radius size of all the rounded corners. For example:
border-radius: 10px;
You can use pixels or any other CSS unit that makes sense. The preceding line
of code results in corners like those in Figure 4.1.
110
CHAPTER 4
FIGURE 4.2 The container on the left has four values set; the one on the
right has two values set. Ive not included a three-value example, because
Ifind it a bit pointless.
As youd logically expect, you can also specify two, three, or four values. For
example:
border-radius: 0px 10px 20px; These relate to the top-left value, top-right
and bottom-left, and bottom-right values, respectively.
Using border-radius, you can also specify two sets of values separated by a
forward slash to indicate separate horizontal and vertical corner radii. For example,
the following line sets every horizontal radius to 10px and every vertical radius
to 20px (Figure 4.3):
border-radius: 10px/20px;
111
The x and y values can follow the same rules as the single set of values you saw
in the rst couple of examples. You can set a dierent value for each radius, like this:
border-radius: 5px 10px 15px 30px/30px 15px 10px 5px;
Or, you can set separate values for the horizontal radii and one value for all
four vertical radii:
border-radius: 10px 20px 30px 40px/30px;
112
CHAPTER 4
The path you specify to the PIE.htc le must be relative to the HTML le the
CSS is applied to, not the CSS, if you are using an external CSS le. This sounds
very odd, but it is due to the way HTC le works: It alters the behavior of the CSS
after it is applied to the HTML!
The other major part of using the CSS3PIE technique comes when you use it
to add support for gradients. To do so, you need to add a special -pie- prexed
version of the property. For example:
-pie-background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.2));
Youll notice that when using the -pie- prex on a gradient, the prex is put on
background, not linear-gradient, which is where the vendor prexes would go.
There is an added complication: the limitation of CSS3PIEs RGBA support.
You see, CSS3PIE will add support, but it wont render the alpha bit. Instead, it
will drop the alpha channel and render the equivalent RGB color. This is certainly
better than nothing and is probably not disastrous in many situations, but it could
also cause content to be rendered unreadable or just look shocking, especially if
youre relying on a color with a low alpha value to just add a faint shadow or tint to
a container on your page. To remedy this problem, it is a good idea to change the
-pie- prexed version of the property to a sensible fallback color or even remove
it in some situations:
-pie-background: linear-gradient(#ff0000,#A60000);
113
The rst two unit values specify the horizontal and vertical oset of the shadow
from the container. Positive values oset the shadow right and down, whereas
negative values oset the shadow left and up. The third unit value species the
amount of blur radius the shadow has (this is optional and defaults to 0 if not
explicitly declared). Increase the value for more blurry, spread-out shadows. The
color is, as youd expect, the color of the shadow.
This basic shadow creates the eect shown in Figure 4.5.
Using a subtle shadow like this is ideal for implying just a bit of depth or texture,
making the container look slightly raised.
Now lets add some rounded corners into the mix:
border-radius: 10px;
box-shadow: 2px 2px 1px black;
As you can see in Figure 4.6, the shadow follows the shape of the rounded
corners, which is rather convenient.
114
CHAPTER 4
The box now looks like it has truly been lifted into the air (Figure 4.7):
But something about the box just doesnt look right. The shadow is rather
unnatural. Usually, shadows have a tint of the color of whatever is below them
peeking through. But never fear; you can achieve this look easily using an RGBA
color (Figure 4.8):
border-radius: 10px;
box-shadow: 5px 5px 10px rgba(0,0,0,0.5);
115
You next need to know that you can include multiple box shadows on a single
container. You just write the dierent shadows you want one after another, delimited by commas:
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0,0,0,0.5),
10px 10px 15px rgba(0,0,0,0.5),
-1px -1px 30px rgba(0,0,0,0.2);
This trio creates some immediate depth, plus the suggestion of multiple
light sources (the very faint shadow is oset left and up using negative values)
(Figure4.9).
Now lets look at inner box shadows. You can make any box shadow an inner
box shadow by adding the inset keyword at the start. For example:
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0,0,0,0.5),
inset 5px 5px 8px rgba(0,0,0,0.5);
Figure 4.10 shows the result. This technique is useful for creating nice button
being pushed in type thingamajigs (technical term).
116
CHAPTER 4
Finally, lets look at one more possible unit value you could include: spread. Im
not talking about middle-aged spread or marmalade but the fact that you can add
a fourth unit value to specify an amount that the shadow size will increase by in
all directions. Its like padding for shadows. For example:
border-radius: 10px;
box-shadow: 5px 5px 10px 10px rgba(0,0,0,0.5);
See the eect in Figure 4.11. Ive never found a use for adding a spread value,
but you probably will.
NOTE: Use box shadows responsibly! Used subtly they can produce a great effect
and lift a design. However, if you use them a lot on the same site and on large
containers, they can make the site look cluttered and horrible. They can also
cause a significant performance impact, especially if you combine them with
animations. They are expensive to render in terms of processing power required.
117
Gradients are one of the most hotly anticipated features to become native to CSS.
Gradients are vital for design in general to reproduce the eects of light falling on
curved/shiny surfaces and create interesting patterns. The number of developers
who use them in web design is staggering, if not unsurprising. What is a surprise
is that until CSS3 came along, web developers never had the ability to create gradients programmatically in any sane way that would work across browsers. SVG
had gradients for a long time before that, but IE never supported SVG until IE9.
All this time youve been stuck with either faking SVG in IE using a Polyll
solution like SVGWeb or using repeated background images for those gradients or
repeating patterns you desired. This last technique works OK-ish but is an inexible pain and can become cumbersome very quickly, especially if your boss keeps
changing his mind about the gradient colors (more playing with Photoshop; oh
goody) or if you are trying to create any kind of complicated layered eect.
Again, CSS3 comes to the rescue with linear and radial gradients, which are
dened in the CSS Image Values and Replaced Content module (http://dev.w3.org/
csswg/css3-images). To see how exible CSS gradients are, just have a good play
with the examples in this section.
Lets review the two dierent gradient types separately.
LINEAR GRADIENTS
Linear gradients are the simpler of the two types; these are smooth color progressions that start at one side or corner of an area and cycle smoothly between two
or more color stops, ending at the other side or corner.
In CSS they work the same. CSS gradients are basically a special kind of background image. You can set them in place of an image in most places that it would
make sense to do so; for example, background-image and border-image (see the
Box Clever: border-image section later in this chapter for more on border images).
118
CHAPTER 4
The most common place youll want to use them is on standard, commonplace
backgrounds. Here is a simple syntax example:
background: linear-gradient(#ff0000,#007700);
Figure 4.12 shows the result, taken from an example le in the chapter4 code
download folder called linear-gradient-test.html. The two colors are the start color
in the gradient and the end color, and by default the gradient runs from the top to
the bottom of the container.
LINEAR GRADIENT DIRECTION
If you want to vary the direction of your gradient, you can add a direction value at
the start of the gradient, like this:
background: linear-gradient(to bottom right, #ff0000,#007700);
This direction value makes the gradient travel from the top left to the bottom
right (Figure 4.13).
As youd expect, you can use a whole range of logical keywords for gradient
direction: to top, to top right, to right, to bottom right, to bottom, to bottom
left, to left, to top left.
119
You can also specify the direction you want the gradient to travel in using an
angle. Zero degrees (0deg) is the equivalent of to right; as you increase the angle,
it travels around counterclockwise. So the subsequent equivalents would be 90deg
= to top, 180deg = to left, 270deg = to bottom. Bear in mind that 135deg will not
be the equivalent of to top left (as you might expect) unless the container is a
perfect square: The diagonal keywords will change the angle so the gradient will
always run from one corner to the other. As a result, you can choose keywords or
angles, depending on the eect you want to create.
Note: The spec states that 0deg is the equivalent of the keywords to top, but
browsers dont follow this currently. This could change in the future.
NOTES: If you look at the code for the linear gradient example, youll notice that Ive
included five lines for the gradienta prefixless line and one for all four major rendering engines. (Opera, Chrome, Firefox, Safari, and IE all support linear and radial
gradients now with vendor prefixes.)
Check out my linear-gradient-app.html file in the chapter4 code download folder
(which looks like Figure 4.14). It is a simple little page I put together using some
JavaScript that allows you to dynamically apply different gradients to the page,
either by clicking the preset buttons or entering your own linear-gradient(...);
value into the form input and clicking the Create! button. You need to include
the semicolon, but you dont need to include all the vendor prefixesjust one
single nonprefixed version is all you need.
120
CHAPTER 4
You can also add multiple color stops between the start and the end point by putting them between the start and end color stops, like this:
background: linear-gradient(to right,#ff0000,#0000ff 40%,
p #000000 70%,#007700);
This eect creates three solid color bands from left to right (Figure 4.16). The
green color stop is set at 66px down from the top, and everything before it adopts
the same color. The red color stop is set at 134px, and everything after it adopts the
same color. I also inserted two white color stops in the middle to force the middle
band to be completely white. This technique is very useful, especially if you want
to start creating more intricate and interesting repeating background patterns, as
youll read about later in the Multiple Backgrounds section.
121
You can even use negative unit values if for some reason you want the linear
gradient to start or end outside the container. (You might want to change the gradient on hover. Unfortunately, you cant smoothly animate a gradient, at least not at
the time of this writing. Believe me, Ive tried.)
Again, Ill extol the awesomeness of transparent colors by providing a very
simple gradient with a vital dierence (Figure 4.17):
background: linear-gradient(to top right,
p rgba(0,0,0,0.6),rgba(0,0,0,0));
background-color: #ff0000;
122
CHAPTER 4
Repeating linear gradients have a similar syntax to linear gradients. Look at the
following example and the result in Figure 4.18:
background: repeating-linear-gradient(to top right, rgba(0,0,0,0.4)
p 10px ,rgba(0,0,0,0) 20px, rgba(0,0,0,0.4) 30px);
background-color: #ff0000;
Only 30 pixels worth of gradient has been specied, but it is repeated over and
over again until the end of the container is reached.
123
RADIAL GRADIENTS
Radial gradients work a bit dierently than linear gradients. Instead of traveling
across a container from one side to another, they radiate outwards from a single
point. Here is a simple example:
background: radial-gradient(50% 50%, 60% 60%, rgb(75, 75, 255),
p rgb(0, 0, 0));
This produces the result shown in Figure 4.19 (if you want to experiment with
this code, download the radial-gradient-test.html le in the chapter4 folder).
NOTE: Radial-gradient-app.html is also included in the code download: This works in the same way as linear-gradient-app.html but with
different radial gradient presets plugged in. Use it to play!
124
CHAPTER 4
FIGURE 4.20 From left to right: top left, bottom center, and right positioning of a gradient. When only one keyword is supplied,
itis assumed to be the horizontal keyword, and the vertical one is given a value of center.
The syntax is a little dierent than that of linear gradients, so lets go through
the radial gradient syntax step by step.
RADIAL GRADIENT POSITION
The rst two values in the syntax (50% 50% in the preceding code) dictate the location of the origin of the radial gradient: The rst value is the horizontal position
inside the container, and the second value is the vertical. In the preceding example,
the radial gradient equates to 50% across from the left side and 50% down from
the top, which places it slap bang in the middle of the container. As with linear
gradients, you can use any unit values that make sense, even negative unit values.
You can also use keywords in place of unit values in the same manner as you
learned earlier but with the addition of center if you want the horizontal or vertical
position to be centered in the container (this doesnt make sense for linear gradients,
but it does for radial gradients). Figure 4.20 shows a few examples.
125
The second set of values in the radial gradient syntax (60% 60% in the example)
dictates the size of the gradientthe horizontal and vertical radius size. Because
you are working with the radius rather than the diameter, 50% or 60% will produce
a nice spread across a container. 100% would be double the width/height of the
container, swamping it entirely, which may or may not be the eect you want
(Figure 4.21).
NOTE: Firefox has never implemented size percentage
values, so they wont work in Firefox. For this reason, it is
better to use keyword values.
Again, to set these values, you can use any units that make sense. You can also
use dierent values for the horizontal and vertical radii, for example:
background: radial-gradient(50% 50%, 70% 40%, rgb(75, 75, 255),
p rgb(0, 0, 0));
126
CHAPTER 4
But as usual, there are more ways to set the radii: CSS3 supplies several keywords for setting the radii, which need explaining because they are a bit confusing.
Consider the following examples (Figure 4.23):
background: -o-radial-gradient(30% 50%, circle closest-side,
p rgb(75, 75, 255), rgb(0, 0, 0));
127
closest-corner positions the gradient so that its edge just touches the
farthest-side positions the gradient so that its edge touches the side of
the element farthest from its centre in the case of a circle or the farthest
horizontal and vertical sides in the case of an ellipse (Figure 4.25).
farthest-corner positions the gradient so that its edge just touches the
corner of the element farthest from the origin. You can use the keyword
cover in place of farthest-corner (Figure 4.26).
128
CHAPTER 4
Ive not used these implicit shape values very much, preferring instead to control
the shape using explicit unit values. But this doesnt mean you wont.
RADIAL GRADIENT COLOR STOPS
Color stops work in the same way as the color stops in linear gradients except that
the units you specify denote distance from the center of the gradient, not distance
from the starting corner/edge.
I encourage you to experiment with dierent color values with the examples
Ive provided and otherwise. Try creating a suns rays or a shadow or ashlight
moving across the top of your site. Again, use RGBA colors for the win! Youll see
more exciting examples throughout the book.
129
REPEATING-RADIAL-GRADIENT
As with linear gradients, you can also create repeating radial gradients by adding
repeating values into the syntax (Figure 4.27):
background: -o-repeating-radial-gradient(50% 50%, 60% 60%,
p rgba(75, 75, 255,0.5) 10px, rgba(0, 0, 0,0.5) 20px);
background-color: #ff0000;
130
CHAPTER 4
aside article {
...
background: repeating-linear-gradient(45deg, rgba(0,0,0,0.1) 1px,
p rgba(0,0,0,0.05) 2px, rgba(0,0,0,0.1) 3px, rgba(0,0,0,0) 4px,
p rgba(0,0,0,0) 5px);
background-color: rgba(255,255,255,0.4);
border-radius: 4px;
box-shadow: 2px 2px 10px black;
}
The result is a rather nice container with a shadow, rounded corners, and a
textured repeating gradient pattern (Figure 4.28).
To add IE support after youve placed the PIE.htc le, you can add the following
two lines, which include a far simpler gradient without an alpha channel that is
still in keeping with the color scheme (Figure 4.29):
-pie-background: linear-gradient(45deg, #6988af, #a6b9cf);
behavior: url(/cmills/arthur/script/PIE.htc);
131
MULTIPLE BACKGROUNDS
CSS3 gives you the ability to attach multiple backgrounds to a single element, which
is trs cool. For so long, if you wanted to have multiple background images on a
container, you had to have a number of extraneous wrapper <div>s for the extra
background images, which was a very lame hack to have to use.
The multiple backgrounds are simply added in a comma-delimited list. Lets
look at a simple example to illustrate the point; youll revisit multiple backgrounds
a number of times throughout the book.
If you again consult the Monty Python example in the king arthur blog example
folder, youll nd the following in the main-style.css le (multiple vendor prexed
versions have been omitted here for brevity):
body {
...
background: url(../images/castle.png) top left no-repeat,
p url(../images/clouds.png) top right no-repeat,
p linear-gradient(top right, #3B6498, #C1CDDB);
background-color: #C1CDDB;
}
Notice that Ive used two background images here and a gradient as well. The
ability to include CSS gradients in the list of multiple backgrounds makes them
even more awesome! Ive also included a separate background color as a fallback
for nonsupporting browsers (Figure 4.30).
132
CHAPTER 4
The castle is positioned at the top left, the clouds are positioned at the top right
so they ow nicely behind the castle, and a subtle blue gradient has been added
behind both for the sky. If you resize the browser with this demo open, it will
immediately become evident how awesome and exible multiple backgrounds are!
However, you need to bear in mind that the images later in the property value
appear behind those earlier on, which is rather contrary to the way CSS usually
works. In CSS, elements drawn later appear on top of those drawn before, so youd
expect it to work the same way with background images. Occasionally, youll wonder what the spec writers were thinking when they wrote certain parts of the spec.
Multiple backgrounds are also very cool for using multiple gradients together
to create complex background patterns. In the Monty Python example (full-post.
html/full-post.css), Ive used positioning to lay the gure captions over the top of
the images. I then used two gradients to apply a grainy texture to the images and
added a highlight to each one (Figure 4.31).
NOTE: At the time of this writing, there are differences
between browser implementations of multiple gradients,
but these should be ironed out by the books release.
MULTIPLE BACKGROUNDS
133
The effect is shown in Figure 4.32. This example is in the file gradientbackground-size.html.
134
CHAPTER 4
The radial gradient creates a simple, small, transparent circle with red on the
outside. The background-size property was used to force this circle into a 22-pixel
square, which then repeats. A couple of simple line patterns are then placed over
the top and spaced so they perfectly bisect the circles, horizontally and vertically.
This is a rather complex bit of code to write for a simple repeating pattern, but it
does show what is possible. You can nd more aesthetically pleasing examples
at Lea Verous fantastic CSS3 patterns gallery athttp://lea.verou.me/css3patterns.
MULTIPLE BACKGROUNDS
135
90px x 90px
30px x 30px
FIGURE 4.34 The image has
been carefully dressed around
the example container. Cool!
CSS3 provides you with more powerful properties to control borders. The most
interesting of these properties is border-image, which in eect allows you to divide
an image into dierent slices and dress the edges around any box youd like. This
sounds a bit complicated, so lets walk through a simple example. To demonstrate
border-image, I rst created a simple image to grab a border from (Figure 4.33).
Next, I applied the border image neatly to the border of a larger box in a exible
manner (Figure 4.34). Check out the border-image.html le in the chapter4 code
download folder. So, how do you do that?
Try increasing and decreasing the width of the browser, and you should see
the border exibly adjust. The following lines of code are doing the heavy lifting
here (border-image is currently supported across all major browsers using vendor
prexes, but Ive omitted them here for brevity):
136
CHAPTER 4
A B C D
B: right slice
30 px
30 px
A: top slice
30 px
C: bottom slice
30 px
D: left slice
As youd expect, the url() syntax points to the image you want to use for the
border.
The four numbers after that specify the widths of the border slices (be mindful
that these are numbers of pixels, even though they have no units) you want to chop
the image into. In order, they refer to the top slice, the right slice, the bottom slice,
and the left slice, as indicated in Figure 4.35.
You can set the slices to any size you like, but it obviously makes sense to divide
the image so the slices in the border contain the parts of the image you want. As
logic would suggest, because in this case all four slices are the same size, you could
write the border-image line using two values or one value, like so:
border-image: url(border.png) 30 round;
137
After slicing the image, it is applied to the borders of your container: The four
corners remain the same. The four sides all tile in one dimension to ll up the
borders, however long they are (although see the end of this section for browser
dierences). The center of the image tiles in both directions to ll up the remaining background space.
How do you control the manner in which the tiling of the sides is handled?
You use the round keyword. round species that the browser should always show a
whole number of repeated border segments and no incomplete fragments, adjusting the size of each segment to maintain the desired result. If you try increasing or
decreasing the browser window width in Opera, Firefox, and IE, youll see that the
size of the balls adjust slightly. Unfortunately, WebKit-based browsers treat round
the same as repeat, another value that just tiles the side slices until they ll up
each side without rounding. You are therefore left with fragments at each end of
the sides, which dont look great (Figure 4.36).
Fragments might look OK as long as you plan the shape of your slices carefully
and make sure they dont dier much in height along their course. Another value
to be aware of is stretch, which is the default. If you swap round for stretch in
this example or omit it altogether, youll get the result shown in Figure 4.37.
Again, note that Ive specied one value here for the repeating behavior of all
four sides. If you want to specify dierent behavior for dierent sides, you could
use two or four sides as logic would suggest; for example, round stretch or round
stretch round stretch.
138
CHAPTER 4
And theres one more detail you should know about the basic syntax. To actually
provide space for your border image, you need to specify a border width, which is
why border-width: 30px; was included in the code example. If you dont do this,
you wont see anything. The border-width property oers additional interesting
possibilities: If you make the border width bigger or smaller than the slices within
the border-image property, the slice size will scale up or down to suit. So, if you
make the border half as big, like so:
border-width: 15px;
the border image slices will be displayed in half dimensions, as shown in Figure4.38!
BORDER-IMAGE PROBLEMS
Using border-image is not all plain sailing, of course, as with most things in web
design. Aside from the fact that WebKit-based browsers currently dont use the
round value properly, there are a couple of other issues to keep in mind.
First, you need to determine if you want your central slice to be discarded
or not. You might want the central slice to act as the background for your container content, or you might just want to put the border image only in the border.
Unfortunately, the default behavior according to the spec is to discard it, but most
browsers do the opposite, except for Chrome (try comparing border-image-2.html
in Chrome and Opera). You are supposed to be able to control this behavior with
border-image-slice, but this property is currently not supported in any browser,
139
This snippet of code made the background look better again in Chrome,
although it wasnt perfect, and it made the content readable in Internet Explorers
decrepit old ancestors. This example is dicult because I am using a complicated
background image on a variable width container. Getting a seamless look would
be a lot easier to do in a simpler, xed-width case!
NOTE: background-clip, defined in www.w3.org/TR/css3-background, allows
you to specify that you want background content to be rendered all the way
out to the edges of the browser (border-box, which is also the default),
to the edges of the padding (padding-box), or to only the edges of the
content (content-box). This property comes in handy in certain situations
and is supported across all modern browsers.
These limitations mean that border-image usage will be slightly more restricted
than is ideal for the moment, but it is already usable to great eect in many situations.
140
CHAPTER 4
BOX-DECORATION-BREAK
FIGURE 4.41 The broken ends of the box are now filled in and are cloned from the start and
end of the box. This looks a lotbetter!
Lets nish the CSS bling tour with a simple little x for those ugly breaks you get
when a nicely styled element wraps across lines (or columns or pages). Figure 4.40
shows a styled link as an example.
This break is easily remedied by a new CSS property called box-decorationbreak (in www.w3.org/TR/css3-background). If you add the following to the link
properties:
box-decoration-break: clone;
youll produce a better-looking result (well, in Opera anyway; other browsers should
catch up soon) (Figure 4.41).
BOX-DECORATION-BREAK
141
To round o the chapter, lets build an ad example using some of the cool properties you learned about earlier. Youll make it look good, albeit dierent across older
browsers, and make it sing with a minimum of images (and a video). Later in the
book youll explore how to make the ad responsive and add some cool animated
eects.
The ad will be for a ctional metal band called Dead Hamster. The band is
making a comeback, and its management wants to move forward with an online
advertising campaign that is going get the band noticed! And what better way to
get people to notice than by using thrills, spills, moving pictures, and raw exciting
content? OK, so they dont have Bieber or Jedward, but they would only serve to
draw the wrong kind of attention.
To make a big splash, the ad will work on mobile devices, so the poster needs
to work at dierent sizes and on dierent devices. And the band also has a huge
following in developing countries due to their freedom anthems. Therefore, the
ad needs to work across less-capable browsers.
Lets rock!
NOTE: I got the idea for creating a responsive advertising example
from Mark Boultons rather interesting Responsive advertising article
at www.markboulton.co.uk/journal/comments/responsive-advertising.
BASIC SETUP
The basic idea is to create a set ad size: the Internet Advertising Bureau (IAB) has
semistandardized sizes for web ads, as youll see at http://en.wikipedia.org/wiki/
Web_banner. Lets start o this example by creating a 730 x 300 pixel pop-under ad.
But lets take it even further and make an eye-catching ad to show that many
of the tasks you used to do with Flash are now possible using only CSS3. In this
chapter youll just build up the basic ad. (Animation will come in Chapter 5, and
responsiveness in Chapter 8.) Youll also learn how to provide a reasonable alternative in older browsers and what improvements you can and should make if you
were to do something similar in a production environment.
142
CHAPTER 4
The background of the entire advertisement is a short looping video clip that
shows o the energy of the band. Over the top of this the most important information is displayed, and on hover/focus another pane of information is shown containing more info. The nal product as it stands at this point is shown in Figure 4.42.
The basic markup structure is as follows:
<section id=ad>
<video></video>
<div id=video-frame></div>
<div id=frame1></div>
<div id=frame2></div>
</section>
One section contains the entire ad and includes a <video> element to render
the rocking Dead Hamster footage, a <div> to apply an eect over the top of the
video (more on this shortly), and then a couple more <div>s to contain the two
panes of information.
NOTE: JavaScript has been used to mute video: I fire the JavaScript on the
onloadedmetadata event to make sure mute is fired before the content starts
playing; otherwise, a clip of sound might be heard before the mute kicks in.
143
Most of the content is absolutely positioned so the layers stack on top of one
another, and most of the containers are set to 720 x 300 px, the same dimensions
as the outer container, to keep everything inside the ad working well. Most of the
code should be pretty simple to understand for anyone with previous CSS experience, so Ill just explain the CSS3 code. You can nd my code in the poster folder
in the code download.
This is a rather useful technique in many ways: Imagine if you had lots of elements, such as headers or articles, and you wanted them to have a background
image at either end and have a exible width and height. This code is all youd need.
Next, youll set a uniform black text shadow on all text, apart from the interesting aming eect Ive put on the word hell: This is suitable for increasing the
latent cheese factor to be appropriate for the average heavy metal band. This can
be done like soadd this now to your text:
144
CHAPTER 4
#ad #hell {
font-size: 150%;
text-shadow: 0 0 4px white,
0 -5px 4px #FFFF33,
2px -10px 6px #FFDD33,
-2px -15px 11px #FF8800,
2px -25px 18px #FF2200;
}
Also, youll include a repeating radial gradient using various transparent blacks
for a bit of background texture, plus a background color to provide a faint blue tint:
#ad #frame1 {
background-image: repeating-radial-gradient(top left,
rgba(0,0,0,0) 9px,
rgba(0,0,0,0.05) 10px,
rgba(0,0,0,0.05) 15px,
rgba(0,0,0,0.1) 16px,
rgba(0,0,0,0.1) 20px);
background-color: rgba(16,8,115,0.2);
}
And nally, youll use cool, very metal web fonts! These all result in a great set
of components that blend well into one another.
145
Youll do this because Flash content tends to dominate the area of the page it
is put on, so rollovers on top of the video content wont work on a Flash fallback.
In the end, lets opt for the cowards option of not displaying the hover eect
in the second frame because IE6, 7, and 8 tend to prove troublesome when you are
trying to get hover eects to work on positioned content. Youll use text-indent
to push the text far o the screen, so it will still be available to screen readers.
In addition, youll include some quick box model and positioning xes for IE6
and 7. The box shadows, text shadows, gradients, and RGBA colors all degrade well.
ADDING AD IMPROVEMENTS
I think youve created a fairly eective basic ad in this example. The ad is all contained within a single container, so it is fairly easy to transplant in whichever page
you want it in, and then position it where you want it.
But why not just create the ad in Flash? It would potentially be simpler to deal
with, but the point is that you are trying to create components with open standards,
which includes all the advantages they bring to the project, plus the text would
not be accessible if you put it in a Flash video. The advantages open standards
have over Flash in this context will be even more obvious when you start to add
animated eects in Chapter 5.
Of course, before you really use this ad, you might want to make a few
improvements:
146
CHAPTER 4
Optimize video les. The video les as they stand are a fairly heavy addition
to a page, so you should optimize them.
Pare down fonts. The fonts are also quite heavy. In a real production environment, you could use Fontforge (as mentioned in Chapter 3) to reduce
the size of the font les and just include the glyphs you need.
Add a link. You should also wrap the nal version in a link (HTML5 allows
block-level linking) to click through to wherever you want the ad to lead to.
WRAPPING UP
Hopefully, youve come away from this chapter with an understanding of the great
new tools CSS3 oers for making your visuals less image-dependent and therefore
more exible and lightweight. Although having the ability to programmatically create web graphics does make web design a lot easier for non-Photoshop ninjas (like
me), I hope youre committed to using those features in a responsible way rather
than just spamming all the relevant properties onto every container on your site!
And, you also now know how to get these CSS3 features working in a reasonable
manner across older, less-capable browsers.
WRAPPING UP
147
5
ANIMATED EFFECTS
USING CSS3
149
Combined, the following four specs provide you with several possibilities for creating more responsive interfaces, animated eects, and presentational enhancements,
which previously were only available through JavaScript:
Support for all four specs is good across modern browsers. In any case, for nonsupporting browsers it is simple to provide alternative styling using the Modernizr
library, which youll learn about in detail later in the Providing Alternatives with
Modernizr section.
So lets explore these interesting new features. You should experiment and have
fun with these features but also use them responsibly. You dont want every new
website to turn into a crazy animated nightmare!
NOTE: The appearance of animations/transitions inside CSS has led a number of web developers
to complain about CSS-based animations breaking the separation of structure, presentation, and behavior layers best practice. And they are technically right. However, you can
spout all the religious arguments you want about animation belonging in the behavior layer
rather than the presentation layer, but animation definitely falls in the realm of design.
150
CHAPTER 5
TRANSFORMS
Lets rst walk through CSS Transforms. The idea with transforms is that you can
change the shape and size of the area an element takes up. As a simple contextual
example, I used a skew transform to rotate the angle of the top-level header in the
Monty Python example, as illustrated in Figure 5.1.
The full code block I used to achieve this follows:
body>header {
..
transform: skew(4deg,6deg);
}
As you can see, transforms take the form of the transform property with a
value consisting of a transform function (in this case skew) and associated values
in parentheses (in this case 4deg, 6deg).
TRANSFORMS
151
The two specs dene two- and three-dimensional transforms. Ill cover the
features they oer in two separate sections and will be brief, because transforms are
a lot more interesting when combined with animations and other eects. Browser
support for transforms is summarized in Table 5.1. Ive not broken them down into
detailed references because generally this data works for all properties associated
with the 2D and 3D varieties of transforms.
TABLE 5.1 Browser Support for Transforms
BROWSER
2D TRANSFORMS
3D TRANSFORMS
Opera
No
Firefox
10 with -moz-
Safari
4 with -webkit-
Chrome
4 with -webkit-
12 with -webkit-
Internet Explorer
9 with -ms-
10 with -ms-
iOS
Android
3 with -webkit-
Mobile Chrome
Opera Mobile
11 with -o-
No
Opera Mini
No
No
Note that in IE10 platform preview 6, support for non-prefixed transform properties has
been added.
152
CHAPTER 5
2D TRANSFORMS
Generally, websites are thought of as working in two dimensions, so to start this
discussion, Ill keep it at and simple. The functions and properties you have for
transforming elements in two dimensions are discussed in the following sections.
In the chapter5 code download folder, youll nd a series of transform- les
demonstrating dierent transforms applied to a simple container. You can nd the
example without any transforms applied in transform-template.html (Figure 5.2);
the others are named intuitively.
TRANSLATE, TRANSLATEX, TRANSLATEY
translate simply moves the element it is applied to by the amount you specify
This makes the element move 200 pixels to the right and 100 pixels down, as
shown in Figure 5.3. Note that in each of these examples, Ive included a ghost
version of the element to show the original position, so it is easy to see exactly
whats happened.
You can use any distance units that make sense; percentage values will be a
percentage of the width or height of the container you are transforming, not its
parent container. If you use negative units, you will translate the container left
instead of right and up instead of down.
TRANSFORMS
153
If you want to move the container in only one direction, you could set the
other value to 0, for example; use the following line if you want to just move the
container 200 pixels to the right:
transform: translate(200px,0);
Be warned, however: If you specify only one value inside a translate transform, the browser will assume that it is an X transform and assume Y and Z are 0.
It is therefore better to be more explicit about the direction you want to translate
in, and use this:
transformX: translate(200px);
or this:
transformY: translate(200px);
X, Y, AND Z AXES
X, Y, and Z are talked about a lot in this chapter. They refer to the X, Y, and Z
axes of the web page, which transforms, transitions, and animations move
elements along. X is the horizontal axis, moving from left to the right on the
page (so a negative X value would mean movement from right to left). Y is
the vertical axis, moving from top to bottom (a negative Y value would mean
movement from bottom to top). The Z axis moves out of the screen toward
the viewer, so from farther away to closer in distance; negative Z would do
the opposite.
154
CHAPTER 5
ROTATE
As you might expect, the rotate transform allows you to rotate an element. In the
transform-2drotate.html le youll nd the following line:
transform: rotate(15deg);
TRANSFORMS
155
Any standard CSS distance units, such as px, em, rem, cm, and so on
Percentages
You can mix and match different values for the horizontal and vertical if you
like, for example, top 35%. If you set only one value, it is assumed to be the
horizontal value with a vertical value of 50%.
Finally, you can set negative values to set the rotation point somewhere outside the element you are transforming.
Note that transform-origin can also affect other types of transforms, such
as scale, and the effect is more noticeable when you start combining transforms with transitions. Do you want your element to grow from the top-left
down and to the right, or do you want it to grow from the center outwards?
156
CHAPTER 5
as one static entity; text wont be reowed and so on. In the transform-2dscale.html
le in the chapter5 code download folder, youll nd the following line:
transform: scale(1.25,1.1);
TRANSFORMS
157
If you want to scale only in a single direction, you could set the direction you
dont want to scale to 1, for example:
transform: scale(1.25,1);
But it is more ecient and intuitive to specify a single value for scalingeither
horizontally:
transform: scaleX(1.25);
or vertically:
transform: scaleY(1.25);
CHAPTER 5
skew accepts the same unit values as rotate, but it works in a dierent way.
Instead of the whole element being rotated but looking the same, it is deformed
by three degrees horizontally and ten degrees vertically. In real terms, this might
seem a bit illogical, because the three degrees x value is applied to the vertical sides
(they are slanted three degrees o vertical) and the ten degrees y value is applied
to the horizontal sides (they are slanted ten degrees o horizontal). Just think of it
this way: The x and y values refer to the axes the shape is distorted along.
If you want to skew an element in only one direction, use skewX or skewY. For
example:
transform: skewX(3deg);
transform: skewY(10deg);
MULTIPLE TRANSFORMS
You can apply multiple transforms in the same rule by including them all in the
same property separated by spaces.
In the example le multiple_2dtransform.html, youll nd the following transform line:
transform: skew(-3deg,-10deg) translateX(-200px) scale(0.7)
p rotate(10deg);
TRANSFORMS
159
MATRIX
I wont discuss the matrix transform function in any great detail, because it is very
complicated. If you have years of experience with SVG, and/or are a math geek,
youll be familiar with these so-called transform matrices: They take the form of
algebraic expressions. For example, the equivalent of transform: rotate(30deg);
as a matrix would be:
transform: matrix(cos(30), sin(30deg), -sin(30deg), cos(30deg), 0, 0);
Transform matrices are very powerful because you can eectively use a single
matrix to apply multiple transforms at once. However, they are unreliable and
overcomplicated. In my opinion, you are better o just using multiple transform
functions as explained in the previous section.
3D TRANSFORMS
Now lets pop up from the at world of 2D and look at transforms that work in
three dimensions. These are slightly more limited in support (at the time of this
writing, Opera didnt yet support them), but it denitely wont be long before you
see support across the full gamut of modern browsers!
Lets explore the properties you have to work with.
TRANSLATE3D, TRANSLATEZ
3D translations work in the same way as 2D translations (see the earlier translate,
translateX, translateY section for full details) except you can move elements along
the Z axis as wellthat is, into and out of the screen. You would think that if you
translate elements along the Z axis, they would move closer and farther away from
you, making them appear bigger and smaller.
However, in practice it doesnt quite work that way. Look at the transform3dtranslate.html example. As in previous examples, this contains the example
container along with a ghost. However, this time the two containers are inside a
wrapper <div>.
160
CHAPTER 5
<div id=wrapper>
<article id=real></article>
<article id=ghost></article>
</div>
This produces the eect shown in Figure 5.8. The #real element appears to
have been moved 100 pixels in front of the #ghost element in the 3D space.
translate3D produces a very similar eect to what youve already seen with
translation functions; however, translate3D allows you to translate elements
along the X, Y, and Z axes at the same time:
transform: translate3D(100px, 200px, 300px);
/* 100 pixels along the X axis, 200 pixels along Y, 300 pixels
p along Z */
TRANSFORMS
161
confusing at rst, because they produce quite dierent results than what you might
expect. rotateX and rotateY rotate the element they are applied to around the X
and Y axes, respectively, which actually transforms them in the Z axis direction!
rotateZ rotates the element around the Z axis, which produces a similar eect to
the 2D rotation you saw in the earlier rotate section!
Lets look at an example to smooth out this confusion: Open the transform3drotate-x-y-z.html le in the chapter5 code download folder. In this le youll
see three copies of an example with a 180 degree rotateX, rotateY, and rotateZ
applied to them, respectively. Ive also applied a basic transition to each one; as
you hover over the examples #wrapper <div>, each <article> will animate, so
you can easily visualize the eects of these transforms. The rotation along the X
axis looks like this:
transform: rotateX(180deg);
Ive not included images here, because it is much easier to see the full eects
of these examples by viewing the code example in your browser.
162
CHAPTER 5
ROTATE3D
So how do these work? Notice that the rotate3D function takes four arguments.
The fourth one is the number of degrees (or radians) you want the element to rotate
through. The rst three unitless values specify a direction vector for the element
to rotate around. So 1,0,0 is one rotation along the X axis, and none in the Y or Z
directions. So, in the rst example, the element rotates around the X axis.
TRANSFORMS
163
1 in X direction
X-axis
9 in X direction
X-axis
3 in Y
direction
Z-axis
1 in Y direction
Z-axis
1 in Z direction
Overall direction vector (1,1,1)
Y-axis
Y-axis
Now its your turn: Try adjusting the vector values in this example to make
the elements rotate in all sorts of weird and wonderful directions! For example,
using a vector of 1,1,1 would cause the element to rotate around a line that travels
downward at 45 degrees between the X, Y, and Z axes. A vector of 9,3,0 would cause
the element to rotate around a line traveling down and right 30 degrees from the X
axis and 60 degrees from the Y axis but not traveling at all in the Z direction. You
can see visualizations of these values in Figure 5.9.
Note that the individual numbers in the vector values dont matter; it is the
proportions that matter. So, for example, 78,78,78 will result in the same direction
vector as 1,1,1. You can also use negative vector values to make your direction vector
travel in the opposite direction. For example, -1,-1,0 makes the element rotate
around a line that is 45 degrees between the X and Y axes but runs left and up, not
right and down, as positive values would produce.
NOTE: Be clear on the way the axes travel! As Ive said before,
positive X is right; negative X is left. Positive Y is down; negative Y
is up. Positive Z is out of the screen; negative Z is into the screen.
164
CHAPTER 5
SCALE3D, SCALEZ
The scale3D and scaleZ transform functions dont do much in real terms; they
imply the ability to grow elements along the Z axis, for example, increasing their
height. But HTML elements intrinsically dont have any thickness in this directionthey are wafer thin. In actual fact, scaleZ will act as a multiplier for the
translateZ function; transform: translateZ(10px) scaleZ(20); would have
the same eect as transform: translateZ(200px). But youd be better o just
using translateZ or translate3D instead, as discussed earlier. If you want to give
the impression of an element increasing in size and/or getting closer to the user,
setting a simple 2D scale is often best.
MATRIX3D
As discussed earlier in the matrix section, matrix transforms are very powerful
but very complicated and pretty much not within the realms of understanding for
designers and other nontechies! And 3D matrices are even more complicated: They
have 16 values for each function, as opposed to six for 2D matrices! Therefore, I
wont discuss them here (refer to the matrix section for links to more information).
PERSPECTIVE, TRANSFORM: PERSPECTIVE, AND PERSPECTIVE-ORIGIN
The transforms youve learned about so far can be used in a 3D space, but the elements exist on a at plane, as if they are all right in front of your eyes. In real life,
this is not the case. You see objects in dierent positions around you in dierent
perspectives. To simulate this a bit more accurately on the web, you can use the
transform: perspective(); function, the perspective property, and the related
perspective-origin property to make your elements look more three dimensional,
even if they dont have other transforms applied.
TRANSFORMS
165
166
CHAPTER 5
No perspective
Perspective: 800px
Perspective
cone
Perspective: 250px
As you can see, a small pixel value produces a very large perspectivethis
equates to your point of view being closer to the elementwhich possibly looks a
bit over the top and unrealistic. A value of 800 pixels is very visible but a bit more
realistic, and a value of 2000 pixels is much more subtle.
So how does perspective work?
The perspective value denes how far away the viewpoint of the element is
from the closest side of the element. OK, that might not make much sense, so Ill
use a diagram and provide some more explanation. Imagine that the element you
are applying the transform to is being viewed by a big eyeball, like your own Eye of
Sauron but without the bad-ass attitude. And imagine that a giant invisible cone
sits on top of the element. The apex of the cone is right above the middle of the
element, and the base of the cone sits on the at plane of the element (Figure 5.11).
TRANSFORMS
167
With no perspective applied, the Eye of Sauron will be right at the apex of the
cone looking directly toward the element, which will therefore be seen straight
on and totally at. If you apply perspective values, the Eye of Sauron still looks
directly at the element, but its position is shifted down the side of the cone. The
perspective value is the distance the Eye of Sauron is from that edge; therefore,
smaller values produce more dramatic distortions in the viewing of the element,
whereas bigger values produce more subtle eects.
You can use pretty much any distance units that make sense for dening the
amount of perspective, although pixels provide the most exact control and are
probably the best to use. If you dont include any units, the units default to
pixels.
TIP: You need to put the perspective transform
before other transforms you want it applied to. If
you use rotateX(10deg) perspective(800px), for example,
the perspective would have no effect.
Now lets turn to the separate perspective property: Look at the perspectiveproperty.html le. In this example Ive added an extra wrapper <div> around the
three <article> elements identied with an ID of perspective-wrap and applied
perspective to the whole lot using the following:
#perspective-wrap {
perspective: 800;
}
#x, #y, #z {
transform: rotateX(30deg);
}
Looking at the example youll see that the rotation transforms are applied to
the <article> elements, but the perspective is applied to all the children of the
<div>, as if they are all in the same 3D space. Because of the perspective, even
though all the child elements have the same amount of rotation applied, they
appear dierently (Figure 5.12).
168
CHAPTER 5
TRANSFORMS
169
If you try this code in a supporting browser, youll see that when the container
is hovered over, the viewpoint changes, making it look as though the camera (or
Eye of Sauron in this case) is panning around the scene. For those of you who
dont have a computer in front of you, Figure 5.13 indicates the eect the change
in perspective-origin has.
Using the perspective-origin property is quite fun, but rather annoyingly,
it only works for the perspective property; you cant apply it to transform:
perspective();.
170
CHAPTER 5
TRANSFORM-STYLE
transform-style is used when you have multiple 3D transformed elements that
appear next to or on top of one another. It has two possible values: flat, the default,
and preserve-3d.
When the default value is in eect, 3D transforms will be rendered, but they
will all be rendered in the same at 2D plane. This means that when multiple 3D
transforms appear in the same space, some of the detail may get lost because they
all appear at the same position along the Z axis.
If you use transform-style: preserve-3d;, the dierent positions of the elements will be preserved along the Z axis. To see this property in action, look at the
preserve-3d.html example le.
In this example Ive created a rather nifty little 3D notepad (Figure 5.14) that
rotates toward you when moused over and allows you to pull out the rst page to
read it when you mouse over the edge of it.
TRANSFORMS
171
So how does this example work? Well, the only image used is the repeating
image tile for the front and back covers of the notepad; the rest of the graphics
were created using box-shadow, text-shadow, gradients, and web fonts. You learned
about these in previous chapters, so I wont explain them here. Ill also not discuss
the animated elements Ive created using transitions, because youll look at those
in detail later in this chapter. Here Ill just concentrate on the transforms. To start,
the markup is just some <article>s wrapped by a wrapper <div>:
<div id=wrapper>
<article id=front></div>
<article id=p1></div>
<article id=p2></div>
<article id=back></div>
</div>
To create the basic book, all of the pages are absolutely positioned on top of
one another. The book is then rotated in three dimensions using the following:
#wrapper
transform: perspective(1200px) rotateY(-9deg);
transform-style: preserve-3d;
}
The pages are then moved into different positions in 3D space using the
following:
#front {
transform: translateZ(5rem);
}
#p1 {
transform: translateZ(0rem); /* Explicitly setting this is
p needed; Firefox does weird things with this example if
p you dont.*/
}
172
CHAPTER 5
#p2 {
transform: translateZ(-5rem);
}
#back {
transform: translateZ(-10rem);
}
TRANSFORMS
173
This example isnt perfect. It would be better handled by a series of CSS Animations triggered by links using JavaScript, because it would mean you could
handle multiple pages ying out and it would be easier to make it keyboard accessible. (Youll look at triggering animations with JavaScript later in the Animations
section.)
Also, it doesnt work in Opera and older browsers because they dont support
3D transforms, so youll need to provide an alternative representation of the data
for those browsers. Youll nd out how to do that later in the Providing Alternatives with Modernizr section.
BACKFACE-VISIBILITY
backface-visibility serves a single function: to specify whether an elements
backface (i.e., the reverse view of its content) is visible when the element is rotated in
3D so that its front is facing away from the viewer. To demonstrate using this property, lets look at how to create a business card that ips over with a 3D transform
(with realistic dimensions sized in millimeters!). You can nd a nished example
in the le two-faced-cheek.html.
Again, Ill ignore the details that arent directly relevant to the example. The
markup is again pretty simple:
<div id=wrapper tabindex=0>
<div id=inner-wrapper>
<div id=front>
</div>
<div id=back>
</div>
</div>
</div>
174
CHAPTER 5
Here, the inner wrapper is used for the sizing and positioning, and the design
work is applied to the two front and back <div>s for the front and back of the card.
The outer wrapper <div> is there to add hover and other state change eects to, so
that you dont get that unwanted behavior in some browsers that was discussed
earlier (see the Firefox Bad Hover? sidebar). The <div> contents are unimportant
for the purposes of this example, although for a real business card youd probably want to mark up the contact details in a more useful way by using an hCard
microformat, for example.
Youll rst set a transition on the inner wrapper and then tell it to preserve
the 3D space:
#inner-wrapper {
...
transition: 1.5s all;
transform-style: preserve-3d;
}
Next, set backface-visibility: hidden; on both the front and back <div>:
#front, #back {
...
backface-visibility: hidden;
}
TRANSFORMS
175
The front of the card doesnt need to be rotated for its default state. However,
Ive applied a rotateX(0deg); transform to it, because it seems to solve a problem
in Firefox in that some of the content on the front of the card is displayed in reverse
when the card ip is triggered, even with backface-visibility: hidden; applied.
Weird but true. The back of the card is rotated around the X axis by 180 degrees
and set to backface-visibility: hidden, because youll want it to be invisible
and upside down by default. z-index is also needed on the front to make it appear
at the front. By default, it would appear behind the back because the back comes
later in the source order.
The last step is to rotate the whole business card by 180 degrees when it is
moused over/focused:
#wrapper:hover #inner-wrapper, #wrapper:focus #inner-wrapper {
transform: rotateX(180deg);
}
176
CHAPTER 5
You could force the browser to use hardware acceleration for this by adding a 3D function at the end of the
transform list that does nothing to the element, like so:
transform: rotate(45deg) translate3d(0,0,0);
This is useful if animations are running too slow on a certain device, for example, an Android phone or
iPhone. However, be careful not to change all the prefixed versions of the property, because you might stop
some browsers from using the property (for example, Opera doesnt support 3D transforms at the time of
this writing). So until support is more consistent, you could do this:
-webkit-transform: rotate(45deg) translate3d(0,0,0);
-o-transform: rotate(45deg);
TRANSFORMS
177
178
CHAPTER 5
TRANSITIONS
With a run-through of CSS3 Transforms complete, lets now turn to pastures new,
namely transitions. As youve seen in some of the transform examples, transitions
allow you to smoothly animate properties that change upon a state change (for
example, when a link is hovered over) rather than the usual on/o rollover that
would occur otherwise.
Table 5.2 summarizes the browser support for transitions.
TABLE 5.2 Browser Support for Transitions
BROWSER
TRANSITIONS
Opera
Firefox
4 with -moz-
Safari
Chrome
4 with -webkit-
Internet Explorer
10 with -ms-
iOS
Android
Mobile Chrome
Opera Mobile
10 with -o-
Opera Mini
No
TRANSITIONS
179
You must set the transition on the element you want the transition to occur on.
transition-property takes as its value the property you want to transition upon
state change.
NOTES: Notice from the code examples in this section that the transition properties
currently need prefixes.
Not all CSS properties are animatable via CSS Transitions and Animations, but
most of the ones youd conceivably want to animate are. A list of animatable
properties is available in the CSS Transitions spec in the Animatable Properties
section at www.w3.org/TR/css3-transitions/#animatable-properties.
180
CHAPTER 5
This property can take values with any CSS time units, but youll pretty much
always use seconds.
DELAYING TRANSITIONS
If you want to set up a delay between the state changing on the element to be
transitioned and the transition occurring, you can use the transition-delay
property, like so:
transition-delay: 2s;
This property is useful if you want to re multiple transitions but want them
to happen one after the other in a staggered fashion.
TRANSITIONS
181
Progression
The available values you can use (modeled on cubic Bzier curves) are:
linear. The transition happens at the same rate from beginning to end.
ease. The default value; the transition starts quickly and then gradually
slows down.
ease-out. The transition starts quickly, stays quick for longer than ease,
ease-in. The transition starts o slowly and then speeds up toward the end.
182
CHAPTER 5
the transition to jump between a set number of steps placed equally along
the transition. For example, steps(10) would make the transition jump
along in ten steps. You can also set an optional second parameter with a
value of start or endfor example, steps(10, start) or steps(10, end).
This species whether the change in property value should happen at the
start or end of each step. You wont nd much use for this optional parameter,
but it is worth a mention.
tom cubic Bzier curve to use for the transition. This function takes
four arguments: the X and Y coordinates of the beginning control handle, and the X and Y coordinates of the end control handle. For example,
cubic-bezier(0.25, 0.1, 0.25, 1.0) is equivalent to the ease preset value.
To make the dierence between these timing functions easier to appreciate,
Ive created an animated bar graph example that shows several dierent bars transitioning across the screen when the display is hovered over (Figure 5.20). Each
one has a dierent timing function applied, so all will reach the end of their course
at the same time, but their rates will vary. See the transition-timing-functions.html
le in the chapter5 code download folder.
NOTE: The steps timing function doesnt yet appear to
work in Opera, but it should get there soon.
TRANSITIONS
183
Ive styled the bars nicely and added a nifty little bit of JavaScript that resizes
the height of the bars and their container to perfectly ll the screen when the
page loads and when the screen is resized, making for an ideal adaptive example.
(Theres also a small media query to change the font size when the height gets
small; Chapter 8 covers Media Queries in more detail.)
How did I do this? The markup is again very simple (Ive removed some of the
<div>s for brevity; there are seven in all):
<div id=wrapper tabindex=0>
<div id=timing1><p>linear</p></div>
<div id=timing2><p>ease</p></div>
...
</div>
184
CHAPTER 5
I set a default height on the <div>s for the benet of browsers that dont support the JavaScript Ive used (they probably wont support the transitions anyway,
but hey), a default width of 25%, some shadowing to make the bars look good,
and most important, I declared a transition of the width property over 3 seconds.
Next, I set the nested <div> widths to 90%, only when their wrapper <div> is
hovered over. Note that it is very powerful to use pseudo-classes in descendant/
child selector chains like this:
#wrapper:hover div, #wrapper:focus div {
width: 100%;
}
TIP: Notice that Ive used a negative number for the Y-position of the first
control handle in the cubic Bezier example: cubic-bezier(0.25,-0.5,0.75,1). This
causes a bounce effect where the transition goes below its beginning value and then
comes back up again and on to the final value. This technique can be very useful for some
effects, such as a toy boat bobbing up and down in the water after being dropped.
TRANSITIONS
185
And thats pretty much a wrap for this example and for transitions. With a bit of
modication, you could use this example to create a real-world, useful bar graph or
perhaps a question page where hovering over the question will reveal the answer.
You could use some of the other timing functions to make a transition of a duck
moving through water, slowing down as it goes, or a ball falling through the air,
gaining speed due to gravity. The other task I tend to use transitions for, beyond
the examples youve already seen throughout this chapter, is making information
boxes appear. You can see a great example of this on the Monty Python King Arthur
example blog-site.html page if you hover over the More details (+) lines at the
bottom of each blog post summary. The opacity and height of the footer increase,
revealing expanded blog post information (Figure 5.21).
186
CHAPTER 5
You must specify at least transition properties and durations for anything to
animate; the other values are optional. If you dont specify a delay, the default is
0s, and if you dont specify a transition timing function, the default is ease.
If you specify multiple longhand properties, those dierent properties are
looped through to make sure all transitions are assigned a value for each property.
Lets look at another example:
transition-property: opacity, height, width, background-color;
transition-duration: 3s;
transition-timing-function: ease-in, ease, linear;
TRANSITIONS
187
In this case, all four of the transition properties will be transitioned over a
duration of 3 seconds, because that is the only value specied in the transitionduration property. Then for transition-timing-function, the rst property is
given ease-in, the second is given ease, and the third is given linear. But there
is one more property. To give this a timing function, you cycle back to the start of
the transition-timing-function list: the fourth property is therefore given the
ease-in timing function.
You can specify that you want all properties that change upon state change to
transition by just writing transition-property: all;
NOTE: To be honest, I very rarely have to write such complicated
transitions. I usually just write something like transition: 1s all;
(the duration often varies).
188
CHAPTER 5
ANIMATIONS
The next stop on this journey is CSS Animations. As discussed previously, animations dier from transitions in that transitions are triggered by state changes,
whereas animations happen independently. I would argue that animations therefore
have a wider scope and are more useful than transitions. For example, you could
use JavaScript to apply a CSS Animation to an element anytime you want, perhaps
by attaching an animation to an ID selector and appending that ID to the element
when a specic event occurs. This makes it easier, for example, to allow users to
click links to re animations.
You can also use CSS Animations with no JavaScript to create intro sequences of
elements sliding into place or constant ambient background animations. Browser
support for CSS Animations is shown in Table 5.3.
TABLE 5.3 Browser Support for Animations
BROWSER
ANIMATIONS
Opera
12 with -o-
Firefox
5 with -moz-
Safari
4 with -webkit-
Chrome
4 with -webkit-
Internet Explorer
10 with -ms-
iOS
Android
4 with -webkit-
Mobile Chrome
Opera Mobile
No
Opera Mini
No
ANIMATIONS
189
190
CHAPTER 5
@keyframes button-glow {
0%
50%
ANIMATIONS
191
But I wouldnt recommend this rewrite, especially not for complicated animations: It is much easier to visualize the animation progression when the keyframes
are written out in the order in which they occur.
You can have as many keyframes as you want and as many properties specied
inside each keyframe as you want, meaning that complex animations are possible.
You can start your keyframes at a value greater than 0%for example, 50%, 60%,
100%. But nothing will happen for the portion of the keyframes where nothing is
specied.
This is very useful because it means you only have to dene an animation once,
and then you can apply it to as many dierent rulesets as you want. You could have
a whole bank of animation classes set up, and then add them where you need them.
192
CHAPTER 5
This property can take a value with any CSS time units, although youll most
likely use seconds.
ANIMATIONS
193
linear. The animation happens at the same rate from beginning to end.
ease. The default value; the animation starts quickly and then gradually
slows down.
ease-out. The animation starts quickly, stays quick for longer than ease,
ease-in. The animation starts o slowly and then speeds up toward the end.
the transition to jump between a set number of steps placed equally along
the transition. For example, steps(10) would make the transition jump
along in ten steps. You can also set an optional second parameter with a
value of start or endfor example, steps(10, start) or steps(10, end).
This species whether the change in property value should happen at the
start or end of each step. You wont nd much use for this optional parameter,
but it is worth a mention.
tom cubic Bzier curve to use for the animation. This function takes four
arguments: the X and Y coordinates of the beginning control handle, and
the X and Y coordinates of the end control handle. For example, cubicbezier(0.25, 0.1, 0.25, 1.0) is equivalent to the ease preset value. For
more on cubic Bzier curves, see the Cubic Bzier Curves sidebar earlier
in the chapter.
194
CHAPTER 5
In this example, the glowing eect for the buttons was a bit too jerky using
the default ease timing function, so I changed it to linear for a smoother feel:
a:hover, a:focus {
...
animation-name: button-glow;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
ADDING A DELAY
Yup, you guessed it; it is also possible to add a delay before an animation starts by
adding an animation-delay value. This property is a lot more useful with animation than it is with transitions. For instance, you could have an animated sequence
occur on page load or after a button is activated with multiple animations occurring
at dierent times. This type of result is not practical to achieve with transitions.
TIP: You can also give animation-delay a negative value to make the animation start
partway through the specified animation-duration.
ANIMATIONS
195
For example, because I wanted the button glow to run seamlessly, I specied
the button-glow animation like this:
@-keyframes button-glow {
0%
50%
100%
I can now halve the animation-duration value, because each iteration would
now be half the button glow pulse. This is a more ecient way to write this example
and any others where you want the animation to do something and then return to
its original state. But not all animations will be like this.
Ive included this updated version for you in the chapter5 download folder as
animation-basics2.html.
ANIMATION-FILL-MODE
The animation-fill-mode property allows you to specify how the animated element is displayed after an animation ends or during an animation-delay that
occurs before the animation starts (i.e., no eect on negative animation delays).
The possible values of animation-fill-mode are as follows:
none. This is the default value. When an animation ends, the element it is
196
CHAPTER 5
retain the styles dened by the properties in the nal keyframe, after the
animation ends. The nal keyframe will usually be 100% or to. This value is
rather useful if you want the animations to nish in their nal, not beginning, statesfor example, when putting the building blocks of a layout
into place upon page load.
backwards. This property value causes styles dened in the rst keyframe
(usually 0% or from) to be applied to the element the animation is applied to
during an animation-delay rather than the default element styles.
both. This value applies the combined eects of forwards and backwards
to an element undergoing an animation.
I wont provide isolated examples for you to see now; instead, Ill present some
examples later in the chapter that use these values.
ANIMATIONS
197
The spec is not very precise in dening the exact order the property values
should be included in the shorthand, but its best to stick with the preceding order
to avoid potential browser bugs. Various sources indicate that this order fullls
the idiosyncrasies dierent browsers currently have.
You need to explicitly include animation-name and animation-duration for
the animation to do anything. If you dont explicitly specify the other values, their
default values will come into play, which are:
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: none;
You can also apply multiple animations in a single ruleset by including them
in the same property separated by commas. This works for both longhand and
shorthand values, for example:
animation: whoosh 10s, zap 5s;
animation-name: whoosh, zap;
animation-duration: 10s, 5s;
If youre using longhand properties with dierent numbers of values, you need
to specify all the animation names to be applied. If any subsequent properties have
fewer values than the number of animations specied, the values will be alternated
to ll the gaps. For example, look at the following properties:
animation-name: whoosh, zap, bang;
animation-duration: 10s, 5s;
animation-delay: 2s;
The whoosh animation will have a duration of 10 seconds, and the zap animation
will have a delay of 5 seconds. The bang animation will have a delay of 10 seconds,
because the duration values have run out, so they cycle around to the beginning
again. All of the animations will have a delay of 2 seconds.
198
CHAPTER 5
ENHANCING A BANNERAD
WITH ANIMATIONS
In Chapter 4, I introduced you to the Dead Hamster banner ada fair stab at creating a banner advertisement with open standards as opposed to Flash, which looks
cool and draws people in. Now youll enhance the banner using CSS Animations,
Transitions, and Transforms.
To refresh your memory on the state in which you left the last version, open
the example in the poster code download folder. You can also use this le as a
starting point from which to add animations. Here youll look at some new code
additions to add exciting swooshy bits to the banner!
NOTE: The finished code example from this section can be found in
the poster-animations-transforms-transitions code download folder.
Look at the rst frame (<div id=frame1> in the HTML). This would look
deliciously cool (and not at all like a middle managers PowerPoint presentation)
if you had the dierent items of text whooshing into the ad, no?
To do this, you rst need to set up the animations you need. For the four different pieces of text, try these on for size:
@keyframes horizontal-left-150 {
from {transform: translateX(150px);}
to {transform: translateX(0px);}
}
@keyframes horizontal-right-400 {
from {transform: translateX(-400px);}
to {transform: translateX(0px);}
}
@keyframes horizontal-right-500 {
from {transform: translateX(-500px);}
to {transform: translateX(0px);}
}
199
@keyframes horizontal-left-600 {
from {transform: translateX(600px);}
to {transform: translateX(0px);}
}
To apply these animations to the dierent pieces of text, youll use rules like this:
#ad h2 {
animation: horizontal-left-150 1s 1 1s backwards;
}
#ad #band-name {
animation: horizontal-right-400 2s 1 2.5s backwards;
}
#ad #album-name {
animation: horizontal-right-500 2s 1 3.5s backwards;
}
#ad #frame1 ul {
animation: horizontal-left-600 2s 1 4.5s backwards;
}
200
CHAPTER 5
I used shorthand here, so lets run through each value to make sure all is clear
and you know whats going on. In each case:
1. Start with animation-name. Each animation is applied to its appropriate
ruleset by name.
2. Add animation-duration. Each animation must have a duration set on it
to work.
3. Add animation-iteration-count. Each animation occurs only once, so
you dont need to add this in, but I included it to make the code completely
obvious.
4. Add animation-delay. An animation delay is set for each rule so the pieces
of text whoosh in at dierent times, not all together.
5. Add animation-ll-mode. This is set to backwards for all animations, which
means that the animated elements take on the styling dened in their from
keyframes during the animation delay in each case, and then the animation
starts. If you didnt include this, the animation would sit in its default position in each case before being animated from the from position and ending
up back in the to position, which is the same as the default. This would
look terrible. Try removing the backwards keywords and refreshing the
example if you want to see the dierence.
TIP: When creating animated effects where you are animating
elements from outside their container onto it, youll usually want
to set overflow: hidden; on the containing element, so the moving
elements slide into view when they move into it.
201
For a bit of fun, I also decided to try animating the aming text shadow by
varying the text shadow values across dierent keyframes. They ended up looking like this:
@keyframes flamey-flamey {
0% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 2px -10px 6px #FFDD33, -2px -15px 11px #FF8800,
p 2px -25px 18px #FF2200;}
19% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 2px -10px 6px #FFDD33, -2px -15px 11px #FF8800,
p 2px -25px 18px #FF2200;}
20% {text-shadow: 0 0 4px white, 0 -4px 3px #FFFF44,
p 3px -9px 7px #FFDF33, -3px -14px 12px #FF9900,
p 3px -24px 19px #FF3300;}
39% {text-shadow: 0 0 4px white, 0 -4px 3px #FFFF44,
p 3px -9px 7px #FFDF33, -3px -14px 12px #FF9900,
p 3px -24px 19px #FF3300;}
40% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 3px -8px 8px #FFFD44, -3px -12px 11px #FF8800,
p 2px -25px 20px #FF2200;}
59% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 3px -8px 8px #FFFD44, -3px -12px 11px #FF8800,
p 2px -25px 20px #FF2200;}
60% {text-shadow: 0 0 5px white, 0 -6px 5px #FFFF55,
p 2px -7px 7px #FFDD33, -5px -13px 15px #FF7700,
p 4px -24px 19px #FF4411;}
79% {text-shadow: 0 0 5px white, 0 -6px 5px #FFFF55,
p 2px -7px 7px #FFDD33, -5px -13px 15px #FF7700,
p 4px -24px 19px #FF4411;}
80% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 5px -8px 6px #FFEE33, -4px -12px 13px #FF8822,
p 2px -26px 18px #FF2200;}
100% {text-shadow: 0 0 4px white, 0 -5px 4px #FFFF33,
p 5px -8px 6px #FFEE33, -4px -12px 13px #FF8822,
p 2px -26px 18px #FF2200;}
}
202
CHAPTER 5
In this case I didnt want a smooth transition between each frame: I wanted
ve clear frames that would repeat; hence, I used duplicate values to make the
text shadow stay the same across each dierent portion of the animation, for
example 019%.
You can then apply this animation using the following code:
#ad #hell {
animation: flamey-flamey 0.2s infinite;
}
This time youre not setting a delay or an animation-fill-mode, and the ames
will keep aming innitely.
The last change in the example was the way #frame2 appears on hover and
focus. This time I used a simple transform and transition:
#ad #frame2 p {
...
transform: scale(0);
transition: 1s all;
}
#ad:hover #frame2 p, #ad:focus #frame2 p {
transform: scale(1);
}
203
PROVIDING ALTERNATIVES
WITH MODERNIZR
Using the Modernizr feature detection library, lets look at an intelligent way to provide alternative styling for browsers that dont support cutting-edge CSS3 features.
The tour of CSS Animations, Transitions, and Transforms youve just read
about was deliberately kept simple, because there is lots of information to take in.
But hopefully youve started to form some killer ideas about the cool eects you
can achieve using these features. For more involved examples, I recommend doing
a Google search. My favorite examples are still CSS3-man (www.optimum7.com/
css3-man) and Pure CSS3 AT-AT (anthonycalzadilla.com/css3-ATAT/index.html),
both by Anthony Calzadilla.
The trouble is that many of the demos youll see dont give too much consideration to working in nonsupporting browsers. Perhaps it doesnt matter in the case
of throwaway demos, and many examples will degrade gracefully. For instance, look
at the preceding animation-basics.html example, which works perfectly well when
the animations are not supported; you just dont get to see the fun animations.
But what about interfaces in which you rely on animations for viewable content?
A good way to deal with such eventualities is to use feature detection; that is, you
can use JavaScript to detect whether the browser accessing the content supports the
CSS features you are using, and then serve dierent styles depending on the result.
The easiest way to do this for noncode ninjas is to use a feature detection
library; the best available is Modernizr (www.modernizr.com), created by Faruk
Ates, Paul Irish, Alex Sexton, and others. This uses JavaScript to feature detect
pretty much every CSS3 and HTML5 feature, and then lets you selectively apply
scripting and styles to suit. As of version 2, you can even build and download your
own custom version that just includes the tests you want, reducing bandwidth (see
www.modernizr.com/download). While you are experimenting at this point, you
should just stick to using the full, uncompressed version of Modernizr (click the
DEVELOPMENT download button on www.modernizr.com).
Lets run through adding some CSS support detection magic to an example! To
keep it simple and easy to follow, youll revisit the business card 3D ip example.
Open the two-faced-cheek-modernizr.html le in the chapter5 code download
folder for the nished example, or open the two-faced-cheek.html le for a starting point.
204
CHAPTER 5
1. Add a <script> element inside the <head> of your page to include the Modernizr script, for example:
<script src=modernizr-2.5.3.js></script>
Now when you run your page and then look at the code as it is rendered (for
example, in a debugging tool like Opera Dragony), youll see that Modernizr has
replaced your no-js class with a huge string of classes that look something like
those shown in Figure 5.23.
This string allows you to specify dierent styles on a page based on whether
dierent features are supported, using descendant selectors. If JavaScript isnt
supported or turned o, youll just be left with the default no-js class, and you
can provide some kind of safe minimal styles that will probably work everywhere
in the absence of more granular support information:
.no-js p {
color: black;
}
When JavaScript is supported and Modernizr is able to give you that granular
support information, you can start applying fallback styles based on very specic
support criteria. Lets look at what the card 3D ip example required for widerranging browser support.
205
The descendant selector applies a 2D transform to the front face of the card
only when it is a descendant of .no-csstransforms3d. 3D rotation supporting
browsers will ignore this styling. In Opera this styling gives you access to the back
of the card, as shown in Figure 5.24.
206
CHAPTER 5
But what about browsers that dont support 2D transforms? Older browsers
like IE8 or Camino wont support rem units, gradients, transforms, or text shadow,
so what about them?
Modernizr wont help with rem units. The best way to deal with them is to
provide a pixel-size fallback next to the rem unit version of your property, as discussed in Chapter 1:
margin-top: 5px;
margin-top: 0.5rem;
Older browsers will just read the rst one, whereas newer browsers that support
rem units will read both, but the latter line will override the former one.
For other CSS features, youll need to include at least the following CSS:
.no-csstransforms #wrapper:hover #front,.no-csstransforms
p #wrapper:focus #front {
margin-left: -350px;
}
.no-cssgradients #front, .no-cssgradients #back {
background: #FF3500;
}
.no-cssgradients #front p, .no-cssgradients #back p {
/* ideally should be .no-textshadow, but modernizr doesnt seem
p to provide this */
color: #000000;
}
207
The rst rule applies an updated :hover/:focus rule to the ip card so that, if
the browser doesnt support 2D transforms, hovering or focusing the card will just
move the front over by 350 pixels to reveal the back. The second rule provides a
simple, solid background color to replace the posh gradient background in nonsupporting browsers. The third rule just colors the text black, so that it is still readable
without the shadows.
This code produces the simple but usable result shown in Figure 5.25.
TIP: The fallback code still wont work in IE67 due
to a horrible bug involving hover effects not working on
positioned elements with nontransparent background colors. See
http://stackoverflow.com/questions/4378497/ie-bug-absolutelypositioned-element-with-a-non-transparent-background-color
for the solution. Go figure!
208
CHAPTER 5
notice that Im using the same setup as I did in the HTML card ip example (see
two-faced-cheek.html). The front face has the form elements in it, whereas the
back face has a Thank you for your feedback! message in it:
<form id=feedback-form action=# class=>
<div id=front>
<h1>Give us your feedback!</h1>
<div>
<label for=name tabindex=0>Name<span class=
p extended-info> - Enter your first and last name
p so we can identify you more easily.</span></label>
<input type=text name=name id=name>
<!-- Other form elements follow -->
</div>
</div>
<div id=back>
<h2>Thank you for your feedback!</h2>
</div>
</form>
209
Yes Ive used the same card ip behavior as before, but instead of animating it
via a transition and triggering it on hover/focus via pseudo-classes, Ive put the
animation in a CSS animation, like this:
@keyframes form-rotate {
from {
transform: rotateX(0deg);
}
to {
transform: rotateX(180deg);
}
}
.form-rotate {
animation: form-rotate 1s forwards;
}
210
CHAPTER 5
To make the whole form slide in and slide out, two animations have been set up:
@keyframes form-out {
from {
transform: translateX(0rem);
}
to {
transform: translateX(38rem);
}
}
.form-out {
animation: form-out 1s forwards;
}
@keyframes form-in {
from {
transform: translateX(38rem);
}
to {
transform: translateX(0rem);
}
}
.form-in {
animation: form-in 1s forwards;
}
211
But I havent applied the three classes shown earlier to anything yet, so what
gives? Ill do this via some simple JavaScript when the Submit button and <h1> are
clicked. The JavaScript looks like this:
var submit = document.getElementById(submit);
var form = document.querySelector(form);
var back = document.getElementById(back);
var h1 = document.querySelector(h1);
TIP: querySelector and addEventListener are not supported by IE versions earlier than version 9. Therefore, for
IE 68 support, youll need to consider using different code.
Here, references to elements are stored on the page in the following variables:
back. The back face of the form; the <div> with the #back attribute
212
CHAPTER 5
First line. Adds an event listener to the submit variable reference, which
executes the rotateForm function when the Submit button is clicked.
Ive used an if ... else statement to see whether the form is oscreen and I
want to move it on or whether it is onscreen and I want to move it o.
form.className=== || form.className===form-in basically species if
the forms class is empty OR it is set to form-in, then it will be oscreen; therefore,
run the rst Modernizr test. modernizr.cssanimations tests whether CSS Animations are supported by the current browser. If they are, then set the forms class
value to form-out to trigger the animation that brings it onscreen.
213
If the Modernizr test returns false, the animation wont work; instead you
set the left property of the form to 0rem to make the form appear on the screen
in one go, and set the form class to form-fallback so that the second part of the
function will run when the user tries to hide the form again (if you dont do this,
the second part of the function will never run because the form class will always
be blank). Its not as nice-looking, but at least it works.
The last part of this section of the code (the h1.innerHTML part) changes the
text inside the <h1> element to a message telling users they can hide it again if
they want to.
If the outer if test returns false, then the form must be onscreen, and the code
inside the else block is executed, which runs another modernizr.cssanimations
test. If this returns true, the code changes the class value to form-in to animate
it oscreen again. If it returns false, the left property is returned to its original
valueto move it oscreen again in a less glamorous mannerand the form class
is set to blank again to return it to its original state.
The last part of the else block changes the <h1> text back to what it was
originally.
Now on to the second function, rotateForm():
function rotateForm() {
if(Modernizr.cssanimations && Modernizr.csstransforms3d) {
form.setAttribute(class,form-rotate);
form.style.left = 0rem;
} else {
back.style.zIndex = 5;
}
}
214
CHAPTER 5
therefore, Ive forced the form to remain onscreen by setting the left property to
0 with form.style.left = 0rem.
If the Modernizr test isnt true, the browser doesnt support CSS Animations
and/or 3D transforms; therefore, I want dierent styling to occur when the Submit
button is clicked. To allow nonsupporting browsers to see the Thank You message, I used back.style.zIndex = 5; to set the z-index of the #back <div> to5,
making it appear above everything else in the stacking order when the Submit
button is clicked. Figure 5.26 shows the three states Im animating in between.
Ive also used some simple transitions to make the help messages appear when
the form labels are hovered over/focused on:
.extended-info {
...
opacity: 0;
transition: 1.5s all;
}
div label:hover .extended-info,div label:focus .extended-info {
opacity: 1;
}
215
Finally, some Modernizr fallbacks are added to allow older browsers to make
some use of the form:
.no-cssgradients #front,.no-cssgradients #back {
background-color: #009999;
}
.no-cssanimations form {
left: 0;
}
.no-csstransforms h1 {
position: static;
}
.no-csstransforms .extended-info {
display: none;
}
Im certainly not expecting you to know JavaScript just to use CSS. If you dont
understand this code, pass it to your friendly JavaScript developer and collaborate on it. He or she can probably do a much better job of this than I have. In any
case, its worth exploring such techniques because its cool to be able to handle
the animation with CSS rather than having to write it all in JavaScript. Even if you
use jQuery or a similar library, it is still a lot of weight to add to the page just for a
couple of simple animations.
216
CHAPTER 5
WRAPPING UP
You should now be clued into how to use CSS Transitions, Transforms, and Animations to achieve some very cool, fresh eects on your web creations. Also, you
now know how to use feature detection mechanisms like Modernizr to provide
more carefully thought-out alternative experiences to nonsupporting browsers
rather than just IE or not IE as discussed earlier in the book, for example, with
CSS3PIE in Chapter 4.
WRAPPING UP
217
6
USING CSS TO
IMPLEMENT ICONS
219
ICONS ROCK!
Youll nd icons everywhere, helping you nd your way and get additional information about people, objects, services, and so on. Often, they are invisible and are
used almost subconsciously due to the familiarity everyone has with recognized
conventions, such as on/o switches, play and pause buttons, airports and train
stations, and toilets (Figure 6.1)! If you think carefully about icons, youll nd that
you use them more often than you realize.
Since the dawn of man, icons have been used for communication. For example,
cave dwellers painted on their caves to record details of meetings and food. And
the more recent examples of Egyptian hieroglyphics and Chinese symbols most
denitely fall under the moniker of icons.
NOTE: I became interested in icons after serving as editor on fellow English gent
Jon Hickss marvelous book, The Icon Design Handbook (Five Simple Steps, 2012).
In fact, this chapter is influenced heavily by Jons wonderful work. I highly
recommend that everyone purchase his book because it is a real joy to read
and provides more in-depth information than Ive assembled in this short account.
220
CHAPTER 6
Similarly to the real world, icons can ll many roles on websites or in applications.
Most commonly, they act as signposts, giving users hints on how to get where they
want to go and do what they want to do. Icons can impart these hints quicker and
more intuitively than textual descriptions, often due to the fact that they follow
established conventions, which can break through the language barrier: Mail, home,
and shopping basket icons are classic examples (Figure 6.2).
If you need to create an icon to represent something where no convention
already exists, you need to choose an image that is as recognizable as possible, easy
to depict in dierent sizes, and attractive enough to draw in the user. Web icons
are typically monochrome with transparent backgrounds so they can be overlaid
nicely on top of dierent backgrounds.
Icons are loosely grouped into three dierent types:
Arbitrary. These icons are more abstract creations that generally dont
directly relate to real-life objects or concepts. Because they are not realworld objects, they must be learned from scratch and so are not immediately
intuitive. Figure 6.5 provides a good example: This icon set was created
for the W3C as part of its eort to brand HTML5 and other cutting-edge
technologies to raise interest and awareness (see www.w3.org/html/logo).
I wont go into a great amount of detail on how to choose and draw icons in
this chapter, but for those of you interested in nding ideas and inspiration, a
Google images search always brings up many, and you can nd a huge number of
great free icons at thenounproject.com. The images in this section have been taken
from the awesome dingbat sets Modern Pictograms and Heydings Common Icons,
available on Font Squirrel.
221
Icons are a great addition when used in the right contexts, and you should give this
some careful thought when considering them. If they solve a problem along the
lines of allowing users to nd what they want or where they want to go faster and
more intuitively, and consume less space, you have a good case for using an icon.
But if you are just using icons everywhere with wild abandon, their eectiveness
is greatly diminished, and you end up with a horrible Christmas tree-type eect!
Places to consider using icons include:
Navigation. Icons can make great signposts to help direct users to where
they want to go. For example, youll learn how to build the example shown
in Figure 6.6 in the next section The Basics of Icon Implementation.
Status. You need only to look at programs like Skype and messenger applications for good status icon usage, for example, Im here, Im away, Im
asleep. See Figure 6.8 for some examples.
User feedback. Form icons are the classic example for user feedback
(Figure6.10): The format is incorrect, Missing information, and so on.
222
CHAPTER 6
223
To implement icons on a web page, arguably the best method is to use CSS background images. Using the <img> tag is workable, but not the best way, because
icons are not really content; rather, they support content, plus <img> elements
aect content layout on the page and are more ddly to place where you want.
Lets look at a quick example. Youll nd the full code for this in the le basicicons.html in the chapter6 code download folder. You rst need to attach the images
to the elements you want them to appear on:
ul li:nth-of-type(1) a {
background-image: url(icons/home.png);
}
ul li:nth-of-type(2) a {
background-image: url(icons/file.png);
}
ul li:nth-of-type(3) a {
background-image: url(icons/circle_info.png);
}
ul li:nth-of-type(4) a {
background-image: url(icons/pencil.png);
}
224
CHAPTER 6
FIGURE 6.12 A simple icon implementation (icons are taken from www.freeiconsweb.com/
Free-Downloads.asp?id=1729 and are published under creative commons unported).
In the rst rule youre setting a gradient on the actual list item to make the
styling on the links more exible. Then in the second rule youre setting the image
to not repeat, because you only want to show it once, and setting a more appropriate position for the icons, because you dont want them to display in the default
top-left corner position. Youre also setting a bit of left padding to make space for
the icon so it doesnt clash with the text and setting a solid background color as a
fallback for browsers that dont support the CSS3 styling features also at work here.
Some CSS3PIE magic is also included here to provide support for IE68 for extra
styling peace of mind. Also, note that Ive attached Selectivizr to the page to make
IE68 support the CSS3 selectors Ive used in this example, such as nth-of-type.
Figure 6.12 shows the result.
225
This method is also a viable option, although generated content is not supported
as widely across browsers (it wont work in IE67). Youll explore using generated
content more in the Web Fonts as Icons section.
226
CHAPTER 6
CSS SPRITES
The preceding examples work well, but what about implementing multiple icons?
Having to pull in a separate image le for each icon introduces a whole lot of HTTP
requests: To make your code more ecient, you can use CSS sprites. The idea is
that you combine all of your images into a single le, and then show the dierent
icons by varying the background-position property. Your code will look like this
(see basic-icons-css-sprites.html):
ul li:nth-of-type(1) a {
background-image: url(icons/sprite-set.png);
background-position: 35% 10px;
}
ul li:nth-of-type(2) a {
background-image: url(icons/sprite-set.png);
background-position: 35% -40px;
}
ul li:nth-of-type(3) a {
background-image: url(icons/sprite-set.png);
background-position: 35% -90px;
}
ul li:nth-of-type(4) a {
background-image: url(icons/sprite-set.png);
background-position: 35% -140px;
}
In each rule the background-position has the same horizontal value but
increasing vertical values; each increase pushes the image farther and farther
upwards, so that you only have to load a single le but can display dierent icons
227
as you are displaying a dierent part of the image in each case. The result is shown
in Figure 6.13.
228
CHAPTER 6
229
The code to achieve this is very similar to what you used earlier, but it just
requires the use of additional multiple background images to include the modiers. You can see an example of this code in the le modied-icons.html in the
chapter6 code download folder. The code looks something like this (Figure 6.15
shows the result):
ul li:nth-of-type(1) a {
background-image: url(icons/plus.png), url(icons/file.png);
}
/* Other three icons included in a very similar way to the first
p one, but ommitted here for brevity */
ul a {
background-repeat: no-repeat;
background-position: 72px 10px, 50px 10px;
background-size: 13px 13px, 20px 25px;
...
}
As you can see, you now have a set of two background images for each icon:
one for the modier and one for the base icon. Two background-positions and
three background-sizes also go along with those images.
230
CHAPTER 6
Another option available to you is using web fonts as icons. Using a single character
for the icons and applying a web font to them can give you the look you want. This
is a good technique in many ways. The text character will be innitely scalable
when zooming in, and there are a wide variety of Dingbats-style fonts to use to
create suitable icons. The downsides are that browsers must support @font-face
for them to work, font les can be big, and actually adding the character(s) into
your HTML will pollute your content and possibly cause accessibility issues for
those using screen readers.
Lets review these problems one by one. Ive assembled an example for you to
dissect in the le web-font-icons.html in the chapter6 folder. To start, youll nd
your fonts using any of the resources detailed in Chapter 3. I found my fonts at
www.fontsquirrel.com/fonts/list/style/Dingbat.
Next, youll create the dierent font formats you need using the Font Squirrel
@Font-Face Generator (www.fontsquirrel.com/fontface/generator).
Then youll import the fonts in your CSS in the usual way using the bulletproof
font syntax:
@font-face {
font-family: Heydings;
src: url(fonts/heydings_icons.eot);
src: url(fonts/heydings_icons.eot?#iefix)
p format(embedded-opentype),
url(fonts/heydings_icons.woff) format(woff),
url(fonts/heydings_icons.ttf) format(truetype),
url(fonts/heydings_icons.svg#SansationRegular)
p format(svg);
font-weight: normal;
font-style: normal;
}
231
Rather than using images or hardcoding your text characters into your HTML,
youll create them on the y using generated content:
ul li:nth-of-type(1) a:before {
content: H;
}
ul li:nth-of-type(2) a:before {
content: D;
}
ul li:nth-of-type(3) a:before {
content: i;
}
ul li:nth-of-type(4) a:before {
content: w;
}
This avoids the problem of polluting your markup with surplus characters.
However, it can be a bit ddly trying to work out which text character corresponds
to which icon you want to use. You could install the font on your system and then
open a word processor and just type out characters until you nd them, or open
the font in an app like Character Map or Font Book and pick them out of there.
It seems that they are mapped to intuitive characters in this caseH for
home, i for the information symbol, and so onso hopefully other icon font
authors will follow suit and start to adhere to some kind of ad hoc conventions.
232
CHAPTER 6
All that remains to do now is apply the font to your generated content and
position it appropriately:
ul a:before {
font-family: Heydings;
position: relative;
right: 4%;
top: 6px;
}
Because you are using fonts, the icons are very easy to size, color, and even add
drop shadow eects to. This is awesome!
ul a:before {
font-family: Heydings;
position: relative;
right: 4%;
top: 4px;
font-size: 1.6em;
color: #333;
text-shadow: 1px 1px 1px rgba(255,255,255,0.4);
}
233
You can put anything you like after the data- part, and store whatever data
you like in these custom attributes. Then youll have your text characters
stored in your data-icon attributes; you can put them all on the page using
only a single CSS ruleset and eliminate the other four that were present
before:
ul a:before {
content: attr(data-icon);
...
}
234
CHAPTER 6
As another alternative for implementing icons, Ill mention the idea of creating
icons from pure CSS. Lucian Marin pioneered this technique and created an icon
set called Peculiar (http://lucianmarin.com/peculiar). The shapes for these icons
were created using pure HTML and CSS. Figure 6.17 shows the icon set.
As an example, the markup for the Home icon looks like this:
235
width: 0;
position: absolute;
bottom: 7px;
left: 0;
}
.icon-home-rectangle {
background-color: #000;
width: 10px;
height: 8px;
border-bottom-left-radius: 1px;
border-bottom-right-radius: 1px;
position: absolute;
bottom: 1px;
left: 3px;
}
.icon-home-line {
background-color: #000;
width: 2px;
height: 5px;
border-radius: 1px;
position: absolute;
top: 2px;
left: 3px;
}
236
CHAPTER 6
You need to make sure the icon HTML is placed inside the container you want
it to appear in (in this case the anchor) and that the container will display as a
block-level element. In the case of your menu this works ne, because the anchors
are already set to display: inline-block; to make the sizing work. Once all the
Peculiar CSS is in place, you need to modify it a bit. For starters, the general icon
class needs some work:
.icon {
position: absolute;
top: 16px;
left: 48px;
width:16px;
height:16px;
transform: scale(1.5);
}
237
Here Ive set the position to absolute so that I can move the icons into position
and moved them using top and left. Ive also used a transform to set the desired
size of the icons. This was needed because the icon shapes are dependent on the
16 x 16 width and height. If you mess with those dimensions, the icons become
distorted.
The only step left to do is to set the icons parent containersthe anchorsto
be positioned, so that the position I set on the icons earlier will happen relative to
them, not the <body> or another positioned ancestor:
ul a {
position: relative;
...
}
238
CHAPTER 6
WRAPPING UP
And so wraps up the exploration of CSS icons. I hope youve found it useful, and
youll go forward and use icons eectively and responsibly! The examples all work
acceptably in IE 68, to a greater or lesser degree. Which one works best for you
really depends on your particular situation and the browser support needs of
your project.
WRAPPING UP
239
7
CSS3 LAYOUT CHOPS
241
Ill also cover the following modules briey at the end of the chapter. These
do not have solid browser support as of yet, but they are damn cool and will be
important in the future:
242
CHAPTER 7
BROWSER
MULTI-COL
FLEXBOX
GRIDS
REGIONS
EXCLUSIONS
GCPM
Opera
Since 11.1
No
No
No
No
Since 12****
No
No
No
Firefox
2.0 with
-moz-*
2.0 with
-moz-**
No
Safari
3.2 with
-webkit-*
3.1 with
-webkit-**
No
6.0 with
-webkit-***
No
No
Chrome
4.0 with
-webkit-*
17 with
-webkit-
No
16 with
-webkit-***
No
No
10 with -ms-
No
No
Internet Explorer
10
10 with
-ms-**
10 with
-ms-
iOS
3.2 with
-webkit-*
5.0 with
-webkit-
No
No
No
No
Android
2.1 with
-webkit-*
2.1 with
-webkit-**
No
No
No
No
Mobile Chrome
Beta with
-webkit-*
Beta with
-webkit-
No
No
No
No
Opera Mobile
Since 11.1
No
No
No
No
Since 12****
Opera Mini
No
No
No
No
No
No
243
MULTI-COL LAYOUTS
The CSS Multi-column layout spec provides you with a small, focused set of tools for
breaking a body of content into multiple columns. This isnt just limited to text: You
can create multi-col layouts with it if you like, and do smart tasks like have images
or other elements span more than one column. But it isnt great for full multi-col
layouts. For example, you cant specify dierent widths for individual columns.
So without further ado, lets look at a simple example. You can nd my nished
example in the le simple-multi-col1.html in the chapter7 code download folder.
In the le, note that the multi-col-related properties have been specied with
prexes for Firefox, and the WebKit browsers but not for IE and Opera, which supports them without prexes. Also note that most of the properties are applied to
the parent container of the actual content you want to split into columns, in this
case the <section> element that contains the main dummy content.
244
CHAPTER 7
Specifying a number of columns equally divides your content into that number
of columns across the horizontal space available. This produces the eect shown
in Figure 7.1.
You can immediately see why this is useful: It is so exible and easy. Prior to
the introduction of this property, you had to break the content into multiple child
containers and then oat those; if content or layout requirements changed, you
had to modify your markup.
NOTE: In my code youll see that to give the columns some space
around the edges and line up at the top, I had to apply some padding to
the whole <section> and remove the top padding from the first main
content <h2>. You need to think carefully about this kind of styling
when trying to get multi-col layouts to look right. Youll learn more
about this in a more complicated example later in this chapter.
MULTI-COL LAYOUTS
245
The eect this has is to make the columns adopt a best-t approach. If three lots
of the specied distance can t into the available container width or thereabouts,
youll produce three columns. If the width becomes narrower or wider, you may
end up with two or four, and so on. The actual column width does vary, because
the browser tries to t the columns as neatly as possible. Figure 7.2 shows a comparison of dierent container widths.
246
CHAPTER 7
MULTI-COL LAYOUTS
247
248
CHAPTER 7
The problem with column-fill is that it only has an eect when you set a
xed height on the container that you are applying multi-col eects to, as you did
in this example. From my experience, youll almost never want to do this because
you can rarely control the exact amount of content youll want to show across
multiple pages using the same template. So column-fill is of limited use in my
opinion. Ive left the code in the example for you to look at but commented it out.
MULTI-COL LAYOUTS
249
250
CHAPTER 7
Note that Ive also given the image some top and bottom margins, and removed
the top margin from the paragraphs directly after a heading or image to make the
paragraphs line up nicely across the columns. Figure 7.5 shows the result.
column-span seems a bit limited in its eects: The only available values are
1 and all, which seems surprising. I would expect it to break items across a set
number of columns higher than 1. In addition, it doesnt seem to work in Firefox
at the time of this writing, which limits its cross-browser appeal. In Firefox the
headings dont look too bad in one column, but the image looks rather broken.
At the time of this writing, work is being done on implementing column-span in
Firefox, but no ETA has been announced.
break-before. Controls breaking before the element(s) being selected. Possible values are auto, always, avoid, column, and avoid-column.
break-inside. Controls breaking inside the element(s) being selected. Possible values are auto, avoid, and avoid-column.
NOTE: There are other break property values besides those listed, but they
only apply to paged media: avoid-page, left, page, and right.
To stop the columns from breaking after headings, you could use the following ruleset:
h3 {
break-after: avoid-column;
}
It is also best to always break columns before the <h3>s so they appear at the
top of the columns. This can be done like so:
h3 {
break-before: column;
}
MULTI-COL LAYOUTS
251
The only multi-col property this uses is column-width, which allows the number
of columns to change at dierent widths without modifying the content.
section {
...
column-width: 36rem;
}
To get the columns to sit well, I set a xed height on the articles:
article {
...
height: 45rem;
...
}
252
CHAPTER 7
MULTI-COL LAYOUTS
253
MULTI-COL PROBLEMS
Apart from some of the support issues documented earlier, the CSS Multi-column
layout module has other problems associated with it. First, it obviously wont work
in older browsers like IE69. To remedy this, you could use Modernizr to detect
support for multi-col (see Chapter 5 for more information on Modernizr) and provide alternative styling for nonsupporting browsers, perhaps using some kind of
slightly more limited oated layouts. Modernizr refers to multi-col as csscolumns.
This is what you are testing for.
Second, multi-col has a fairly limited scope in terms of how it can be used: It
was created to be used in specic circumstances where you want to put content
into multiple columns and the content isnt too complicated. You cant create full
magazine-style layouts or full multiple-column sites with multi-col, because you
cant specify widths of individual columns, column breaking seems unreliable, and
the spec in general is limited in scope. For such tasks, you need a combination of
dierent layout tools.
254
CHAPTER 7
USING FLEXBOX
USING FLEXBOX
255
This causes the children to be laid out in a horizontal row (Figure 7.7).
If you wanted to lay out your child elements vertically instead in a column,
you could do this:
section {
display: flexbox;
flex-flow: column;
}
256
CHAPTER 7
And the great thing is that you can also reverse the direction the child elements
are displayed in, either horizontally or vertically, by using row-reverse and columnreverse. Try these options to see what happens!
WRAPPING ELEMENTS ONTO NEW LINES
If there are enough child elements to overow the parent element, you can make
them wrap onto multiple lines by adding an extra keyword to the flex-flow property, as shown in the example le our-friends-exbox-wrap.html:
section {
display: flexbox;
flex-flow: row wrap;
}
This is similar to the previous example but contains six <article>s of equal
width, not three. This produces the result shown in Figure 7.8. Note how, when
you reduce the width of the browser window, the layout will go from three to two
to one columna cool responsive eect.
Note: flex-flow is actually a shorthand property for setting the flex-direction
and flex-wrap properties on one line. Their possible values are as follows:
USING FLEXBOX
257
Cross axis
Cross axis
Main axis
258
CHAPTER 7
This initially looks illogical. Surely this code should cause it to appear rst, not
last. With flex-order, you put your child elements inside ordinal groups: The
elements from each ordinal group appear from lowest ordinal group number to
highest ordinal group number, starting from 0. If multiple elements appear in the
same ordinal group, they will then be ordered inside the group according to their
position in the original source order.
USING FLEXBOX
259
In the preceding code you are putting the rst <article> into ordinal group1.
But the default ordinal group is 0; therefore, all the other elements will appear
before it in their natural source order. If you want to make the fourth <article>
appear rst inside the exbox, you could use the following:
article {
...
order: 2;
}
article:nth-of-type(2) {
order: 1;
}
260
CHAPTER 7
By default this will lay out your elements in a column aligned to the left horizontally and sort of near the top vertically. Lets rst align them in a better position
vertically:
header {
display: flexbox;
flex-flow: column;
justify-content: center;
}
USING FLEXBOX
261
262
CHAPTER 7
USING FLEXBOX
263
264
CHAPTER 7
This code produces the result shown in Figure 7.12. The three <articles> have
been given flex: 1, which gives them a positive ex ratio of 1:1:1, so they will
always take up an equal part of whatever space is available.
Now lets see what happens when you give the #cast container a flex value of 2:
#cast {
flex: 2;
}
Figure 7.13 shows the eect. The ratio is now 2 : 1 : 1, so the Cast is now given
twice as much of the exible space as the others.
USING FLEXBOX
265
Lets briey explore the other two arguments and their eects. Try setting
these values on your properties:
#cast {
flex: 1 400px;
}
#facts {
flex: 1 250px;
}
#plot {
flex: 1 250px;
}
In this case, you are setting widths of 400, 250, and 250 pixels on the exible
containers; the remaining width is then divided equally between them, because
the positive ex is set to 1 for all of them.
Now try these values:
#cast {
flex: 1 400px;
}
#facts {
flex: 1 400px;
}
#plot {
flex: 1 500px;
}
266
CHAPTER 7
Here, the combined widths would cause the containers to overow their parent, which would look horrible. Fortunately, a default negative ex value of 1 is set
on all of the children, which causes them all to shrink by an equal amount of the
overow, meaning that all is well. If you wanted one of the children to be reduced
by a larger amount than the others, you could set an explicit negative ex value
on it, for example:
#plot {
flex: 1 3 500px;
}
Now the exible boxes are shrunk in size until they no longer overow their
container. Because the negative ex ratio #cast to #facts is 1 : 3, #cast will have
of the total width reduction applied to it, and #facts will have of the total
width reduction applied to it.
This would cause the Plot to be shrunk by ths of the overow amount, and
the other two to be shrunk by only
ththe shrinking ratio is 1 : 1 : 3.
USING FLEXBOX
267
You can put your cross-browser exbox into action using your old friend Modernizr. Modernizr detects support for the new Flexbox syntax (flexbox/no-flexbox)
and the old version (flexbox-legacy/no-flexbox-legacy).
Look at the code download le our-friends-exbox-modernizr.html. This is
the same as the previous example you looked at except that Modernizr is included
on the page, and a whole raft of legacy Flexbox properties are applied to browsers
that only support the old syntax using Modernizrs descendant selector system. I
wont list all of the fallback code here, but you can nd it under the Modernizr
fallback rules ag in the our-friends-exbox-modernizr.html le.
These properties work fairly well and are fairly self-explanatory, although I
found that box-flex (the old syntax of flex) seemed to work slightly oddly and
unreliably. Hopefully, browsers will support the new syntax soon so that this kind
of craziness will become a thing of the past!
TIP: To provide browsers that dont even support the old Flexbox
syntax with alternative layout rules, use .no-flexbox-legacy xxx { ... }.
268
CHAPTER 7
EXPLORING GRIDS
EXPLORING GRIDS
269
You then divide this container into columns and rows using the grid-columns
and grid-rows properties, like so:
body {
display: grid;
grid-columns: 30rem 40rem 30rem;
grid-rows: 1fr 1fr 1fr 1fr;
}
The grid-columns property species three columns in the grid, and they are
30 rems wide, 40 rems wide, and 30 rems wide, respectively. In this case, the gridrows property is using a new CSS unit called fr (fraction), which means I will be
this many parts of the total big. So in this case you have four rows that are all 1fr
big for a total of 4fr. Therefore, each row spans 1/4 of the total height of the body.
You could also use percentages, other CSS length units, or auto to specify columns, for example:
body {
display: grid;
grid-columns: 30% 40% 30%;
grid-rows: 1fr 1fr 1fr 1fr;
}
In this alternative version, Ive changed grid-columns so that the columns are
percentages (you can see this alternative example in simple-grid2.html). Percentages work the way youd expect them to, although you need to be careful about
using weird combinations of percentages and absolute unit values: If they end
up as less than 100% in one or both dimensions, youll waste space and produce
unexpected results. If they end up as more than 100%, your content may be cut o.
270
CHAPTER 7
You can t these elements to the grid you dened earlier using the following
properties:
grid-column species the column the child element will be placed in, or
grid-row species the row the child element will be placed in, or start in,
grid-row-span species the number of rows that the child element will
span (optional).
EXPLORING GRIDS
271
So, for example, you could lay out your content like this:
header {
grid-column: 1;
grid-column-span: 3;
grid-row: 1;
}
footer {
grid-column: 1;
grid-column-span: 3;
grid-row: 4;
}
#block1 {
background-color: blue;
grid-column: 1;
grid-row: 2;
grid-row-span: 2;
}
/* And so on - look at the code file for the rest of it */
272
CHAPTER 7
grid-columns
1
4%
2
20%
3
20%
7
4%
<article>
<article>
1 300px
<article>
divider
<article>
divider
divider
grid-rows
6
20%
<article>
<article>
2 450px
4 450px
5
20%
<header>
1 300px
3 450px
4
12%
<footer>
You can use nested grids if you like to create all kinds of complicated layouts,
although if you consider doing this, your information architecture might need
revisiting! Im sure this simple example gives you a good idea of how powerful
these grids can be, especially considering that you can create liquid grids as well
as xed grids, and you can place elements wherever you like on the grid regardless
of source order and structure.
EXPLORING GRIDS
273
Ive provided you with the columns and rows declarations free of charge:
grid-columns: 4% 20% 20% 12% 20% 20% 4%;
grid-rows: 300px 450px 450px 450px 300px;
Now you need to work out rulesets to place all the content in the places shown
on the schematic. Look at the example le if you get stuck! The nal example looks
the one shown in Figure 7.16.
GRID PROBLEMS
IE10 is the only browser with decent support for CSS grids at the time of writing.
However, I believe it was worth talking about them, because all the browser vendors
have shown an interest in them of late.
You could also argue that they are not quite as exible as other layout methods
youve seen already. One aspect of grids that surprised me is that you can only place
immediate children of the grid layout element on the grid. But I think it depends
on how you use them. For example, you could use a simple grid to place a header,
footer, and three columns easily, and then lay out the content inside them using
a dierent mechanism, such as Flexbox. A combination of these layout methods
would prove eective in your layout design.
274
CHAPTER 7
A few other CSS3 layout modules are also worth mentioning, although Ill just talk
about them briey, because their browser support and nished status is even more
nonexistent than those youve learned about already.
REGIONS
The CSS Regions Module Level 3 spec (http://dev.w3.org/csswg/css3-regions) denes
a set of functionality for specifying dierent elements to ow content into. This
was supported in IE10 and Chrome/Safari nightlies at the time of this writing. But
at the time, the spec looked to be very much in ux and likely to changehence
my unwillingness to cover it in much detail.
However, for completeness Ill walk you through it. See the le simple-regionsms.html in the chapter7 code download folder for an example that will work in
IE10. Here you have a set of <div>s for laying out content into:
<section id=layout>
<div id=region1 class=region></div>
<div id=region2><img src=images/sunset.jpg
p alt=sunset image></div>
<div id=region3 class=region></div>
<div id=region4 class=region></div>
<div id=region5 class=region></div>
</section>
The regions magic works as follows: You identify the source of the content (in
this case, the iFrame) by its ID and give it a keyword of your choosing:
#region-content {
-ms-flow-into: my-regions;
}
275
You then dictate where the content should ow into by applying your keyword
to the relevant elements. In this case, I wanted the content to ow into the four
<div>s that have a class of region:
.region {
padding: 1rem;
background-color: red;
border: 1px solid white;
-ms-flow-from: my-regions;
}
This is how it currently works in IE10, and it produces the layout shown in
Figure 7.17. Note how Ive actually created this layout using a CSS grid. Indeed, you
can lay out the page in any way you want, and then put the content into elements
of your choosing using regions.
276
CHAPTER 7
Try resizing the browser window and note how the content keeps reowing
inside the regions: The reason is that Ive set the width of the grid rows using percentages. The content starts to ow into the rst region in the source order and
then continues to the second region when the rst is lled, and so on.
WebKit-based browsers currently support regions but with a dierent syntax
that isnt limited to using an iFrame to contain the content:
#region-content {
content: -webkit-from-flow(flow_name);
}
.region {
-webkit-flow: flow_name;
}
An example of this that will work in Chrome Canary only (at the time of this
writing) can be seen in simple-regions-webkit.html. Be warned though: To enable
CSS regions in this browser, you currently need to type about:ags into the Chrome
Canary URL bar, enable CSS Regions in the settings, and relaunch.
TIP: In the same manner as multi-col, you can use break properties to
specify where content should and shouldnt break when it is nearing the
edge of your regions. See http://dev.w3.org/csswg/css3-regions/#region-flow-break
for more details.
EXCLUSIONS
The idea behind the CSS Exclusions and Shapes Module Level 3 (http://dev.w3.org/
csswg/css3-exclusions) is that you can dene a shape or specify an element and
then ow content around that shape/element, thereby creating complicated layouts. You might see these types of layouts in a magazine with text owing around
an image of a mountain or a oated image halfway between two columns of text.
You can think of exclusions as a way to create more powerful oats. Indeed, CSS3
did have a feature called positioned oats, which was invented by Microsoft, but
this seems to have been merged with the Exclusions spec now.
277
Exclusions arent supported anywhere at the time of this writing, but Ill at least
give you an idea of how they are supposed to work. To make a more interesting
oat, you could have a simple section with a gure inside it, like this:
<section>
...
<figure> ... </figure>
...
</section>
You should be able to absolutely position the gure inside the section, and then
turn it into an exclusion using the wrap-flow property:
figure {
position: absolute;
color: #fff;
top: 30%;
left: 40%;
wrap-flow: both;
}
278
CHAPTER 7
wrap-flow species what side of the exclusion element, in this case the gure,
you want the text to ow around. You can specify auto, start, end, both, maximum,
or clear:
auto is the default: If you set this value, the surrounding text will not wrap
around the exclusion; it will just sit underneath the exclusion element as
if it doesnt exist.
start means that content will wrap around the start of the exclusion, but
end means that content will wrap around the end of the exclusion, but the
both means that the content will wrap around the start and end of the
exclusion.
maximum will cause content to wrap around the side of the exclusion that
clear means that content will only wrap around the top and bottom of the
exclusion; the space to the left and right (start and end) of it will be left empty.
wrap-margin species how much margin you want left between the exclusion
element and the rest of the content.
wrap-padding species how much padding you want left between the exclusion
element and the rest of the content.
If you have multiple exclusions interacting inside the same space, they should
wrap around one another in reverse order of how they are placed in the document.
See http://dev.w3.org/csswg/css3-exclusions/#exclusions-order for more details.
If you want your content to ow around a more complicated shape, you can
dene what the shape of the exclusion will be using the shapes part of the Exclusions spec: See http://dev.w3.org/csswg/css3-exclusions/#shapes. Youll be able
to create circles, ellipses, and so on to shape your exclusions or even base those
shapes on images.
279
GCPM
Finally, lets look at the CSS Generated Content for Paged Media (GCPM) module (www.w3.org/TR/css3-gcpm). This module is currently supported only by the
experimental Opera Reader technology, but it is lots of fun to play with. You
can set your whole web page (or a small part of it) to be paginated using rulesets
dened in a special paged at-rule:
@media -o-paged {
...
}
When you load this page in a supporting browser, the whole page content will
be paginated, and you can ick through the pages by swiping left and right on a
touch device, and by using arrow keys on a non touch device.
Opera Reader/GCPM has many more features besides. See Hkon Wium Lies
website at http://people.opera.com/howcome/2011/reader for experimental builds
and a more complete treatment.
280
CHAPTER 7
WRAPPING UP
In this chapter you explored some of the new layout features contained among
the CSS3 modules, including multi-col, exbox, exclusions, and generated content
for paged media.
A signicant number of these features are currently not supported across browsers, and unfortunately, some of them dont degrade gracefully, causing layouts to
completely break in those browsers that dont support them. However, browser
vendors are working hard on adding support for them. In the meantime, you can
provide alternative styling to nonsupporting browsers through tools like Modernizr,
and you should be prepared for the revolution when it comes.
WRAPPING UP
281
8
RESPONSIVE AND
ADAPTIVE DESIGN
283
A BRIEF HISTORY OF
WEB BROWSERS
When the web was rst introduced in the early to mid-90s, it was basically viewable using web browser software installed on personal computers (rst desktops,
and slightly later, laptops). These computers had monitors with resolutions of
640x480 pixels, 800 x 600 pixels, and later on, 1024 x 768 pixels. This didnt really
change much until the middle of the 2000s when mobile phones became powerful enough to run real web browsers (OK, before that was a lame standard called
WAP, but I wont bother discussing it here; you can look it up if you are interested).
Fast forward a few more years and a huge variety of devices are now capable
of browsing the web:
284
CHAPTER 8
Several varieties of tablets are available too, mainly iPads and a slew of
Android-based devices, again running similar browsers to those described
previously but with larger screens.
TVs are increasingly becoming web-enabled: You can view the web on
TVs (from companies like Sony, Samsung, and Ikea) with built-in browsers
and on games consoles run through TVs (like the Nintendo Wii and the
PlayStation 3).
Portable game consoles like the Nintendo 3DS and Sony Vita all have web
browsers as well.
Many people in the world still browse the web using feature phones that
dont have very good web browsers installed or use a proxy browser, such
as Opera Mini to gain access to web content (see the Opera Mini sidebar).
OPERA MINI
Opera Mini is a proxy-based browser that doesnt work like a normal web browser. Usually, you install
a browser on your device that has full rendering capabilities. When a web page is browsed to, the code,
images, and other assets that make up that web page are downloaded to your device and interpreted
and assembled into a web page by the browser for you to interact with. But Opera Mini does not have full
rendering capabilities; it is merely a thin client that can display a static format similar to PDF called OBML
(Opera Binary Markup Language). The web-page code and assets, when requested, are actually downloaded
to a server farm to be assembled into the web page and are then compressed into this OBML format.
The OBML page is then sent to the device to be displayed. This system has some big advantages: First, OBML
is a static, compressed format. The size of the pages you are viewing can be reduced by up to 90 percent
using this system, meaning much smaller downloads, which is great for those on slow networks and those
still paying for web access by the kilobyte. Second, because rendering is done on the server, the Mini client
is very small and simple; therefore, it can run on low-powered phonespretty much anything with a JVM
(Java Virtual Machine).
Opera Mini does have its disadvantages too. Rendering will not look as nice, because many styling features,
such as box shadows and web fonts, are turned off to save on bandwidth and processing power requirements. In addition, OBML just provides a static snapshot of the page you are viewing at the time it was rendered; therefore, animated content (CSS animations, JavaScript-based animations, Flash, or even animated
GIFs) wont work, and background script operations, such as Ajax page updates, wont work either. This
means that web applications that rely on heavy scripting may not perform very well, depending on whether
the developer responsible tested in Opera Mini and used progressive enhancement to still provide a workable experience without JavaScript.
But most websites work well on Opera Mini. The point is not to provide a perfect browsing experience,
but to provide a fast, usable browsing experience that works on nearly any device. It is worth installing
OperaMini on a high-powered device, such as an iPhone. If you are stuck on a slow, mobile phone network
and desperately need to use the web, Opera Mini can be very useful.
285
Broadly speaking, there are three main strategies for optimizing web content across
dierent devices. Lets look at each one in detail.
DO NOTHING SPECIAL
Do nothing special sounds great, huh? The truth is that as long as you create web
content using open standards and best practices, as detailed in this book and other
decent learning resources, your content will probably be accessible across most
devices. The web is responsive by default. The <body> element will cover 100 percent of the browser window width unless you tell it not to. And if you use oats to
arrange repeated content blocks in rows and size containers in percentages rather
than absolute measurements, your layout will have some degree of exibility as
browser windows become narrower.
In addition, many HTML5 and CSS3 features will degrade gracefully in nonsupporting browsers. As you can see in my CSS bling example in Opera 12 (Figure 8.1,
left) and in Opera Mini 6 (Figure 8.1, right), many of the bling eects dont work in
Opera Mini, but the content is still readable.
NOTE: The Opera Mini screen shot shown in Figure 8.1
is actually taken from the Opera Mini simulator, which is
available at www.opera.com/developer/tools/mini.
286
CHAPTER 8
287
Although this might seem like a good idea, it is fraught with problems and you
must be careful. First, youll have to publish and maintain two or more versions
of your site (desktop version, mobile version, iPad app, TV app, etc.), which adds
more time and cost to the project.
Second, doing browser sning is error prone and shortsighted. If you are just
detecting the iPad, for example, because you have a specic iPad app, it might
not be so bad. But it usually makes more sense to develop sites to work across all
devices, not just one. Also, user agent strings are deliberately ambiguous, because
back in the early days of the web, developers started using user agent sning to
arbitrarily target browsers they wanted to support, leaving other browsers locked
out, even if they could render those sites perfectly well. To get access to these sites,
browsers started aping other vendors user agent strings, so youd end up with
user agent strings like this:
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13
p (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
And even if your code is serving the right content to the right browsers now, it
may not in the future when new browsers come out that have dierent user agent
strings. Youll have to keep updating your code to take these new browsers into
account! As an example, when Opera hit version 10, the user agent string was
changed to include a version number of 9.81, because so many developers were
using browser sning code that returned Opera 10+ as Opera 1, thereby blocking
browsers from accessing sites that would render them ne. Hilarity ensued. Really.
It is much more eective and less error prone to test whether browsers support
the features your sites need, as youve been doing with Modernizr, rather than
testing whether the browser is one of the ones you think will support your code.
TIP: You should always provide a link to switch between site
versions too, in case a mobile user wants to use the desktop
version of the site instead. Users hate having their choices taken away!
288
CHAPTER 8
TERMINOLOGY CONFUSION!
You were probably wowed when you first read the delicious buzzword-laden title of this chapter. I included
both responsive design and adaptive design because youll probably hear these two terms and various other word combinations to describe the techniques this chapter covers in your travels around the
interwebs.
In fact, I was confused about when to use which term. So, after doing a bit of research on the subject, the
best distinction between adaptive and responsive that I came up with is as follows:
Responsive design refers to the use of technologies like media queries and flexible units to create flexible web page/app layouts that are optimized to suit different-sized viewports.
Adaptive design is pretty much another term for progressive enhancement, which of course was
defined in Chapter 1, and examples have been shown throughout the book. Adaptive design refers to
any design that allows a website to adapt and provide an acceptable experience in browsers of different
abilities. You could think of responsive design as a subset of adaptive design.
Youll also hear the term mobile web quite a lot, especially from manager types; its used to describe the
web created for mobile devices, or some such thing. I recommend that you stay away from this term as
much as possible.
Designer and all-round good bloke Stephen Hay summed it up nicely when he said: There is no mobile
web. There is only the web, which we view in different ways. There is also no desktop web. Or tablet web.
Thank you.
Creating different sites for different devices is not really the right way to think about accessing web content;
you should strive to optimize the same content for different devices.
A better way to think about mobile is a state of being rather than a device. When users are mobile, they
are more likely to be using various devices to browse the web, have less bandwidth available, and be interested in different information and functionality. This leads to a separate set of requirements for people who
are stationary and those who are on the move. Therefore, different versions of your site will require different UX work.
289
Serving smaller images, videos, and other media to smaller screen devices
that dont need the bigger versions and could really benet from being
saved some bandwidth.
290
CHAPTER 8
BROWSER
MEDIA QUERIES
@VIEWPORT CSS
Opera
Since 9.5
?*
n/a**
n/a**
Firefox
Since 3.5
?*
n/a**
n/a**
Safari
Since 4
?*
n/a**
n/a**
Chrome
Since 4
?*
n/a**
n/a**
Internet Explorer
Since 9
?*
n/a**
n/a**
iOS
Since 3.2
?*
Since 3.2
No
Android
Since 2.1
?*
Since 2.1
No
Mobile Chrome
Since beta
?*
Since beta
No
Opera Mobile
Since 10
?*
Since 10.0
Since 11.0
Opera Mini
Since 5
?*
Since 6.0
No
* It was difficult to find any concrete, detailed support data for the <source> media attribute. But from my tests,
itseems to work well across all the latest desktop and mobile browsers.
** The Viewport meta tag and @viewport arent relevant to nonmobile browsers.
Optimizing one site for dierent browsers/devices is the strategy mainly covered
in this chapter. It is arguably the best and most future-proof way of optimizing
your content for dierent browsers/devices. In reality, most modern sites will use
a combination of this strategy and the preceding strategyserving dierent sites
to dierent devicesto provide a decent experience to various devices. Lets move
on and look at some groovalicious, modern web-design techniques.
291
Nav 220px
Footer 100%
So far in this book, Ive deliberately not considered responsive design very much
because I wanted to dedicate this chapter to it! However, youve already seen some
of the elements of responsive design without even knowing it, mainly the exible
techniques Ill talk about in this section.
292
CHAPTER 8
FIGURE 8.4 The flexible layout with the content filled in. Love that retro feel!
293
A good way to get the media elements to also breathe inside their containers is to
set max-width: 100%; on those elements. So even when the images and videos are
larger than their containers, they will be constrained inside. And as the containers
shrink or grow, the media elements will shrink and grow with them (Figure 8.6).
294
CHAPTER 8
To give you some examples, Ive used this trick on the main playing video, the
related reels, and the other videos in the reel:
video {
max-width: 100%;
}
#related article {
...
width: 35%;
margin: 2rem 2%;
padding: 2rem 3%;
}
#related img {
display: block;
margin: 0 auto;
max-width: 100%;
}
#video-reel article {
width: 33%;
display: inline-block;
opacity: 0.7;
}
#video-reel img {
max-width: 100%;
}
295
Another good way to use max-width when creating responsive layouts is to set
an upper bound on your layout width. When your layout starts to look ghastly in
very wide viewports (and lets face it, big cinema-screen monitors are increasingly common these days), you can control the result using something like this:
body {
max-width: 1300px;
margin: 0 auto;
}
When the upper bound is reached, the layout will no longer grow but instead
be centered inside whatever space is available, as shown in Figure 8.7.
TIP: max-width is not supported in IE7 and earlier; therefore, Ive
set width: 100% as a fallback in the iefixes.css file included in one
of my conditional comments (along with pixel fallbacks for all the units
set in rems, which arent supported in IE8 and earlier). But you must be
careful with this: width is way less flexible than max-width. If the container
is smaller than the image, the image will maintain its set width and overflow the container.
296
CHAPTER 8
MEDIA QUERIES
The Media Blitz example is looking good now, but it is still not great. When you
resize the screen less than 1024px in width, the <h1> wraps onto two lines, and
the media elements start to look tiny and insignicant. This is unacceptable given
that they are supposed to be the main content of the site!
Wouldnt it be great if you had a mechanism to dynamically alter the layout of
your site based on features such as width and height?
Well, heres the good news: The Media Queries spec (www.w3.org/TR/
css3-mediaqueries) allows you to do just that! In a nutshell, it extends the functionality of CSS3 media types, which allow you to apply styles to markup based
on whether it is onscreen, being printed, and so on:
@media print {
/* print styles go here */
}
<link rel=stylesheet media=print href=print.css>
Media queries go even further, allowing you to apply styles based on media
types plus the result of tests on the condition of media features, such as browser
viewport width, screen orientation, resolution, and more. Here is a simple example:
@media screen and (max-width: 800px) {
/* put your styles here */
}
This code block species the following: For the screen media type only, if the
width of the browser window is 800 pixels or less, apply the styles within the block.
If these conditions arent true, completely ignore the rules within the block. You can
immediately see how powerful this feature is. It means that you can start applying
dierent styles to your site depending on features like screen width, so you can
provide one layout for a wide viewport, one for a narrow viewport, and as many
more as you like!
MEDIA QUERIES
297
If you want to apply your custom styles to any media type, you can use the
keyword all, or just omit the media type. The following are equivalent:
@media all and (max-width: 800px)
@media (max-width: 800px)
You can use the not keyword to indicate that you want to apply your styles in
any case other than the one evaluated as true by the media query. For example:
@media not screen and (max-width: 800px) {
/* put your styles here */
}
You can chain further conditions onto the ends of your media queries to enforce
stricter conditions, for example:
@media screen and (max-width: 800px) and (orientation: landscape) {
/* put your styles here */
}
If you want to apply the same set of conditional styles when multiple conditions
are true, you can put the dierent sets of conditions on the same line, separated
by commas, like so:
@media screen and (max-width: 800px), print and (max-width: 29.7cm)
{
/* put your styles here */
}
The most common media features youll want to test are as follows:
or height of your browser windows viewport: the part of the window that
the web page is actually displayed in.
298
CHAPTER 8
min/max-device-width and min/max-device-height. Apply styles depending on the physical width or height of the device rather than the viewport.
The importance of this distinction will become apparent later in the chapter.
MEDIA QUERIES
299
#main-panel {
margin-left: 0px;
}
nav ul {
width: 100%;
}
nav li {
display: inline-block;
}
nav li a {
display: block;
margin-right: 3rem;
}
nav hr {
width: 90%;
}
body {
display: table;
width: 100%;
}
nav {
display: table-caption;
table-layout: fixed;
caption-side: bottom;
}
}
300
CHAPTER 8
You force these rules to kick in when the browser window is less than 1024
pixels in width. When they kick in, you remove the oat from the <nav>, change
its width to 100%, and get rid of the left margin from both the <nav> and the
#main-panel so that the location of the navigation menus changes from the side
of the layout to the top of it. You then set the list items to display: inline-block
so they sit alongside one another rather than on top of one another, do a couple of
other minor adjustments there, and then use some CSS tables magic to relocate the
navigation to the bottom of the site instead of the top. Figure 8.8 shows the result.
MEDIA QUERIES
301
If you need to target more devices, you might well expand your list of
queries to suit other screen sizes. Targeting devices like this is referred to
as setting device breakpoints.
My personal preference is to use content breakpoints instead: I usually
ignore target devices completely and just add in media queries to fix the
layout when it breaks. This methodology is more flexible and therefore
better overall for supporting a wide range of devices. But it is often a bit
more complicated than just creating a couple of well-thought-out layouts
for specific screen sizes. The choice is yours.
Width- and orientation-based media queries are certainly the most common
media queries youll use, although with so many high-resolution devices
now available on the market, you might also want to provide different
images or layout features depending on resolution: see the High-fidelity
Devices section later in the chapter.
302
CHAPTER 8
The next media query simply reduces the font size and spacing of the navigation menus to make them t better at slightly smaller widths:
@media all and (max-width: 870px) {
nav {
font-size: 3rem;
}
nav li a {
margin-right: 1rem;
}
}
The third media query performs a number of tasks but basically narrows down
the Related Reels sidebar to a single column and alters the layout of the Video
Reel section.
@media all and (max-width: 800px) {
...
}
MEDIA QUERIES
303
The fourth media query puts all the major containers in a single column but
puts the Related Reels into two columns again:
@media all and (max-width: 600px) {
...
}
The nal media query kicks in at 350 pixels or less, which reduces the Related
Reels to a single column again and makes the <h1> smaller:
@media all and (max-width: 350px) {
...
}
304
CHAPTER 8
The table-related properties are part of CSS2. They were created to allow web developers to lay out groups
of elements with a tabular structure without abusing table markup. An obvious application of CSS tables
is to lay out forms in an easier fashion (see the file form_csstables.html in the chapter8 code download
folder). This is basically achieved using markup like this:
<ul>
<li><label><input></li>
...
</ul>
The technique Ive used in my media query example is the only known way to move the position of a child
element from side to top to bottom reliably without changing the source order. It is a useful technique to
keep in mind, although bear in mind that these properties dont work in IE7 and earlier.
MEDIA QUERIES
305
MOBILE FIRST
Lets now turn the media query example on its head by looking at the Mobile First
technique invented by Luke Wroblewski. This technique reverses what you did in
the preceding section. You create the mobile layout rst as the default layout, and
then apply wider layouts as the browser width increases.
The Media Blitz example is recreated using Mobile First in the le media-blitz4-mobile-rst.html. I wont show all of the code here, but be sure to dig through
the le so you can appreciate the dierences between media-blitz-3 and mediablitz-4. The former starts with the wide-screen layout and layers on styles suitable
for narrower screens. The latter starts with the narrow-screen layout and layers
on styles suitable for wider screens. As a brief example, the <h1> is initially set to
its smallest size:
h1 {
font-family: Monoton, cursive;
}
This reverse method has many advantages: One of which is that it is often easier
to start by designing a simple, narrow (mobile) layout and then add on complexity
to work up to a richer wide-screen (desktop) layout than it is to design a complex,
all-singing wide-screen layout and then try to factor that down to an eective
(uncluttered) narrow layout.
306
CHAPTER 8
One problem with Mobile First is that browsers that dont support media queries will get a mobile layout rather than a desktop layout. To x this, you could
include a JavaScript polyfill in your page. The two worth checking out are
css3-mediaqueries.js (http://code.google.com/p/css3-mediaqueries-js) and
respond.js (https://github.com/scottjehl/Respond). Both work in the same sort of
way. You just include the JavaScript in your page after the CSS declarations. All my
responsive examples from number 4 (media-blitz-4-mobile-rst.html) on include
the following:
<script src=respond.min.js></script>
307
Another advantage of Mobile First is that you can easily serve smaller background
images to smaller devices, and then swap them out for bigger images using rules
in wider media queries. For example, in simple-responsive-header-image1.html,
a background image spans the whole <header>, which runs across 100 percent of
the screen width. Ive included it like this:
header {
...
background: url(images/sunset.jpg) center;
}
Setting it to display in the center ensures that the nice sun in the center of the
image will always display in the center of the header. But theres more you can do
here.
Take a look at simple-responsive-header-image2.html. The original 1024px
wide image is 41 KB, which doesnt make much dierence to a user with a fast connection but could slow down response time somewhat for a mobile user on a slow
mobile network. To mitigate this, Ive included a 480px version in the default CSS:
header {
...
background: url(images/sunset-480.jpg) center;
}
308
CHAPTER 8
Devices that have a browser window width of 480px or less will only load the
small image, and devices with a browser window width of over 480px will load
the larger image.
Of course, the preceding technique doesnt work for images put on the page
using <img>. Often, youll want to serve smaller content images to smaller devices
too. This is a much harder problem to solve. Fortunately, intelligent people have
been thinking about this problem. For a robust solution that relies on some serverside magic, check out Matt Wilcoxs excellent Adaptive Images technique. All youll
need is at http://24ways.org/2011/adaptive-images-for-responsive-designs.
309
RESPONSIVE VIDEO
For video, the solution to making it responsive is a bit dierent. HTML5 <video> has
a rather nifty responsive mechanism includeda media attribute on the <source>
element in which you can insert a media query test. If the test is passed, that
video source is the one loaded into the <video> element, unless of course another
<source> element later on in the source order overrides it.
In media-blitz-5-responsive-video.html, you can see this in action:
<video controls>
<source src=videos/320/crystal320.mp4 type=video/mp4
p media=all and (max-width: 480px)>
<source src=videos/320/crystal320.webm type=video/webm
p media=all and (max-width: 480px)>
<source src=videos/720/crystal720.mp4 type=video/mp4
p media=all and (min-width: 481px)>
<source src=videos/720/crystal720.webm type=video/webm
p media=all and (min-width: 481px)>
...
</video>
When the screen width is 480px or less, the 320 video is loaded; when the
screen width is more than 480px, the 720 video is loaded.
NOTE: I cheated slightly in media-blitz5.css. I set the <video> element to
width: 100%, not, max-width: 100%, so that the video will always span the
full width of the screen, even when the 320 video is displayed across the
full-screen width at 321480px. This is not a great idea, especially when
the width gets much bigger, because the video will start to look very
grainy. You need to be especially mindful of this on very high-resolution
devices like the iPhone 4.
310
CHAPTER 8
There is more to optimizing content for mobile devices using media queries than
you might rst think. If you view one of the media query examples youve seen so
far in this chapter on a mobile phone, youll see the surprising result shown in
Figure 8.11.
NOTE: You might also get slightly odd positioning or other behavior
of the video depending on the mobile device viewing the content,
because some mobile browsers will play the video inside the browser,
whereas others hand off the video playing to the devices native player.
The problem here is that mobile browsers lie. When a mobile browser renders
the average site, it doesnt render it at the actual browser width and display it as is.
Instead, it renders the site at a higher assumed widthOpera Mobile, for example,
uses 850px (and sometimes goes wider, depending on how wide the page being
rendered is)and shrinks the result to t on the mobile screen.
311
You can understand why browser creators would do this. Historically, most
sites are not created with responsive techniques in mind; therefore, they would
look crappy if rendered at widths of 480px, 320px, or less. But in this responsive
world, you should override this behavior so that your media queries behave like
you want them to.
You could do this by changing your width/height media queries to always test
for the equivalent device-width/device-height as well. For example:
@media all and (max-width: 800px), @media all and
p (max-device-width: 800px) {
...
}
But having to do this for every @media block means a lot of extra typing and
hassle, so lets look at a better solution: viewport.
<META NAME="VIEWPORT">
A better, less messy way to make media queries behave themselves is to use the
viewport meta tag. Invented by Apple to make web apps display more reliably
on iDevices, it was adopted by other browser manufacturers because it is a jolly
good idea.
To get your media queries to behave (Figure 8.12), you can add the following
line into your HTML <head> (see media-blitz-6-with-viewport.html in the code
download folder):
<meta name=viewport content=width=device-width>
This makes the browser render the site at its true width, triggering media queries as appropriate.
312
CHAPTER 8
The viewport meta tag is not just limited to forcing browsers to tell the truth
about the sites width or height. You can also do the following:
Set a specic width or height to render at. This is done using a number
for the width or height value. For example,
<meta name=viewport content=width=320>
Set an initial zoom factor for your content. This is done using initialscale and a zoom factor:
<meta name=viewport content=initial-scale=1.5>
Such values work just like CSS scale transforms: 1.5 means zoom in by
50%, 0.75 means zoom out to 75% of initial size, and so on.
Set the target pixel density. As youll see later in the High-delity Devices
section, devices with high resolutions will often have multiple physical
313
device pixels for each pixel on your page (sometimes called CSS pixels). To
alter how many or just set a CSS pixel to equal 1 device pixel, you can use
target-densitydpi=device-dpi. For example:
target-densitydpi=device-dpi or
target-densitydpi=160.
<meta name=viewport content=target-densitydpi=device-dpi>
Set a maximum and/or minimum allowed zoom factor for your content.
If you want to limit how far your users can zoom in or out, you can use
maximum-scale and minimum-scale, like so:
<meta name=viewport content=maximum-scale=2, minimum-scale=0.5>
314
CHAPTER 8
@VIEWPORT
You might be thinking that this viewport thing smells like presentation
rather than content so should probably be handled using some kind of
CSS construct rather than an HTML meta tag. Some clever folks at Opera
agree and have produced the @viewport rule spec (http://dev.w3.org/csswg/
css-device-adapt/#the-viewport-rule), which defines the same functionality
as Viewport meta tag but as a CSS construct. The different options available in Viewport meta tag all have their equivalents in @viewport, except
target-densitydpi (hopefully, this will be added later):
@-o-viewport {
width: device-width;
width: 320px;
zoom: 1.5;
max-zoom: 2;
min-zoom: 0.5;
user-zoom: fixed;
}
Note that @viewport currently works only in Opera Mobile 11 and later, but
in my opinion it is a better implementation than Viewport meta tag, and
should catch on in the future.
315
HIGH-FIDELITY DEVICES
Or in the case of CSS background images, you could check for a certain pixel
ratio via a media query and use additional rules inside the media query to x the
issue in browsers that pass the test.
For example, you could use background-size to cancel out the eects of the
device zoom in the case of a background slice:
#wrap {
background: url(images/wood.jpg);
}
@media screen and (min-device-pixel-ratio: 3/2) {
#wrap {
background-size: 255px;
/* Original image is 1.5 times this size - 383px */
}
}
316
CHAPTER 8
Or when dealing with icons, you could serve a larger background image to
devices with a higher pixel density, for example:
ul li:nth-of-type(1) a {
background-image: url(icons/home-32.png);
border-radius: 20px 0 0 0;
background-position: 25px 50%;
}
@media screen and (-o-min-device-pixel-ratio: 3/2) {
ul li:nth-of-type(1) a {
background-image: url(icons/home-48.png);
}
}
You can see working examples of these techniques in the le high-resolutionexample.html. Note that at the moment min-device-pixel-ratio is supported differently across browsers: Opera Mobile uses ratio values, for example, 3/2, whereas
WebKit-based mobile browsers support it with decimals, such as 1.5. In the example
le youll see multiple versions of the media query with dierent vendor prexes
used to serve the dierent browsers values they recognize.
If you want to stop mobile browsers from applying their default zoom, you could
use the target-densitydpi viewport feature to tell the browser, I really do want
to make 1 pixel equal 1 pixel; tell the whole truth, damn you! like this:
<meta name=viewport content=width=device-width,
p target-densitydpi=device-dpi>
HIGH-FIDELITY DEVICES
317
A RESPONSIVE HEAVY
METAL BANNER AD!
As promised earlier in the book, Ill round o this chapter by returning to the heavy
metal banner ad and making it responsive. Ill make it pair down to the smaller
large rectangle ad size of 336 x 280 in devices with screens narrower than 800px
and change it to a narrow banner that spans 100 percent of the screen width in
very narrow devices (less than 480px in width). Ill also use the media attribute in
my video <source>s to stop the video being served to narrow-screen devices and
include a background image instead in such cases. See the poster-responsive folder
in the root of the code download for the nished new version.
A fair amount of work was required here to adjust all the styles and get the ad
looking good at this narrower size. I wont discuss all the CSS changes in the media
query, because there is nothing new here. To see all the new styles, search for the
preceding media query in the code and check them out.
Note that I didnt tweak the animations: When I tested the narrow size in animation-supporting browsers, all the animations seemed to still look ne.
Here is how I set up the alternative styling for narrow-screen browsers. Note that
Ive completely hidden the <video> to save on processing in small-screen devices:
@media all and (max-width: 480px) {
video {
display: none;
}
318
CHAPTER 8
#ad {
width: 100%;
height: 90px;
background-image: url(bg-alternative.jpg);
font-size: 13px;
}
#ad, #ad div {
width: 100%;
height: 90px;
}
#ad #band-name {
top: -10px;
left: 20px;
}
#ad #album-name {
top: 50px;
right: 40px;
}
#ad #frame1 ul, #ad #frame2 p {
visibility: hidden;
}
#ad h2, #ad #band-name, #ad #album-name, #ad #frame1 ul {
animation: none;
}
}
319
Here I implemented some simple styling to alter the ads dimensions. I also hid
the video player and some of the text, and turned o all the animations (except
the awesome ames), because I felt the ad would be too cluttered at a smaller size.
Smaller, less-powerful devices also appreciate less load on their processors.
And thats it! Figure 8.13 shows the three dierent sizes of the ad.
WRAPPING UP
This chapter has given you valuable insights into optimizing your web creations
so theyll look better and perform better on dierent types of devices, from tiny
mobile devices to wide-screen monitors. Along the way you looked at media queries,
viewport, adaptive image and video techniques, and more. I think youll agree that
this chapter was a lot of fun, so go forth and play!
320
CHAPTER 8
INDEX
NUMBERS
2D transforms
applying, 159
matrix, 160
rotate, 155156
scale, scaleX, scaleY, 157158
skew, skewX, skewY, 158159
translate, translateX, translateY,
153154
X, Y, and Z axes, 154
3D animations, hardware acceleration,
177. See also CSS Animations
3D transforms. See also CSS
Transforms
backface-visibility, 174177
matrix3D, 165
perspective, 165170
rotate3D, 163164
rotateX, rotateY, rotateZ, 162
scale3D and scaleZ, 165
transform-style, 171174
translate3D, translateZ, 160161
trouble with, 178
SYMBOL
:: (double-colon) syntax, 33
A
accessibility, prioritizing, 78
adaptive design, versus responsive
design, 289
Adaptive Images technique, 309
adjacent sibling CSS3 selector, 23
Android
animations, 189
bling boxes, 109
CSS3 Color Units, 16
font formats, 74
layout features, 243
rem units, 20
responsive design features, 291
text features, 87, 94
transforms, 152
transitions, 179
animating aming text, 202203
animation rate, altering, 194195
195196
193, 198
animation-fill-mode property, 196197
animation-name property, using,
192, 198
animations. See also 3D animations;
CSS Animations
adding delays, 195
applying to elements, 192
button-glow, 196
card ip behavior, 208, 210
enhancing banner ad with, 199203
:hover/:focus rule, 208
menu-move, 193
moving <h1>, 210212
multiple, 197198
overflow: hidden, 201
running number of times, 193
shorthand, 197198
sliding form, 211
triggering via JavaScript, 208216
whoosh, 198
animation-timing-function, 194195
anti-aliasing, 81
<article> element, 5153
<aside> element, 5455
Ates, Faruk, 67, 204
attr() function, using, 33
attribute CSS3 selector, 22, 27
<audio> element, 48, 50
control buttons, A-4A-5
media styling, A-10A-11
resources, A-11
SVG and <canvas>, A-10A-11
wiring buttons with JavaScript,
A-5A-9
B
backface-visibility 3D transform,
174177
background content, rendering, 140
background images
serving to small devices, 308
using in banner ads, 144
background-clip property, using, 140
background:radial-gradient, 126
backgrounds
attaching to elements, 132
gradients, 133
in IE versions, 135
using linear gradients on, 119
background-size, using gradients with,
134135
banner ad. See also bling boxes
adding bling to, 142146
animating aming text, 202203
background images, 144
enhancing with animations,
199203
heavy metal example, 318320
improving, 146
recommended size, 142
repeating radial gradient, 145
support for older browsers, 145146
Bzier curves, cubic, 182
bling boxes. See also banner ad; CSS3
features
adding depth, 114117
adding to banner ad, 142146
advantages, 108
border-image property, 136140
box-decoration break property, 141
box-shadow property, 114117
browser support for, 109
disadvantages, 108
examples, 108
border-image property
applying, 136138
central slice, 139
fragments, 138
problems, 139140
providing space, 139
tiling sides, 138
url() syntax, 137
border-radius property, 110113
Boulton, Mark, 142
box-decoration break property,
using, 141
boxes. See bling boxes
box-shadow property, 114117
browser support. See also mobile
browsers; Modernizr
animations, 189
bling box features, 109
color units, 16
CSS selectors, 2226
INDEX
321
C
Caballero, Luz, 63
Calzadilla, Anthony, 204
<canvas> element, 6263
capitalization, controlling, 100
captions, creating, 5657
Cederholm, Dan, 9
character set, dening, 4243
child CSS3 selector, 23, 25
Chrome
animations, 189
bling boxes, 109
CSS3 Color Units, 16
font formats, 74
layout features, 243
rem units, 20
responsive design features, 291
text features, 87, 94
transforms, 152
transitions, 179
Chrome Mobile
font formats, 74
text features, 87, 94
Clark, Keith, 34, 67
ClearType, use by Windows, 81
Collison, Simon, 86
column layouts, 5. See also CSS Multicolumn layout module
content
generating, 26
thought process for, 1011
corners, rounded, 110113
CSS, Bulletproof, 4
CSS Animations. See also 3D
animations; animations
at-rule block, 191
322
INDEX
background-color, 191
D
date and time, marking up, 5758
datetime attribute, using, 5758
Dead Hamster banner ad,
142146, 199
descendant CSS3 selector, 23
design philosophies. See web design
philosophy
Devlin, Ian, A-11
DHTML (dynamic HTML), 39
DOCTYPE, using, 41, 43
double-colon (::) syntax, 33
dynamic UIs, 5
E
elements. See also HTML5 elements
repeating patterns of, 29
selecting, 23, 26, 28
styling, 2325
ellipsis;, using with text-overflow
property, 9091, 93
embedded video, implementing with
HTML, 40
error messages, examples of, 6162
Eye of Sauron, 167168
F
feature detection library. See
Modernizr
<figcaption> element, 5657
<figure> element, 5657
Firefox
animations, 189
bling boxes, 109
CSS3 Color Units, 16
font formats, 74
rem units, 20
responsive design features, 291
text features, 87, 94
transforms, 152
transitions, 179
Flexbox. See also layout modules
aligning children, 261262
align-items property, 262
align-self property, 262
<articles> and <section>, 256
box-flex property, 268
browser support, 255
Cast container, 265
child <articles>, 264265
child ow direction, 256257
cross axis, 258
cross-browser with Modernizr,
267268
display order of child elements,
259260
display property, 255
Facts container, 265
flex property, 263264
flex-flow property, 257258
exibility of, 263267
flex-order property, 259
<header> content, 261
G
Gallagher, Nicolas, 64
Gasston, Peter, 267
GCPM (Generate Content for Paged
Media), 243, 280
general sibling CSS3 selector, 23
Google
Fonts service, 79
webfont loader, 78
Google Code, HTML5 shiv, 4546
graceful degradation, 89
gradients
features, 118
linear, 118123
radial, 124130
using with backgrounds, 133
grid layout examples, 272274
grid structure. See also layout modules
dening, 269270
grid-columns property, 270
grid-rows property, 270
grids
elements, 271
tting content onto, 271273
Gunther, Lars, 43
H
<header> element, 54
headings
determining levels of, 56
grouping, 56
heavy metal banner ad, 318320
<hgroup> element, 56
Hicks, Jon, 216
high-delity devices, 316317
highlighting words, 59
Holy Grail tribute site, 72, 7577
Home icon
CSS applied to, 235236
markup for, 235
:hover eect, using with
transforms, 163
HSL, browser support for CSS 3 Color
Units, 1618
HSLA, browser support for CSS 3 Color
Units, 1618
INDEX
323
I
IAB (Internet Advertising Bureau), 142
icons
arbitrary, 221
background images, 229230
background-position property, 227
background-size property, 228229
comparison, 222223
CSS sprites, 227228
emotion, 222223
functionality, 222
generated content for, 226
guidelines for use of, 222223
ideograms, 221
implementing, 224230, 235238
324
INDEX
J
JavaScript, triggering animations with,
208216
JavaScript libraries
css3-mediaqueries-js, 65
CSS3PIE, 6667
Modernizr, 67
respond.js, 65
Selectivizr, 67
Jehl, Scott, 65
K
kerning text, 101
King Arthur example, adding fonts to,
7577
Krug, Steve, 8
L
language CSS3 selector, 24
Lauke, Patrick, 62
Lawson, Bruce
HTML5 semantics, 53
HTML5 video player, 50
IE conditional comments, 69
layout modules. See also CSS
Multi-column layout module;
Flexbox; grid structure
CSS Exclusions and Shapes, 242,
277279
CSS Flexible box, 242
CSS GCPM (Generate Content for
Paged Media), 280
CSS Grids, 242
CSS Multi-column, 242
CSS Regions Level 3, 275277
GCPM, 243
Regions, 242
layout techniques
containers, 292293
max-width, 295296
responsive media layouts,
293296
layout width, setting upper bound
on, 296
letters in elements, selecting, 26
ligatures
dealing with, 9596
discretionary, 98
linear gradients
color stops, 121122
negative unit values, 122
repeating, 123
RGBA colors, 122
syntax, 123
M
Makeev, Vadim, 50
Manian, Divya, 11
Marin, Lucian, 235
<mark> element, 59
matrix 2D transform, 160
matrix3D transform, 165
Media Blitz site, 292, 297, 299, 306307
media layouts, responsive, 293296
media queries
applying, 299301, 303304
applying styles, 297298
content breakpoints, 302
device breakpoints, 302
Mobile First technique, 306
not keyword, 298
orientation-based, 302
polylls, 307
spec, 297
table-related properties, 305
testing features, 298299
using, 302
viewport meta tag, 312315
width-based, 302
menu-move animation, running, 193
<meta name=viewport>, 312315
mime-types, described, 43
Miro Video Converter, 49
mobile browsers. See also browser
support
browser width, 311
<meta name=viewport>, 312315
optimizing content for, 311312
rendering sites, 311312
width/height media queries, 312
Mobile Chrome
animations, 189
CSS3 Color Units, 16
layout features, 243
rem units, 20
responsive design features, 291
transforms, 152
transitions, 179
N
<nav> element, 55
Neal, Jonathan, 46
negation CSS3 selector, 24
negation pseudo-class, 28
normalize.css, using, 63
numerals
fractions, 99
ordinal, 99
tabular, 99
O
opacity, browser support for CSS3
Color Units, 16, 18
open standards, 6
OpenType fonts
numbers, 9899
support for, 74
Opera
animations, 189
bling boxes, 109
CSS3 Color Units, 16
font formats, 74
layout features, 243
rem units, 20
text features, 87, 94
transforms, 152
transitions, 179
Opera Mini
animations, 189
bling boxes, 109
CSS3 Color Units, 16
disadvantages, 285
features, 285
layout features, 243
OBML (Opera Binary Markup
Language) page, 285
rem units, 20
responsive design features, 291
simulator, 286
text features, 87, 94
transforms, 152
transitions, 179
Opera Mobile
animations, 189
bling boxes, 109
CSS3 Color Units, 16
Emulator, 287
font formats, 74
layout features, 243
rem units, 20
responsive design features, 291
text features, 87, 94
transforms, 152
transitions, 179
ordinal numerals, declaring, 99
P
Peculiar icon set, using, 235238
perspective 3D transforms, 165170
petite caps, using, 100
philosophy of web design, 69
polylls, using with media
queries, 307
prexed properties, 15
progressive enhancement, 89
pseudo-classes, 2831
pseudo-elements, 26, 3233
Python, Monty, 72
R
radial gradients
circle closest-corner, 128
circle closest-side, 127
circle farthest-corner, 129
INDEX
325
2D transform, 155156
3D transforms, 162
rotate3D transform, 163164
rounded corners, 110114
S
Safari
animations, 189
bling boxes, 109
CSS3 Color Units, 16
font formats, 74
layout features, 243
rem units, 20
responsive design features, 291
text features, 87, 94
transforms, 152
transitions, 179
scale 2D transforms, 157158
326
INDEX
T
tables, applying, 305
tabular numerals, declaring, 99
Tan, Jon, 81
target CSS3 selector, 24
:target pseudo-class, 2829
template. See also HTML5
browser support for, 4446
building, 4146
character set, 4243
document outline, 4142
HTML5 DOCTYPE, 41
language, 4142
mime-types, 43
XHTML5 and coding styles, 43
text. See also fonts; typography
aligning, 92
capitalizing, 100
controlling hyphenation, 9293
justifying, 92
ligatures, 9596
sizing using rems, 1921
using word-wrap with, 91
text eects, browser support for, 87
text overow, controlling, 9091
text rendering, optimizing, 9596
text-shadow property, 8890
U
UI element pseudo-classes CSS3
selector, 2324
universal CSS3 selector, 22
usability, prioritizing, 8
V
validating HTML5, 47
vendor prexes, 1416
video
muting, 142
responsive, 310
video formats, converting between, 49
<video> element, 4850
control buttons, A-4A-5
controls attribute, 49
height attribute, 49
media styling, A-10A-11
poster attribute, 49
resources, A-11
<source> attributes, 49
SVG and <canvas>, A-10A-11
using in banner ad, 142
width attribute, 49
wiring buttons with JavaScript,
A-5A-9
@viewport rule spec, accessing, 314
W
W3C
Current Work page, 12
WOFF standard, 74
web browsers. See browser support
web design philosophy, 69
web fonts. See also fonts; text;
typography
added bandwidth, 80
creating text characters, 232
FOUT (ash of unstyled text), 7884
HTML5 data- attribute, 233
as icons, 231234
problems, 7884
storing text characters, 233
using, 73
Windows rendering problems,
8182
webfont loader, 7879
X
X, Y, and Z axes, 154
XHTML5 and coding styles, 43
Z
zebra stripes, creating, 25, 30
zooming feature, including, 314
INDEX
327
SIGN UP TODAY
peachpit.com /creativeedge
9
STYLING HTML5
MEDIA AND FORMS
Some HTML5 features not only provide new capabilities to allow you to
create richer, better functionality more easily and natively,
but they also bring with them new visual controls for your
users to interact with. These include <video> and <audio>, as
well as some new HTML5 form features. However, they present a
host of styling problems: As with many older, less-nascent HTML
features, the specs dont dictate how they should be styled, so
browsers have dierent default styling for such elements.
Its a pain to style such elements across browsers consistently,
especially if you also need to consider styling fallbacks that might
be written in Flash. The information in this chapter will ease your
pain by providing you with techniques for cross-browser styling
consistency.
A-3
CUSTOMIZING <VIDEO>
AND <AUDIO>
The HTML5 <video> and <audio> elements provide a great way to embed media
onto your page without having to use plug-in content like Flash; although, for
older browser support youll want to consider providing a Flash movie fallback.
One of the main pain points of the HTML5 media elements is that they look
dierent across browsers, as illustrated in Figure 9.1.
To remedy this, you can remove the native controls provided by the controls
attribute, create your own simple buttons using HTML and CSS, and then use the
HTMLMediaElement JavaScript API to wire those buttons to the right functions.
Youll learn how to do this in the next few sections.
A-4
CHAPTER 9
A-5
Next, youll remove the default video controls (my HTML examples include
the controls attribute so the native browsers controls are used if JavaScript isnt
available), and make the custom controls visible:
seekbar.value = 0;
media.removeAttribute(controls);
controls.style.visibility = visible;
Here, listeners are added to the buttons to make the relevant actions happen
when they are pressed. Another listener is added to the <video>/<audio> so that
you can stop it when the end of the media is reached, and yet another is added to
set the timer value when the time of the media updates.
Now on to the functions! The rst function, playPauseMedia(), controls what
happens when the rst button is clicked:
function playPauseMedia() {
if(media.className=== || media.className===paused) {
media.setAttribute(class,playing);
play.setAttribute(data-icon,u);
A-6
CHAPTER 9
media.play();
} else {
media.setAttribute(class,paused);
play.setAttribute(data-icon,P);
media.pause();
}
}
Here Ive used a simple if ... else statement to specify that if the class set
on the media element is blank or paused, it is paused or stopped; otherwise, it is
playing. If it is paused or stopped, you change the class on the media element to
playing, change the data-icon attribute value on the Play button to u (a pause
icon), and play the video using the play() method of the media API. If the media
is playing, you change the medias class attribute value back to paused, change
the data-icon attribute value on the Play button to P (a play icon), and pause
the video using the media APIs pause() method.
Next, you add the stopMedia() function, which controls what happens when
the Stop button is pressed:
function stopMedia() {
media.pause();
media.currentTime = 0;
media.setAttribute(class,);
play.setAttribute(data-icon,P);
}
This is much simpler, because it has only one state rather than two states that
are toggled in between. There is no stop() method in the media API, so instead
you use the pause() method to pause the media and put it back to the start using
currentTime = 0. You also make sure that the Play/Pause button is reset by putting those class and data-icon attributes you were playing with earlier back to
their default states.
A-7
Next, you add the setTime() function, which updates the time counter:
function setTime() {
var minutes = Math.floor(media.currentTime / 60);
var seconds = Math.floor(media.currentTime - minutes * 60);
var minuteValue;
var secondValue;
if (minutes<10) {
minuteValue = 0 + minutes;
} else {
minuteValue = minutes;
}
if (seconds<10) {
secondValue = 0 + seconds;
} else {
secondValue = seconds;
}
mediaTime = minuteValue + : + secondValue;
timer.innerHTML = mediaTime;
}
This code isnt as bad as it looks. The rst part uses a bit of math to work out
what the minute and second values are from the raw seconds returned by the
currentTime method of the API. The second part checks whether the minute
and second values are less than 10 or not. If so, a 0 is appended to the value, for
example, 09. If not, the 0 is not appended, so the values will appear as, for example,
10, not 010.
A-8
CHAPTER 9
The nal two lines build the minute and second value into a timer readout,
for example, 09:43, and then that value is squirted into the timer <div> using
innerHTML.
The last set of functions is for the rewind/fast forward functionality:
function mediaBackward() {
media.pause();
interval = setInterval(media.currentTime =
p media.currentTime - 3, 200);
}
function mediaForward() {
media.pause();
interval = setInterval(media.currentTime =
p media.currentTime + 3, 200);
}
function normalPlay() {
clearInterval(interval);
media.play();
}
The rst two functions use setInterval() to add or subtract three to/from
the current time every fth of a second while the mouse button is held down. I
also pause the video while this is happening so that it doesnt mess up the process.
There is a setPlaybackRate() method, but I had to fake it like this as that method
doesnt work in Opera yet.
When the mouse button is not longer pressed, the normalPlay() removes the
interval, and just starts the video playing as normal.
A-9
and then only reveal them in their full glory when you do hover over the media:
#player:hover #controls, player:focus #controls {
opacity: 1;
}
You could get a lot crazier with transforms and transitions if you wanted to, but
Id advise against it. Animating video is so processor intensive that its best to avoid it.
Another tip concerns styling Flash fallbacks. You pretty much cant. And even
if you want to do something simple like making sure a <video> is centered in its
parent column, you need to include a wrapper <div> around the video, and then
center that. For example:
#wrapper {
margin: 0 auto;
}
A-10
CHAPTER 9
Another big bugbear is getting consistent styling on the HTML5 media and the
Flash fallback. You need to think about the styling of the HTML and the Flash
movie separately.
NOTE: If you really dont fancy tackling all the JavaScript and styling
manually, you could use one of the many third-party video players
available. Many of them are written to take a lot of the browsers
inconsistencies and HTML5/Flash standoffs out of your hands. I recommend checking out http://videojs.com and http://sublimevideo.net.
OTHER RESOURCES
As you might have guessed, there is a lot more I could say about HTML5 media; in
fact, theres enough to ll an entire book. And indeed one of this books sister books
lls this role. For much more about HTML5 media, check out HTML5 Multimedia:
Develop and Design (Peachpit, 2011) by Ian Devlin.
There are also numerous other good resources available on the Internet. Here
are just a few:
A-11
FORM IMPROVEMENTS
CSS3 and associated, modern web design goodies oer specic features for making
HTML form styling easier. Simply put, HTML forms are a total pain to get looking
good, and looking the same across browsers. The reason is that they are rendered
so dierently by default across browsersand that is before you even start using
the new HTML5 form controls, which as mentioned in Chapter 2 are not supported
that well across browsers yet.
IMPROVING CONSISTENCY
A great way to instantly level the playing eld and improve consistency across
browsers is to apply that rather useful normalize.css to your forms (youve seen this
used throughout this book). Normalize renders many elements more consistently
across browsers, including form controls. If you want to see the eect it has, look
at the demo page at http://necolas.github.com/normalize.css/demo.html. Scroll
down to the Forms section. This may not be exactly what you want straight away,
but it is a great base to build upon.
Keep in mind that form elements need to have a name attribute to be submitted as part of a form and to be validated. The pseudo-classes available to use with
CSS are as follows:
A-12
CHAPTER 9
:required and :optional. These pseudo-classes let you style controls based
on whether or not they have a required attribute.
Here Ive made the optional input look a bit fainter and less important than the
required one, and also used generated content to add an asterisk to the required
label.
Next, Ive styled the valid and invalid input examples as follows:
@keyframes box-shake {
from { transform: translateX(2px); }
to { transform: translateX(-2px); }
}
FORM IMPROVEMENTS
A-13
#email:invalid {
border: 2px solid rgb(255,100,100);
box-shadow: inset 2px 2px 3px rgba(0,0,0,0.7);
background: linear-gradient(top,#fff,#eee);
animation: box-shake 0.1s infinite;
}
#email:valid {
border: 1px solid black;
box-shadow: inset 2px 2px 3px rgba(0,0,0,0.7);
background: linear-gradient(top,#fff,#eee);
}
Ive made invalid inputs look as deviant as possible with a big red border and
a shaky animation! Try entering an email address into one of the email elds to
see the instant change in style when the form data becomes valid. Then Ive used
a number input with min and max attributes set (allowing data in the range 1100):
@keyframes box-pulse {
from { transform: scale(1.1); }
to { transform: scale(0.9); }
}
#number:out-of-range {
border: 2px solid rgb(255,100,100);
box-shadow: inset 2px 2px 3px rgba(0,0,0,0.7);
background: linear-gradient(top,#fff,#eee);
animation: box-pulse 0.8s infinite linear alternate;
transform-origin: center;
}
A-14
CHAPTER 9
#number:in-range {
border: 1px solid black;
box-shadow: inset 2px 2px 3px rgba(0,0,0,0.7);
background: linear-gradient(top,#fff,#eee);
}
Try focusing the input and entering a value of 101 or more to see what
happens!
NOTE: The pseudo-selectors in the file css3-form-selectors.
html will work across all modern browsers with the exception
that in-range and out-of-range dont work in Firefox.
WRAPPING UP
In this chapter, you learned a range of styling tips and tricks to help you get the
most out of some of the new HTML5 featuresnamely <audio> and <video>. You
also learned some neat little HTML form goodies.
WRAPPING UP
A-15