Author Archive

Behind The Scenes Of Tourism New Zealand (Case Study)


  

In 2011 we saw the rise in popularity of two relatively new trends: responsive Web design and the use of HTML’s canvas. While some websites had experimented with both, in the last 12 months we’ve seen these trends move from the fringes firmly into the mainstream.

Responsive Web design is more a concept than a technology — an ideal that many new websites aspire to. Canvas, on the other hand, is an HTML5-based technology that opens the door to a new wave of interactivity. In this article, we’ll look at a website that embraces both of these elements, one that has been nominated for a Technical Achievement award at SxSW Interactive 2012: Tourism New Zealand.

I spoke with the creative and technical teams at the New Zealand-based firms Shift and Assembly about the technology behind Tourism New Zealand’s home page, how it was made and how they balanced the breakthrough effect with bandwidth.

After we learn how Tourism New Zealand was built, we’ll look at the basics of putting together your own animated HTML5 canvas background.

The Inspiration

Tourism New Zealand has a history of strong media and advertising campaigns, particularly through TV commercials, and its destination marketing website has long featured these videos.

So, when a redesign of the website was planned without an accompanying TV commercial, the team at Shift had a new challenge: to showcase the landscape and breadth of activities in New Zealand to an audience that has come to interact with a website, not to watch a video.

Shift was inspired by, among other things, Nike’s Better World website (which Smashing Magazine has covered). But whereas that website used HTML5 animation to create an effect of parallax scrolling, Shift proposed a camera view that moves through the real world.

Shift’s first idea was to use video as a background, with the camera descending through some of New Zealand’s most exciting locations. The problem was bandwidth: at 25 frames per second, Shift would need to deliver thousands of full-screen frames. This was an impossible goal, so instead the team set a target of around 200 frames for the entire website. But 200 frames for the amount of footage they wanted worked out to about three frames per second, which doesn’t look particularly good.

At this point, they nearly abandoned the idea.

By chance, though, a solution was found. Scrubbing through a QuickTime video, Shift’s creative director, Mark Zeman, noticed that being able to control the frame rate as you move the play head gives the illusion of a smooth experience. He suspected that if the browser’s scroll bar could be used to scrub the footage, it would feel similarly smooth. And if the camera shot photographs as it moved through each scene, it would create the illusion that the user was practically controlling the camera as it descended through New Zealand.

The first prototype was made with a few images and some JavaScript, just to prove that the browser could handle this type of manipulation. Freelance front-end developer Jeff Nusz was then tasked with turning this proof of concept into a working website. The brief was simple: no loading bar, and the first frame must load almost instantly. Furthermore, the website had to be usable even when the user doesn’t wait for all of the images to download.

On Location

With the prototype built and approved by Tourism New Zealand, it was time to load up the trucks with scaffolding and start shooting.

Shift worked with directors Damon Duncan and Matt von Trott of Assembly throughout development of the project, which enabled them to build the large motion-control rigs that were required for the shoot.

A 15-meter-high motion-control rig was built, with a vertical dolly track that housed a Canon 5D DSLR. The rig was set up at each location, and the camera travelled 12 meters down it, taking anywhere between 750 and 950 stills, a process that lasted at least two hours each time (and six hours at Milford Sound, the first location on the website), because the camera moved around 15 millimeters every 10 seconds.


Milford Sound, New Zealand

Each location took three days to shoot. The first day was spent building the tower and putting together the motion-control rig. The second day was usually spent rehearsing the scene, and the third would be for the actual shoot, which included multiple passes of the scene. Indeed, the scene for Waiheke Island is a combination of two takes.


Time-lapse sequences from all four shoots (watch on Vimeo)

Front-end developer Jeff Nusz had built a suite of tools to help the crew plan the photography. The directors also showed the original prototype to the cast and crew, which helped to demonstrate what they were filming and how the time-lapse footage would work.

Post-Production

There were only five days between the final day of shooting and the launch of the website. Most of the code had been written and ported to JavaScript using prototype images, and so it was now a matter of editing the hundreds of photos from each location down to 200 hand-optimized 1280 × 720-pixel frames.

The team spent time testing the website in each browser, noticing different memory quirks in Chrome and Firefox, and it worked on optimizing the website’s performance. Because many of New Zealand’s tourists come from China, the time was also spent making sure the website worked even in IE 6. To better understand the toll of such a heavy home page, Shift used WebPagetest to test it from various parts of the globe.

From 25 MB To 300 KB

Although the entire website weighs in at 25 MB, it enables a usable experience after the first 300 KB of data and images have loaded.

On the initial loading of the page, a 40 KB image is loaded that contains all 200 frames at a very low resolution. This means that as soon as the initial frame of Milford Sound has loaded, you can scrub through the entire website and get some approximation of the full experience. Then, when you stop scrubbing, the website loads the frame you’re on and starts loading the frames before and after it. Moreover, as you scroll the page, all downloading activity stop to ensure the smoothest possible scrolling experience. When you stop scrolling, all downloading resume.

Interestingly, Jeff’s background is mainly in working with Flash, so the initial website was built in Flash and then ported to HTML5 at the last minute. Jeff says that the similarities between ActionScript and JavaScript made this a relatively pain-free process:

ActionScript 3 is a lot like JavaScript. I did a lot of the work in Flash, and I wanted to see how well it would translate, and it was pretty much cut-and-paste for the most part. I just had to structure things in a similar way and make a few semantic changes. Ninety percent of the code ported as it was, which was great.

One of the team’s early breakthroughs was in figuring out how to split up the website’s elements. You can see in the sketch below how a website normally works: you have a long page and, conceptually speaking, the browser’s viewport moves up and down the page (i.e. the latter moving across the former).

In this next sketch, the page itself is a giant empty GIF that you scroll up and down; but the website detects every time you scroll, calculates your position and then translates that to the frame you should be on. The height of the window also changes depending on how big your browser’s viewport is, because if the page is huge and your viewport is small, then the scroll bar would be tiny; Shift wanted to keep the size of the scroll bar consistent, regardless of the browser’s size.

As Jeff notes, “Although it’s not exact, the goal was that one click of your mouse-wheel would be one frame�:

The tag layer and the UI layer is just HTML and CSS, but the background is either an HTML5 canvas that we draw to or it’s Flash. There’s about a 20-millisecond lag between the frames moving and the background changing in Flash, so the canvas version became the primary method used for browsers that support it.

The tags do not scroll in the conventional sense, but for each frame, they are assigned specific x and y coordinates based on the frame. This allows tags to be “gluedâ€� to background elements — a tree, mountain top, etc. — and these coordinates would be recalculated on the fly if the browser window was resized.

To create this effect, the team used Adobe After Effects to keyframe each tag and output the coordinates. Jeff built a PHP script into which the team could copy and paste the After Effects keyframe data, whereupon the script would generate JavaScript that the website could use. Jeff then tweaked the tags in JavaScript to make sure they scrolled as expected.

Sprite Sheets

To create the illusion that the page loads quickly, Jeff came up with the idea of using sprite sheets. As he puts it, “The sprite sheets were the breakthrough that allowed us to make the website usable so quickly after the page loads�.

The first frame (of the background image) is 90 KB. So, together with the first low-resolution sprite sheet (which is 30 KB), these images initially weigh only 130 KB. Once the page has loaded all of the content, it loads a higher-resolution sprite sheet, and then another, and then it loads in the full-resolution images one by one. Rather than loading these large images in sequence, it loads them based on your scroll position within the document.

You can check that the sprite sheets load before the full-resolution images by turning the Webkit Inspector on and watching the “Network� activity after the page has started to render.

Using Inline JavaScript

I asked the team at Shift why so much inline JavaScript was in the head of the document. Best practice would suggest it should be moved to a separate file. However, something more is going on here.

Shift’s solution architect, Glenn Wright, has been working on the website for the last six years. He explains:

The inline JavaScript is there to define the configuration for each page. We can cache each page’s configuration in JavaScript, then all the external libraries that the page loads utilize that data. It gives us an easy way to configure the responsive grid and all of the interactions that the page will have to use.

Testing Mode

A testing mode on the website lets you see some of this loading process in action. Clear your browser’s cache, load Tourism New Zealand’s home page, and then hit the tilde (~) key five times to enable testing mode. You won’t see any change immediately, but once in this mode you can use the following keyboard commands:

  • 1
    Turn on the visualizer for “frames loaded�
  • 3
    Toggle tags on and off
  • 0
    Toggle the high-resolution image on and off
  • -
    Go to the previous low-resolution sprite
  • +
    Go to the next high-resolution sprite

Building Your Own Canvas Background Animation

While websites like Tourism New Zealand take months to design and build, creating your own animated canvas background is relatively straightforward. All it takes is a little JavaScript, a pinch of HTML5 and an enormous amount of imagination to dream up a worthwhile use.

Indeed, a word of caution is in order. We all know that with great power comes great responsibility, and just because we can load 50 high-resolution frames and animate them as the user scrolls the window doesn’t mean we should. As mentioned earlier, websites that use this technique are both lauded and criticized. Make sure that you are enriching the user experience rather than needlessly slowing it down.

First, we need to do a couple of things. Let’s grab some video (a time-lapse video works best for this), and then create our 50 frames. You can create as many frames as you like, but we’ll stick with 50 because this is how many Tourism New Zealand uses for each scene.

Next, let’s grab some royalty-free time-lapse footage from Artbeats and import it into iMovie, where you can export individual frames.

Choose Share → Export Using QuickTime, and in the pop-up dialog box select “Movie to Image Sequence.â€�

We export the images as JPEGs, which leaves us with hundreds of images. So, we have to do two things:

  1. Batch process the images in Photoshop to the required size (here, we went with 480 × 270 pixels to maintain the aspect ratio).
  2. Edit the number of images down to 50. Shift was painstaking in doing this, retouching and editing thousands of images down to just 200. To keep things easy for this tutorial, let’s just delete three photos out of every four.

You should now have 50 photos that, when played in sequence, make for a somewhat choppy time-lapse video.

On to the next couple of steps. First, we’ll figure out how to load the images in the browser and control them with the scroll bar. Secondly, we’ll create our own sprite sheet and use that instead. Open your code editor of choice, and create a new JavaScript file. Or why not head over to GitHub and download the project to play around with?

You’ll also need an HTML file with a canvas element in it, which is as simple as this:

<canvas id="canvas"></canvas>

Hopefully, the comments in the code sufficiently explain what’s going on, but here’s a breakdown anyway.

First, we set up the canvas element and use some basic maths to set start and end points:

// Create our timeLapseVideo object and cache the window object
timeLapseVideo = new Image();
$window = $(window);

// Define the timeLapseVideo element
timeLapseVideo.onload = function(){
  videoContainer.width = 960;
  videoContainer.height = 540;
  videoContext.drawImage(timeLapseVideo, 0, 0, 960, 540);
}

// Load the first frame
timeLapseVideo.src = 'images/TimeLapse001.jpg';

// Calculate how far to scroll before changing a frame
var scrollDistance = $window.height() - $window.scrollTop(),
    totalHeight = $(document).height() - scrollDistance;
    frameDiff = totalHeight / (numberOfFrames - 1);

Then, when the window scrolls, we work out which frame needs to appear on screen:

// Which frame do we need to show?
frameString = (Math.round($window.scrollTop()/frameDiff) + 1).toString();

// Change the image in the canvas
timeLapseVideo.src = 'images/TimeLapse' + frameString + '.jpg';

Make sure to go through the full source code to see it in action. Be careful, because there is no check to determine whether an image has already loaded; you could end up hitting your server with hundreds of requests per page. So, like Tourism New Zealand, you need to build in a check to see whether an image has been cached.

Creating And Using A Sprite Sheet

We can also create our own sprite sheet with our image to emulate more of Tourism New Zealand’s behavior. Some apps and websites are available to help you do the job (see the “Related Links� section at the end), but it’s probably easier to run a simple script that pastes all of the images onto a canvas and then take a plain screenshot of that. The code for this script is in the GitHub repository in case you want to take a look.

There are two main differences with this technique. First, we load only one image onto the canvas, which is the sprite sheet:

timeLapseVideo.src = 'images/spritesheet.jpg';

When the window scrolls, we then draw part of this sprite to the canvas:

videoContext.drawImage(timeLapseVideo, x, y, 80, 45, 0, 0, 960, 540);

In the line above, x and y are the starting coordinates of the sprite, which in turn are dictated by the frame. We’re using a simple loop to iterate through the sprite to find the right coordinates, but you could set up an array of values to look up. These tiny frames are 80 × 45 pixels, and they are drawn from 0,0 to 960 × 540 pixels. CSS then stretches this canvas to fit the entire window.

You can improve this script a great deal by, for example, preloading images when the user isn’t scrolling (some links are below to point you in the right direction). If you make improvements, please do share your work in the comments below.

Creativity In Design And Development

Distilling 18 months of hard work into one article like this is an impossible task. Shift had the time and budget to fly around New Zealand and take thousands of beautiful photographs. This is not an option for the average Web designer!

However, what is perhaps most striking about Tourism New Zealand is the imagination in its concept and execution. By taking the leap from virtual to physical world (and back again!), the scroll bar has become a conduit by which the user can control their experience of New Zealand — if only for 200 frames.

Jeff’s ingenious loading techniques and the use of sprite sheets also kept away the loading bar that is so familiar with websites like this. On an average broadband connection, the experience is effortless and fun.

Perhaps the biggest lesson to be learned here is this. Despite its many bells and whistles, Tourism New Zealand encourages the user to discover the website in much the same way they would discover the country.

Technology supports the great design, not the other way around. If we could all exercise this level of creativity, imagination and user engagement, then we, too, would create amazing websites that shape the future of Web design.

Related Links

I must extend my very special thanks to Jeff (@jeffnusz), Glenn, Che and, in particular, Mark (@markzeman), who were patient with my intermittent Skype connection and who were so transparent in offering their thoughts and many of the images and resources featured in this article.

(al)


© Richard Shepherd for Smashing Magazine, 2012.


CSS3 Flexible Box Layout Explained





 



 


The flexible box layout module — or “flexbox,� to use its popular nickname — is an interesting part of the W3C Working Draft. The flexbox specification is still a draft and subject to change, so keep your eyes on the W3C, but it is part of a new arsenal of properties that will revolutionize how we lay out pages. At least it will be when cross-browser support catches up.

In the meantime, we can experiment with flexbox and even use it on production websites where fallbacks will still render the page correctly. It may be a little while until we consider it as mainstream as, say, border-radius, but our job is to investigate new technologies and use them where possible. That said, when it comes to something as fundamental as page layout, we need to tread carefully.

The Display Property

So what is flexbox, and why was it created? First, let’s look at how we currently lay out pages and some of the problems with that model.

Until last year, most of us were using tables to lay out our pages. Okay, maybe not last year! But I suspect that many of you reading this have been guilty of relying on tables at some point in your career. At the same time, it actually made a lot of sense. And let’s face it: it worked… to a point. However, we all then faced the reality that tables were semantically dubious and incredibly inflexible. And through the haze of this mark-up hangover, we caught a glimpse of the future: the CSS box model. Hurray!

The CSS box model allowed us to tell the browser how to display a piece of content, and in particular how to display it as a box. We floated left and right, we tried to understand what inline-block meant, and we read countless articles about clearfix, before just copying and pasting the clearfix hack-du-jour into our CSS.

For those of us testing our websites back to IE6, we had to grapple with hasLayout and triggering it with the following or some similar fix:

* html #element {
height: 1%;
}

The box model worked, and in most cases it worked well. But as the Web entered its teenage years, it demanded more complex ways of laying out content and — thanks to a certain Mr. Ethan Marcotte — of responding to the size of the browser and/or device.

Percentage + Padding + Border = Trouble

Here’s another problem with the current box model: absolute values for padding, margin and border all affect the width of a box. Take the following:

#element {
width: 50%;
border 1px solid #000;
padding: 0 5px;
}

This will not give us a box that is 50% of its parent. It will actually render an element that is 50% of the parent’s width plus 12 pixels (2-pixel border + 10-pixel padding). You could set the padding as a percentage value (although not for input elements in Firefox!), but adding percentage values of widths to the pixel values of borders can cause mathematical problems.

There are two ways to fix this problem. The first is to use the new CSS3 box-sizing property, and setting it to border-box:

#element {
box-sizing: border-box;
width: 50%;
border 1px solid #000;
padding: 0 5px;
}

This new CSS3 panacea effectively tells the browser to render the element at the specified width, including the border width and padding.

The second way to fix this problem is to use flexbox.

Many Problems, Many Solutions

The W3C responded with a suite of answers: the flexible box model, columns, templates, positioned floats and the grid. Adobe added regions to the mix, but they are not yet supported by any browser.

The display property already has no less than a staggering 16 values: inline, block, list-item, inline-block, table, inline-table, table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, table-caption, none and inherit.

And now we can add a 17th: box.

Living In A Box

Let’s take a look at flexbox, which brings with it a brand new value for the display property (box) and no less than 8 new properties. Here’s how the W3C defines the new module:

In this new box model, the children of a box are laid out either horizontally or vertically, and unused space can be assigned to a particular child or distributed among the children by assignment of flex to the children that should expand. Nesting of these boxes (horizontal inside vertical, or vertical inside horizontal) can be used to build layouts in two dimensions.

Sounds exciting! The Working Draft expands on this a little:

Flexbox… lacks many of the more complex text or document-formatting properties that can be used in block layout, such as “float� and “columns,� but in return it gains more simple and powerful tools for aligning its contents in ways that Web apps and complex Web pages often need.

Now this is beginning to sound interesting. The flexbox model picks up where the box model leaves off, and the W3C reveals its motivation by noting that “Web apps and complex Web pages� need a better layout model. Here’s a list of the new flexbox properties:

  • box-orient,
  • box-pack,
  • box-align,
  • box-flex,
  • box-flex-group,
  • box-ordinal-group,
  • box-direction,
  • box-lines.

For the sake of brevity, I will use only the official spec’s properties and values, but do remember to add the vendor prefixes to your work. (See the section on “Vendor Prefixes and Cross-Browser Support� below.)

You might also want to check out Prefixr from Jeffrey Way, which can help generate some of the CSS for you. However, I found that it incorrectly generated the display: box property, so check all of its code.

Everything Will Change

If you take the time to read or even browse the latest Working Draft (from 22 March 2011), you’ll notice a lot of red ink, and with good reason. This spec has issues and is still changing; we are in unchartered waters.

It’s worth noting that the syntax used in this article, and by all current browsers, is already out of date. The Working Draft has undergone changes to much of the syntax used in the flexbox model. For example:

display: box;

This will become:

display: flexbox;

Other changes include some properties being split (box-flex will become flex-grow and flex-shrink), while others will be combined (box-orient and box-direction will become flex-direction). Indeed, anything that starts box- will be changed to flex-. So, keep your eyes on the spec and on browser implementations. (CanIUse helps, but it doesn’t cover all of the properties.)

PaRappa the Wrapper

Using flexbox often requires an extra div or two, because the parent of any flexbox element needs to have display set to box. Before, you could get away with the following:

<div style="float: left; width: 250px;"> Content here </div>
<div style="float: right; width: 250px;"> Content here </div>

Now with flexbox, you’ll need:

<div style="display: box">
  <div style="width: 250px"> Content here </div>
  <div style="width: 250px"> Content here </div>
</div>

Many of you have already turned away, insulted by this extra mark-up that is purely for presentation. That’s understandable. But here’s the thing: once you master the CSS, this extra containing div becomes a small price to pay. Indeed, you’ll often already have a containing element (not necessarily a div) to add display: box to, so there won’t be a trade-off at all.

On a broader note, sometimes you need presentational mark-up. It’s just the way it goes. I’ve found that, particularly when working on cross-browser support for a page, I have to add presentational mark-up for browsers such as IE6. I’m not saying to contract “div-itis,� but because we all use HTML5 elements in our mark-up, we find that sections often need div containers. That’s fine, as long as it’s kept to a minimum.

With this in mind, let’s get busy with some code. I’ve put together a demo page, and you can download all of the source files.

screenshot

Over the next few paragraphs, we’ll use the new flexbox model to create a basic home page for a blog. You might want to launch a latest-generation browser, though, because we’re now coding at the cutting edge. And it’s an exciting place to be.

box-flex

Let’s start with the basics: box-flex. Without box-flex, very little can be achieved. Simply put, it tells the browser how to resize an element when the element is too big or small for its parent.

Consider the following classic problem. You have a container with three children that you want to position side by side. In other words, you float them left. If the total width of these boxes is wider than that of the parent — perhaps because of padding, margin or a border — then you need to either specify exact widths in pixels (which is not flexible) or work in percentages (and the sometimes mind-bending calculations that come with them!).

Here’s the problem we have on our Fruit Blog, with three 320-pixel-wide asides (plus padding and margin) inside a 920-pixel-wide container:

screenshot

As you can see, the content is wider than the parent. However, if we set set the parent to display: box and each of these asides to box-flex: 1, then the browser takes care of the math and renders the following:

screenshot

So, what exactly has happened here?

The box-flex property refers to how the browser will treat the width of the box — or, more specifically, the unused space (even if that space is negative — i.e. even if the rendered boxes are too big for the container) — after the box has rendered. The value (1 in our example) is the ratio. So, with each aside set to a ratio of 1, each box is scaled in exactly the same way.

In the first instance, each aside was 320 pixels + 20 pixels of padding on the left and right. This gave us a total width of 360 pixels; and for three asides, the width was 1080 pixels. This is 160 pixels wider than the parent container.

Telling the browser that each box is flexible (with box-flex) will make it shrink the width of each box — i.e. it will not change the padding. This calculation is a fairly easy one:

160 pixels ÷ 3 asides = 53.333 pixels to be taken off each aside.

320 pixels − 53.333 = 266.667 pixels

And, if we look in Chrome Developer tools, we will see this is exactly how wide the box now is (rounded up to the nearest decimal):

screenshot

The same would be true if each aside had a width of 100 pixels. The browser would expand each element until it filled the unused space, which again would result in each aside having a width of 266.667 pixels.

This is invaluable for flexible layouts, Because it means that your padding, margin and border values will always be honored; the browser will simply change the width of the elements until they fit the parent. If the parent changes in size, so will the flexible boxes within it.

Of course, you can set box-flex to a different number on each element, thus creating different ratios. Let’s say you have three elements side by side, each 100 pixels wide, with 20 pixels padding, inside a 920-pixel container. It looks something like this:

screenshot

Now, let’s set the box-flex ratios:

.box1 { box-flex: 2; }
.box2 { box-flex: 1; }
.box3 { box-flex: 1; }

Here’s what it looks like:

screenshot

What just happened?!

Well, each aside started off as 140-pixels wide (100 pixels + 40 pixels padding), or 420 pixels in total. This means that 500 pixels were left to fill once we’d made them flexible boxes.

However, rather than split the 500 pixels three ways, we told the browser to assign the first aside with a box-flex of 2. This would grow it by 2 pixels for every 1 pixel that the other two boxes grow, until the parent is full.

Perhaps the best way to think of this is that our ratio is 2:1:1. So, the first element will take up 2/4 of the unused space, while the other two elements will take up 1/4 of the unused space (2/4 + 1/4 + 1/4 = 1).

2/4 of 500 pixels is 250, and 1/4 is 125 pixels. The final widths, therefore, end up as:

.box1 = 350px (100px + 250px) + 40px padding
.box2 = 225px (100px + 125px) + 40px padding
.box3 = 225px (100px + 125px) + 40px padding

Add all of these values up and you reach the magic number of 920 pixels, the width of our parent.

An important distinction to make is that the ratio refers to how the additional pixels (or unused space) are calculated, not the widths of the boxes themselves. This is why the widths are 350:225:225 pixels, and not 460:230:230 pixels.

The wonderful thing about the flexbox model is that you don’t have to remember — or even particularly understand — much of the math. While the Working Draft goes into detail on the calculation and distribution of free space, you can work safe in the knowledge that the browser will take care of this for you.

Animating Flexible Boxes

A simple and elegant effect is already at your fingertips. By making the li elements in a navigation bar flexible, and specifying their width on :hover, you can create a nice effect whereby the highlighted li element expands and all the other elements shrink. Here’s the CSS for that:

nav ul {
display: box;
width: 880px;
}

nav ul li {
padding: 2px 5px;
box-flex: 1;
-webkit-transition: width 0.5s ease-out;
min-width: 100px;
}

nav ul li:hover {
width: 200px;
}

screenshot

You’ll spot a min-width on the li element, which is used to fix a display bug in Chrome.

Equal-Height Columns: The Happy Accident!

As we’ll see, all flexbox elements inherit a default value of box-align: stretch. This means they will all stretch to fill their container.

For example, two flexbox columns in a parent with display: box will always be the same height. This has been the subject of CSS and JavaScript hacks for years now.

There are a number of practical implementations of this fortunate outcome, not the least of which is that sidebars can be made the same height as the main content. Now, a border-left on a right-hand sidebar will stretch the full length of the content. Happy days!

box-orient and box-direction

The box-orient property defines how boxes align within their parent. The default state is horizontal or, more specifically, inline-axis, which is horizontal and left-to-right in most Western cultures. Likewise, vertical is the same as block-axis. This will make sense if you think about how the browser lays out inline and block elements.

You can change the box-orient value to vertical to make boxes stack on top of each other. This is what we’ll do with the featured articles on our fruit blog.

Here is what our articles look like with box-orient set to its default setting:

screenshot

Ouch! As you can see, the articles are stacking next to each other and so run off the side of the page. It also means that they sit on top of the sidebar. But by quickly setting the parent div to box-orient: vertical, the result is instant:

screenshot

A related property is box-direction, which specifies the direction in which the boxes are displayed. The default value is normal, which means the boxes will display as they appear in the code. But if you change this value to reverse, it will reverse the order, and so the last element in the code will appear first, and the first last.

While box-orient and box-direction are essential parts of the model, they will not likely appear in the final specification, because they are being merged into the flex-direction property, which will take the following values: lr, rl, tb, bt, inline, inline-reverse, block and block-reverse. Most of these are self-explanatory, but as yet they don’t work in any browser.

box-ordinal-group

Control over the order in which boxes are displayed does not stop at normal and reverse. You can specify the exact order in which each box is placed.

The value of box-ordinal-group is set as a positive integer. The lower the number (1 being the lowest), the higher the layout priority. So, an element with box-ordinal-group: 1 will be rendered before one with box-ordinal-group: 2. If elements share the same box-ordinal-group, then they will be rendered in the order that they appear in the HTML.

Let’s apply this to a classic blog scenario: the sticky post (i.e. content that you want to keep at the top of the page). Now we can tag sticky posts with a box-ordinal-group value of 1 and all other posts with a box-ordinal-group of 2 or lower. It might look something like this:

article {
box-ordinal-group: 2;
}

article.sticky {
box-ordinal-group: 1;
}

So, any article with class="sticky" is moved to the top of the list, without the need for any front-end or back-end jiggering. That’s pretty impressive and incredibly useful.

We’ve used this code in our example to stick a recent blog post to the top of the home page:

screenshot

box-pack and box-align

The box-pack and box-align properties help us position boxes on the page.

The default value for box-align is stretch, and this is what we’ve been using implicitly so far. The stretch value stretches the box to fit the container (together with any other siblings that are flexible boxes), and this is the behavior we’ve seen so far. But we can also set box-align to center and, depending on the box-orient value, the element will be centered either vertically or horizontally.

For example, if a parent inherits the default box-align value of horizontal (inline-axis), then any element with box-align set to center will be centered vertically.

We can use this in our blog example to vertically center the search box in the header. Here’s the mark-up:

<header>
  <form id="search">
    <label for="searchterm">Search</label>
    <input type="search" placeholder="What’s your favourite fruit…" name="searchterm" />
    <button type="submit">Search!</button>
  </form>
</header>

And to vertically center the search box, we need just one line of CSS:

header {
display: box; box-align: center;
}

header #search {
display: box; box-flex: 1;
}

The height of #search has not been set and so depends on the element’s content. But no matter what the height of #search, it will always be vertically centered within the header. No more CSS hacks for you!

screenshot

The other three properties of box-align are start, end and baseline.

When box-orient is set to horizontal (inline-axis), an element with box-align set to start will appear on the left, and one with box-align set to end will appear on the right. Likewise, when box-orient is set to vertical (block-axis), an element with box-align set to start will appear at the top, and one with box-align set to end will move to the bottom. However, box-direction: reverse will flip all of these rules on their head, so be warned!

Finally, we have baseline, which is best explained by the specification:

Align all flexbox items so that their baselines line up, then distribute free space above and below the content. This only has an effect on flexbox items with a horizontal baseline in a horizontal flexbox, or flexbox items with a vertical baseline in a vertical flexbox. Otherwise, alignment for that flexbox item proceeds as if flex-align: auto had been specified.

Another property helps us with alignment: box-pack. This enables us to align elements on the axis that is perpendicular to the axis they are laid out on. So, as in the search-bar example, we have vertically aligned objects whose parent have box-orient set to horizontal.

But what if we want to horizontally center a box that is already horizontally positioned? For this tricky task, we need box-pack.

If you look at the navigation on our fruit blog, you’ll see that it’s only 880 pixels wide, and so it naturally starts at the left of the container.

screenshot

We can reposition this ul by applying box-pack to its parent. If we apply box-pack: center to the navigation element, then the navigation moves nicely to the center of the container.

screenshot

This behaves much like margin: 0 auto. But with the margin trick, you must specify an explicit width for the element. Also, we can do more than just center the navigation with box-pack. There are three other values: start, end and justify. The start and end values do what they do for box-align. But justify is slightly different.

The justify value acts the same as start if there is only one element. But if there is more than one element, then it does the following:

  • It adds no additional space in front of the first element,
  • It adds no additional space after the last element,
  • It divides the remaining space between each element evenly.

box-flex-group and box-lines

The final two properties have limited and/or no support in browsers, but they are worth mentioning for the sake of thoroughness.

Perhaps the least helpful is box-flex-group, which allows you to specify the priority in which boxes are resized. The lower the value (as a positive integer), the higher the priority. But I have yet to see an implementation of this that is either useful or functional. If you know different, please say so in the comments.

On the other hand, box-lines is a bit more practical, if still a little experimental. By default, box-lines is set to single, which means that all of your boxes will be forced onto one row of the layout (or onto one column, depending on the box-orient value). But if you change it to box-lines: multiple whenever a box is wider or taller than its parent, then any subsequent boxes will be moved to a new row or column.

Vendor Prefixes and Cross-Browser Support

It will come as no surprise to you that Internet Explorer does not (yet) support the flexbox model. Here’s how CanIUse sees the current browser landscape for flexbox:

screenshot

The good news is that Internet Explorer 10 is coming to the party. Download the platform preview, and then check out some interesting examples.

Also, we need to add a bunch of vendor prefixes to guarantee the widest possible support among other “modern� browsers. In a perfect world, we could rely on the following:

#parent {
display: box;
}

#child {
flex-box: 1;
}

But in the real world, we need to be more explicit:

#parent {
display: -webkit-box;
display: -moz-box;
display: -o-box;
display: box;
}

#child {
-webkit-flex-box: 1;
-moz-flex-box: 1;
-o-flex-box: 1;
flex-box: 1;
}

Helper Classes

A shortcut to all of these vendor prefixes — and any page that relies on the flexbox model will have many of them — is to use helper classes. I’ve included them in the source code that accompanies this article. Here’s an example:

.box {
display: -webkit-box;
display: -moz-box;
display: -o-box;
display: box;
}

.flex1 {
-webkit-flex-box: 1;
-moz-flex-box: 1;
-o-flex-box: 1;
flex-box: 1;
}

.flex2 {
-webkit-flex-box: 2;
-moz-flex-box: 2;
-o-flex-box: 2;
flex-box: 2;
}

This allows us to use this simple HTML:

<div class='box'>
  <div class='flex2' id="main">
   <!-- Content here -->
 </div>
  <div class="flex1" id="side�>
    <!-- Content here -->
  </div>
</div>

Using non-semantic helper classes is considered bad practice by many; but with so many vendor prefixes, the shortcut can probably be forgiven. You might also consider using a “mixin� with Sass or Less, which will do the same job. This is something that Twitter sanctions in its preboot.less file.

Flexie.js

For those of you who want to start experimenting with flexbox now but are worried about IE support, a JavaScript polyfill is available to help you out.

Flexie.js, by Richard Herrera, is a plug-and-play file that you simply need to include in your HTML (download it on GitHub). It will then search through your CSS files and make the necessary adjustments for IE — no small feat given that it is remapping much of the layout mark-up on the page.

screenshot

A Word on Firefox

The flexbox model was, at least originally, based on a syntax that Mozilla used in its products. That syntax, called XUL, is a mark-up language designed for user interfaces.

The irony here is that Firefox is still catching up, and its rendering of some flexbox properties can be buggy. Below are some issues to watch out for, which future releases of Firefox will fix. Credit here must go to the uber-smart Peter Gasston and Oli Studholme, giants on whose shoulders I stand.

  • Flexbox ignores overflow: hidden and expands the flexbox child when the content is larger than the child’s width.
  • The setting display: box is treated as display: inline-box if there is no width.
  • The outline on flexbox children is padded as if by a transparent border of the same width.
  • The setting box-align: justify does not work in Firefox.
  • If you set box-flex to 0, Firefox forces the element to act like it’s using the quirks-mode box model.

Summary

The flexbox model is another exciting development in the CSS3 specification, but the technology is still very much cutting-edge. With buggy support in Firefox and no support in Internet Explorer until version 10 moves beyond the platform preview, it is perhaps of limited use in the mainstream.

Nevertheless, the spec is still a working document. So, by experimenting with these new techniques now, you can actively contribute to its development.

It’s hard to recommend the flexbox model for production websites, but envelopes need pushing, and it might well be the perfect way to lay out a new experimental website or idea that you’ve been working on.

Offering a range of new features that help us break free of the float, the flexbox model is another step forward for the layout of modern Web pages and applications. It will be interesting to see how the specification develops and what other delights for laying out pages await the Web design community in the near future.

Further Reading

From floats to flexbox, here’s everything else you need to know:

Special thanks to Tim Davey for the artwork.

(al)


© Richard Shepherd for Smashing Magazine, 2011.


Behind The Scenes Of Nike Better World

Advertisement in Behind The Scenes Of Nike Better World
 in Behind The Scenes Of Nike Better World  in Behind The Scenes Of Nike Better World  in Behind The Scenes Of Nike Better World

Perhaps one of the most talked about websites in the last 12 months has been Nike Better World. It’s been featured in countless Web design galleries, and it still stands as an example of what a great idea and some clever design and development techniques can produce.

In this article, we’ll talk to the team behind Nike Better World to find out how the website was made. We’ll look at exactly how it was put together, and then use similar techniques to create our own parallax scrolling website. Finally, we’ll look at other websites that employ this technique to hopefully inspire you to build on these ideas and create your own variation.

Nike Better World

Nike-Better-World in Behind The Scenes Of Nike Better World

Nike Better World is a glimpse into how Nike’s brand and products are helping to promote sports and its benefits around the world. It is a website that has to be viewed in a browser (preferably a latest-generation browser, although it degrades well) rather than as a static image, because it uses JavaScript extensively to create a parallax scrolling effect.

A good deal of HTML5 is used to power this immersive brand experience and, whatever your views on Nike and its products, this website has clearly been a labor of love for the agency behind it. Although parallax scrolling effects are nothing new, few websites have been able to sew together so many different design elements so seamlessly. There is much to learn here.

An “Interactive Storytelling Experience�

In our opinion, technologies are independent of concept. Our primary focus was on creating a great interactive storytelling experience.

– Widen+Kennedy

Nike turned to long-time collaborator Widen+Kennedy (W+K), one of the largest independent advertising agencies in the world, to put together a team of four people who would create Nike Better World: Seth Weisfeld was the interactive creative director, Ryan Bolls produced, while Ian Coyle and Duane King worked on the design and interaction.

Wiedenkennedy in Behind The Scenes Of Nike Better World

I started by asking the team whether the initial concept for the website pointed to the technologies they would use. As the quote above reveals, they in fact always start by focusing on the concept. This is a great point. Too many of us read about a wonderful new technique and then craft an idea around it. W+K walk in the opposite direction: they create the idea first, and sculpt the available technologies around it.

So, with the concept decided on, did they consciously do the first build as an “HTML5 website,� or did this decision come later?

There were some considerations that led us to HTML5. We knew we wanted to have a mobile- and tablet-friendly version. And we liked the idea of being able to design and build the creative only once to reach all the screens we needed to be on. HTML5 offered a great balance of creativity and technology for us to communicate the Nike Better World brand message in a fresh and compelling way.

– W+K

HTML5 is still not fully supported in all browsers (read “in IE�) without JavaScript polyfills, so just how cross-browser compatible did the website have to be?

The primary technical objectives were for the site to be lightweight, optimized for both Web and devices, as well as to be scalable for future ideas and platforms.

– W+K

To achieve these goals, the website leans on JavaScript for much of the interactivity and scrolling effects. Later, we’ll look at how to create our own parallax scrolling effect with CSS and jQuery. But first, we should start with the template and HTML.

The Starting Boilerplate

It’s worth pointing out the obvious first: Nike Better World is original work and should not be copied. However, we can look at how the website was put together and learn from those techniques. We can also look at other websites that employ parallax scrolling and then create our own page, with our own code and method, and build on these effects.

I asked W+K if it starts with a template.

We started without a framework, with only reset styles. In certain cases, particularly with experimental interfaces, it ensures that complete control of implementation lies in your hands.

– W+K

If you look through some of the code on Nike Better World, you’ll see some fairly advanced JavaScript in a class-like structure. However, for our purposes, let’s keep things fairly simple and rely on HTML5 Boilerplate as our starting point.

Download HTML5 Boilerplate. The “strippedâ€� version will do. You may want to delete some files if you know you won’t be using them (crossdomain.xml, the test folder, etc.).

As you’ll see from the source code (see the final code below), our page is made up of four sections, all of which follow a similar pattern. Let’s look at one individual section:

<section class="story" id="first" data-speed="8" data-type="background">
 <div data-type="sprite" data-offsetY="950" data-Xposition="25%" data-speed="2"></div>
 <article>
  <h2>Background Only</h2>
  <div>
   <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  </div>
 </article>
</section>

I’m not sure this is the best, most semantic use of those HTML5 tags, but it’s what we need to make this effect work. Normally, a section has a heading, so, arguably, the section should be a div and the article should be a section. However, as W+K points out, the HTML5 spec is still young and open to interpretation:

HTML5 is still an emerging standard, particularly in implementation. A lot of thought was given to semantics. Some decisions follow the HTML5 spec literally, while others deviate. As with any new technology, the first to use it in real-world projects are the ones who really shape it for the future.

– W+K

This is a refreshing interpretation. Projects like Nike Better World are an opportunity to “reality check� an emerging standard and, for the conscientious among us, to provide feedback on the spec.

In short, is the theory of the spec practical? W-K elaborates:

We use the article tag for pieces of content that can (and should) be individually (or as a group) syndicated. Each “story� is an article. We chose divs to wrap main content. We took the most liberty with the section tag, as we feel its best definition in the spec is as chapters of content, be it globally.

– W+K

As an aside (no pun intended!), HTML5 Doctor has begun a series of mark-up debates called Simplequizes, which are always interesting and illustrate that there is rarely one mark-up solution for any problem. Make sure to check them out.

In style.css, we can add a background to our section with the following code:

section { background: url(../images/slide1a.jpg) 50% 0 no-repeat fixed; }

We should also give our sections a height and width, so that the background images are visible:

.story { height: 1000px; padding: 0; margin: 0; width: 100%; max-width: 1920px; position: relative; margin: 0 auto; }

I’ve set the height of all our sections to 1000 pixels, but you can change this to suit your content. You can also change it on a per-section basis.

We have also made sure that the maximum width of the section is the maximum width of the background (1920 pixels), and we have specified a relative position so that we can absolutely position its children.

Here’s the page before adding JavaScript. It’s worth digging into the source code to see how we’ve duplicated the sections in the HTML and CSS.

Backgroundonly in Behind The Scenes Of Nike Better World

Even with this code alone, we already have a pleasing effect as we scroll down the page. We’re on our way.

The HTML5 Data Attribute

Before looking at parallax scrolling, we need to understand the new data attribute, which is used extensively throughout the HTML above.

Back in the good old days, we would shove any data that we wanted to be associated with an element into the rel attribute. If, for example, we needed to make the language of a story’s content accessible to JavaScript, you might have seen mark-up like this:

<article class='story' id="introduction" rel="en-us"></article>

Sometimes complex DOM manipulation requires more information than a rel can contain, and in the past I’ve stuffed information into the class attribute so that I could access it. Not any more!

The team at W+K had the same issue, and it used the data attribute throughout Nike Better World:

The data attribute is one of the most important attributes of HTML5. It allowed us to separate mark-up, CSS and JavaScript into a much cleaner workflow. Websites such as this, with high levels of interaction, are almost application-like behind the scenes, and the data attribute allows for a cleaner application framework.

– W+K

Sportisanaddress in Behind The Scenes Of Nike Better World

So, what is the data attribute? You can read about it in the official spec, which defines it as follows:

Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.

– W+K

In other words, any attribute prefixed with data- will be treated as storage for private data; it does not affect the mark-up, and the user cannot see it. Our previous example can now be rewritten as:

<article class='story' id="introduction" data-language="en-us"></article>

The other good news is that you can use more than one data attribute per element, which is exactly what we’re doing in our parallax example. You may have spotted the following:

<div data-type="sprite" data-offsetY="100" data-Xposition="50%" data-speed="2"></div>

Here, we are storing four pieces of information: the x and y data offsets and the data speed, and we are also marking this element as a data type. By testing for the existence of data-type in the JavaScript, we can now manipulate these elements as we wish.

Parallax Scrolling

On our page, three things create the parallax scrolling illusion:

  • The background scrolls at the slowest rate,
  • Any sprites scroll slightly faster than the background,
  • Any section content scrolls at the same speed as the window.

With three objects all scrolling at different speeds, we have created a beautiful parallax effect.

AnExplanation in Behind The Scenes Of Nike Better World

It goes without saying that we don’t need to worry about the third because the browser will take care of that for us! So, let’s start with the background scroll and some initial jQuery.

$(document).ready(function(){
 // Cache the Window object
 $window = $(window);
// Cache the Y offset and the speed
$('[data-type]').each(function() {
  $(this).data('offsetY', parseInt($(this).attr('data-offsetY')));
  $(this).data('speed', $(this).attr('data-speed'));
});
// For each element that has a data-type attribute
 $('section[data-type="background"]').each(function(){
  // Store some variables based on where we are
  $(this).data('speed', parseInt($(this).attr('data-speed')));
   var $self = $(this),
   offsetCoords = $self.offset(),
   topOffset = offsetCoords.top;
   $(window).scroll(function(){
    // The magic will happen in here!
   }); // window scroll
 });	// each data-type
}); // document ready

First, we have our trusty jQuery document ready function, to ensure that the DOM is ready for processing. Next, we cache the browser window object, which we will refer to quite often, and call it $window. (I like to prefix jQuery objects with $ so that I can easily see what is an object and what is a variable.)

We also use the jQuery .data method to attach the Y offset (explained later) and the scrolling speed of the background to each element. Again, this is a form of caching that will speed things up and make the code more readable.

We then iterate through each section that has a data attribute of data-type="background" with the following:

$('section[data-type="background"]').each(function(){}

Already we can see how useful data attributes are for storing multiple pieces of data about an object that we wish to use in JavaScript.

Inside the .each function, we can start to build up a picture of what needs to be done. For each element, we need to grab some variables:

// Store some variables based on where we are
var $self = $(this),
    offsetCoords = $self.offset(),
    topOffset = offsetCoords.top;

We cache the element as $self (again, using the $ notation because it’s a jQuery object). Next, we store the offset() of the element in offsetCoords and then grab the top offset using the .top property of offset().

Finally, we set up the window scroll event, which fires whenever the user moves the scroll bar or hits an arrow key (or moves the trackpad or swipes their finger, etc.).

We need to do two more things: check that the element is in view and, if it is, scroll it. We test whether it’s in view using the following code:

// If this section is in view
if ( ($.Window.scrollTop() + $.Window.height()) > ($offsetCoords.top) &&
( ($offsetCoords.top + $self.height()) > $.Window.scrollTop() ) ) {
}

The first condition checks whether the very top of the element has scrolled into view at the very bottom of the browser window.

The second condition checks whether the very bottom of the element has scrolled past the very top of the browser window.

You could use this method to check whether any element is in view. It’s sometimes useful (and quicker) to process elements only when the user can see them, rather than when they’re off screen.

So, we now know that some part of the section element with a data-type attribute is in view. We can now scroll the background. The trick here is to scroll the background slower or faster than the browser window is scrolling. This is what creates the parallax effect.

Here’s the code:

// Scroll the background at var speed
// the yPos is a negative value because we're scrolling it UP!
var yPos = -($window.scrollTop() / $self.data('speed'));

// If this element has a Y offset then add it on
if ($self.data('offsetY')) {
  yPos += $self.data('offsetY');
}

// Put together our final background position
var coords = '50% '+ yPos + 'px';

// Move the background
$self.css({ backgroundPosition: coords });

The y position is calculated by dividing the distance that the user has scrolled from the top of the window by the speed. The higher the speed, the slower the scroll.

Next, we check whether there is a y offset to apply to the background. Because the amount that the background scrolls is a function of how far the window has scrolled, the further down the page we are, the more the background has moved. This can lead to a situation in which the background starts to disappear up the page, leaving a white (or whatever color your background is) gap at the bottom of each section.

The way to combat this is to give those backgrounds an offset that pushes them down the page an extra few hundred pixels. The only way to find out this magic offset number is by experimenting in the browser. I wish it was more scientific than this, but this offset really does depend on the height of the browser window, the distance scrolled, the height of your sections and the height of your background images. You could perhaps write some JavaScript to calculate this, but to me this seems like overkill. Two minutes experimenting in Firebug yields the same result.

The next line defines a variable coords to store the coordinates of the background. The x position is always the same: 50%. This was the value we set in the CSS, and we won’t change it because we don’t want the element to scroll sideways. Of course, you’re welcome to change it if you want the background to scroll sideways as the user scrolls up, perhaps to reveal something.

(Making the speed a negative number for slower scrolling might make more sense, but then you’d have to divide by -$speed. Two negatives seems a little too abstract for this simple demonstration.)

Finally, we use the .css method to apply this new background position. Et voila: parallax scrolling!

Here’s the code in full:

// Cache the Window object
$window = $(window);

// Cache the Y offset and the speed of each sprite
$('[data-type]').each(function() {
  $(this).data('offsetY', parseInt($(this).attr('data-offsetY')));
  $(this).data('speed', $(this).attr('data-speed'));
});

// For each element that has a data-type attribute
$('section[data-type="background"]').each(function(){

// Store some variables based on where we are
var $self = $(this),
    offsetCoords = $self.offset(),
    topOffset = offsetCoords.top;

$(window).scroll(function(){

// If this section is in view
if ( ($window.scrollTop() + $window.height()) > (topOffset) &&
( (topOffset + $self.height()) > $window.scrollTop() ) ) {

  // Scroll the background at var speed
  // the yPos is a negative value because we're scrolling it UP!
  var yPos = -($window.scrollTop() / $self.data('speed'));

  // If this element has a Y offset then add it on
  if ($self.data('offsetY')) {
    yPos += $self.data('offsetY');
  }

  // Put together our final background position
  var coords = '50% '+ yPos + 'px';

  // Move the background
  $self.css({ backgroundPosition: coords });

  }; // in view

}); // window scroll

});	// each data-type

Of course, what we’ve done so far is quite a bit simpler than what’s on Nike Better World. W+K admits that the parallax scrolling threw it some challenges:

The parallax scrolling presented a few small challenges in cross-browser compatibility. It took a little experimenting to ensure the best scrolling experience. In the end, it was less about the actual parallax effect and more about synchronized masking of layers during transitions.

– W+K

W+K also reveals how it maintained a fast loading and paint speed by choosing its tools wisely:

The key to maintaining faster speeds is to use native CSS where possible, because DOM manipulation slows down rendering, particularly on older browsers and processors.

– W+K

For example, the “Moreâ€� button below spins on hover, an effect achieved with CSS3. In browsers that don’t support CSS3 transforms, the purpose of the graphic is still obvious.

CSSuse in Behind The Scenes Of Nike Better World

Adding More Elements

Of course, one of the other common features of parallax scrolling is that multiple items on the page scroll. So far, we have two elements that move independently of each other: the first is the page itself, which scrolls when the user moves the scroll bar, and the second is the background, which now scrolls at at slower rate thanks to the jQuery above and the background-position CSS attribute.

For many pages, this would be enough. It would be a lovely effect for the background of, say, a blog. However, Nike and others push it further by adding elements that move at a different speed than that of the page and background. To make things easy — well, easier — I’m going to call these new elements sprites.

Here’s the HTML:

<div id="smashinglogo" data-type="sprite" data-offsetY="1200" data-Xposition="25%" data-speed="2"></div>

Put this just before the closing </article> tag, so that it appears behind the contents of <article>. First, we give the div an id so that we can refer to it specifically in the CSS. Then we use our HTML5 data attribute to store a few values:

  • The status of a sprite,
  • A y (vertical) offset of 1200 pixels,
  • An x (horizontal) position as a percentage,
  • A scrolling speed.

We give the x position of the sprite a percentage value because it is relative to the size of the viewport. If we gave it an absolute value, which you’re welcome to try, there’s a chance it could slide out of view on either the left or right side.

Now about that y offset…

Inception

This is the bit that’s going to mess with your noodle and is perhaps the hardest part of the process to grasp.

Thanks to the logic in the JavaScript, the sprite won’t move until the parent section is in view. When it does move, it will move at (in this case) half the speed. You need the vertical position, then, to account for this slower movement; elements need to be placed higher up if they will be scrolling more slowly and, therefore, moving less on the y axis.

We don’t know how far the user has to scroll before the section appears at the bottom of the page. We could use JavaScript to read the viewport size and then do some calculations based on how far down the page the section is positioned. But that is already sounding too complicated. There is an easier way.

What we do know is how far the user has scrolled before the current section is flush with the top of the viewport: they have scrolled the y offset of that particular section. (Put another way, they have scrolled the height of all of the elements above the current one.)

So, if there are four sections, each 1000 pixels high, and the third section is at the top of the viewport, then the user must have scrolled 2000 pixels, because this is the total height of the preceding sections.

If we want our sprite to appear 200 pixels from the top of its parent section, you’d figure that the total vertical offset we give it should be 2200 pixels. But it’s not, because this sprite has speed, and this speed (in our example) is a function of how far the page has been scrolled.

Let’s assume that the speed is set as 2, which is half the speed at which the page is scrolling. When the section is fully in view, then the window has scrolled 2000 pixels. But we divide this by the speed (2) to get 1000 pixels. If we want the sprite to appear 200 pixels from the top, then we need to add 200 to 1000, giving us 200 pixels. Therefore, the offset is 1200. In the JavaScript, this number is inverted to -1200 because we are pushing the background-position down off the bottom of the page.

Here’s a sketch to show this in action.

Parallax-sketch in Behind The Scenes Of Nike Better World

This is one of those concepts that is easier to understand when you view the page and source code and scroll around with the console open in Firebug or Developer Tools.

The JavaScript looks like this:

// Check for other sprites in this section
$('[data-type="sprite"]', $self).each(function() {

  // Cache the sprite
  $sprite = $(this);

  // Use the same calculation to work out how far to scroll the sprite
  var yPos = -($.Window.scrollTop() / $sprite.data('speed'));
  var coords = $sprite.data('Xposition') + ' ' + (yPos + $sprite.data('offsetY')) + 'px';
  $sprite.css({ backgroundPosition: coords });
}); // sprites

HTML5 Video

One criticism levelled at Nike Better World is that it didn’t use HTML5 video. HTML5 is still not fully supported across browsers (I’m looking at you, Internet Explorer), but for the purposes of this article, we’ll embrace HTML5 video, thanks to the lovely folks at Vimeo and Yum Yum London.

But we can’t set a video as a background element, so we have a new challenge: how to position and scroll this new sprite?

Well, there are three ways:

  1. We could change its margin-top property within its parent section;
  2. We could make it a position: absolute element and change its top property when its parent section comes into view;
  3. We could define it as position: fixed and set its top property relative to the viewport.

Because we already have code for the third, let’s grab the low-hanging fruit and adapt it to our purposes.

Here’s the HTML we’ll use, which I’ve placed after the closing </article> tag:

<video controls width="480" width="320" data-type="video" data-offsetY="2500" data-speed="1.5">
  <source src="video/parallelparking.theora.ogv" type="video/ogg" />
  <source src="video/parallelparking.mp4" type="video/mp4" />
  <source src="video/parallelparking.webm" type="video/webm" />
</video>

First, we’ve opened our HTML5 video element and defined its width and height. We then set a new data-type state, video, and defined our y offset and the speed at which the element scrolls. It’s worth nothing that some experimentation is needed here to make sure the video is positioned correctly. Because it’s a position: fixed element, it will scroll on top of all other elements on the page. You can’t cater to every viewport at every screen resolution, but you can play around to get the best compromise for all browser sizes (See “Bespoke to Brokeâ€� below).

The CSS for the video element looks like this:

video { position: fixed; left: 50%; z-index: 1;}

I’ve positioned the video 50% from the left so that it moves when the browser’s size is changed. I’ve also given it a z-index: 1. This z-index prevents the video element from causing rendering problems with neighbouring sections.

And now for the JavaScript! This code should be familiar to you:

// Check for any Videos that need scrolling
$('[data-type="video"]', $self).each(function() {

  // Cache the sprite
  $video = $(this);

  // Use the same calculation to work out how far to scroll the sprite
  var yPos = -($window.scrollTop() / $video.data('speed'));
  var coords = (yPos + $video.data('offsetY')) + 'px';

  $video.css({ top: coords });

}); // video

And there you have it! A parallax scrolling HTML5 video.

Bespoke or Broke

Of course, every design is different, which means that your code for your design will be unique. The JavaScript above will plug and play, but you will need to experiment with values for the y offset to get the effect you want. Different viewport sizes means that users will scroll different amounts to get to each section, and this in turn affects how far your elements scroll. I can’t control it any more than you can, so you have to pick a happy medium. Even Nike Better World suffers when the viewport’s vertical axis stretches beyond the height of the background images.

I asked W+K how it decides which effects to power with JavaScript and which are better suited to modern CSS techniques:

Key points that required complex interaction relied on JavaScript, while visual-only interactivity relied on CSS3. Additionally, fewer browsers support native CSS3 techniques, so items that were more important to cross-browser compatibility were controlled via JavaScript as well.

– W+K

This is a wonderful example of “real-world design.� So often we are bamboozled with amazing new CSS effects, and we make websites that sneer at older browsers. The truth is, for most commercial websites and indeed for websites like Nike Better World that target the biggest audience possible, stepping back and considering how best to serve your visitors is important.

W+K explains further:

We started by creating the best possible version, but always kept the needs of all browsers in mind. Interactive storytelling must balance design and technology to be successful. A great website usable in one or two browsers ultimately fails if you want to engage a wide audience.

– W+K

And Internet Explorer?!

IE was launched in tandem with the primary site. Only IE6 experienced challenges, and as a deprecated browser, it gracefully degrades.

– W+K

The Final Code

The code snippets in this piece hopefully go some way to explaining the techniques required for a parallax scrolling effect. You can extend them further to scroll multiple elements in a section at different speeds, or even scroll elements sideways!

Feel free to grab the full source code from GitHub, and adapt it as you see fit. Don’t forget to let us know what you’ve done, so that others can learn from your work.

Of course, remember that manipulating huge images and multiple sprites with JavaScript can have huge performance drawbacks. As Keith Clark recently tweeted:

KeithClark1 in Behind The Scenes Of Nike Better World

Test, test and test again. Optimize your images, and be aware that you may have to compromise to support all browsers and operating systems.

Tell A Story

Above and beyond the technical wizardry of parallax websites — some of the best of which are listed below — the common thread that each seems to embody is story. That’s what makes them great.

I asked W+K what it learned from the project:

That a strong voice, simplicity and beauty are integral to a great interactive storytelling experience. We often hear things like “content is king, and technology is just a tool to deliver it,â€� but when you’re able to successfully combine a powerful message with a compelling execution, it creates an experience that people really respond to and want to spend time with.

– W+K

We really have just scratched the surface of the work that goes into a website like Nike Better World. The devil is in the details, and it doesn’t take long to see how much detail goes into both the design and development.

However, if you have a compelling story to tell and you’re not afraid of a little JavaScript and some mind-bending offset calculations, then a parallax website might just be the way to communicate your message to the world.

More Examples

Nike wasn’t the first and won’t be the last. Here are some other great examples of parallax scrolling:

Manufacture d’essai

Manufacture-dEssai in Behind The Scenes Of Nike Better World

Yebo Creative

Yebocreative in Behind The Scenes Of Nike Better World

TEDx Portland

TEDxPortland1 in Behind The Scenes Of Nike Better World

Ben the Bodyguard

BenTheBodyguard in Behind The Scenes Of Nike Better World

Campaign Monitor Is Hiring

CampaignMonitor1 in Behind The Scenes Of Nike Better World

Nizo App

Nizo1 in Behind The Scenes Of Nike Better World

7 Best Things of 2010

7BestThings in Behind The Scenes Of Nike Better World

If you’ve seen or built a great parallax website, please let us know about it in the comments.

… If you need any more encouragement to create a website as compelling as these, here’s what the team at W+K used to put together Nike Better World: MacBook Air 13″, Canon 5D Mark II, Coda, Adobe Photoshop and Adobe Illustrator.

Thanks

Putting together this article took the cooperation of a number of people. I’d like to thank Seth, Ryan, Ian and Duane for answering my questions; Katie Abrahamson at W+K for her patience and for helping coordinate the interview; and Nike for allowing us to dissect its website so that others could learn.

(al)


© Richard Shepherd for Smashing Magazine, 2011.


How To Use CSS3 Pseudo-Classes

Advertisement in How To Use CSS3 Pseudo-Classes
 in How To Use CSS3 Pseudo-Classes  in How To Use CSS3 Pseudo-Classes  in How To Use CSS3 Pseudo-Classes

CSS3 is a wonderful thing, but it’s easy to be bamboozled by the transforms and animations (many of which are vendor-specific) and forget about the nuts-and-bolts selectors that have also been added to the specification. A number of powerful new pseudo-selectors (16 are listed in the latest W3C spec) enable us to select elements based on a range of new criteria.

Css3 in How To Use CSS3 Pseudo-Classes

Before we look at these new CSS3 pseudo-classes, let’s briefly delve into the dusty past of the Web and chart the journey of these often misunderstood selectors.

A Brief History Of Pseudo-Classes

When the CSS1 spec was completed back in 1996, a few pseudo-selectors were included, many of which you probably use almost every day. For example:

  • :link
  • :visited
  • :hover
  • :active

Each of these states can be applied to an element, usually <a>, after which comes the name of the pseudo-class. It’s amazing to think that these pseudo-classes arrived on the scene before HTML4 was published by the W3C a year later in December 1997.

CSS2 Arrives

Hot on the heels of CSS1 was CSS2, whose recommended spec was published just two years later in May 1998. Along with exciting things like positioning were new pseudo-classes: :first-child and :lang().

:lang
There are a couple of ways to indicate the language of a document, and if you’re using HTML5, it’ll likely be by putting <html lang="en"> just after the doc type (specifying your local language, of course). You can now use :lang(en) to style elements on a page, which is useful when the language changes dynamically.

:first-child
You may have already used :first-child in your documents. It is often used to add or remove a top border on the first element in a list. Strange, then, that it wasn’t accompanied by :last-child; we had to wait until CSS3 was proposed before it could meet its brother.

Why Use Pseudo-Classes?

What makes pseudo-classes so useful is that they allow you to style content dynamically. In the <a> example above, we are able to describe how links are styled when the user interacts with them. As we’ll see, the new pseudo-classes allow us to dynamically style content based on its position in the document or its state.

Sixteen new pseudo-classes have been introduced as part of the W3C’s CSS Proposed Recommendation, and they are broken down into four groups: structural pseudo-classes, pseudo-classes for the states of UI elements, a target pseudo-class and a negation pseudo-class.

W3c in How To Use CSS3 Pseudo-Classes
The W3C is the home of CSS.

Let’s now run through the 16 new pseudo-selectors one at a time and see how each is used. I’ll use the same notation for naming classes that the W3C uses, where E is the element, n is a number and s is a selector.

Sample Code

For many of these new selectors, I’ll also refer to some sample code so that you can see what effect the CSS has. We’ll take a regular form and make it suitable for an iPhone using our new CSS3 pseudo-classes.

Note that we could arguably use ID and class selectors for much of this form, but it’s a great opportunity to take our new pseudo-classes out for a spin and demonstrate how you might use them in a real-world example. Here’s the HTML (which you can see in action on my website):

<form>
 <hgroup>
 <h1>Awesome Widgets</h1>
 <h2>All the cool kids have got one :)</h2>
 </hgroup>
 <fieldset id="email">
 <legend>Where do we send your receipt?</legend>
 <label for="email">Email Address</label>
 <input type="email" name="email" placeholder="Email Address" />
 </fieldset>

 <fieldset id="details">
 <legend>Personal Details</legend>
 <select name="title" id="field_title">
  <option value="" selected="selected">Title</option>
  <option value="Mr">Mr</option>
  <option value="Mrs">Mrs</option>
  <option value="Miss">Miss</option>
 </select>

 <label for="firstname">First Name</label>
 <input name="firstname" placeholder="First Name" />

 <label for="initial">Initial</label>
 <input name="initial" placeholder="Initial" size="3" />

 <label for="surname">Surname</label>
 <input name="surname" placeholder="Surname" />
 </fieldset>

 <fieldset id="payment">
 <legend>Payment Details</legend>

 <label for="cardname">Name on card</label>
 <input name="cardname" placeholder="Name on card" />

 <label for"cardnumber">Card number</label>
 <input name="cardnumber" placeholder="Card number" />

 <select name="cardType" id="field_cardType">
  <option value="" selected="selected">Select Card Type</option>
  <option value="1">Visa</option>
  <option value="2">American Express</option>
  <option value="3">MasterCard</option>
 </select>

 <label for="cardExpiryMonth">Expiry Date</label>
 <select id="field_cardExpiryMonth" name="cardExpiryMonth">
  <option selected="selected" value="mm">MM</option>
   <option value="01">01</option>
   <option value="02">02</option>
   <option value="03">03</option>
   <option value="04">04</option>
   <option value="05">05</option>
   <option value="06">06</option>
   <option value="07">07</option>
   <option value="08">08</option>
   <option value="09">09</option>
   <option value="10">10</option>
   <option value="11">11</option>
   <option value="12">12</option>
 </select> /
 <select id="field_cardExpiryYear" name="cardExpiryYear">
   <option value="yyyy">YYYY</option>
    <option value="2011">11</option>
    <option value="2012">12</option>
    <option value="2013">13</option>
    <option value="2014">14</option>
    <option value="2015">15</option>
    <option value="2016">16</option>
    <option value="2017">17</option>
    <option value="2018">18</option>
    <option value="2019">19</option>
 </select>

 <label for"securitycode">Security code</label>
 <input name="securitycode" type="number" placeholder="Security code" size="3" />

 <p>Would you like Insurance?</p>
 <input type="radio" name="Insurance" id="insuranceYes" />
  <label for="insuranceYes">Yes Please!</label>
 <input type="radio" name="Insurance" id="insuranceNo" />
  <label for="insuranceNo">No thanks</label>

 </fieldset>

 <fieldset id="submit">
 <button type="submit" name="Submit" disabled>Here I come!</button>
 </fieldset>
</form>

Before-after in How To Use CSS3 Pseudo-Classes
Our form, before and after.

1. Structural Pseudo-Classes

According to the W3C, structural pseudo-classes do the following:

… permit selection based on extra information that lies in the document tree but cannot be represented by other simple selectors or combinators.

What this means is that we have selectors that have been turbo-charged to dynamically select content based on its position in the document. So let’s start at the beginning of the document, with :root.

Selectors-level-screenshot in How To Use CSS3 Pseudo-Classes
Level 3 selectors on the W3C website.

E:root

The :root pseudo-class selects the root element on the page. Ninety-nine times out of a hundred, this will be the <html> element. For example:

:root { background-color: #fcfcfc; }

It’s worth noting that you could style the <html> element instead, which is perhaps a little more descriptive:

html { background-color: #fcfcfc; }

iPhone Form Example
Let’s move over to our sample code and give the document some basic text and background styles:

:root {
color: #fff;
text-shadow: 0 -1px 0 rgba(0,0,0,0.8);
background: url(…/images/background.png) no-repeat #282826; }

E:nth-child(n)

The :nth-child() selector might require a bit of experimentation to fully understand. The easiest implementation is to use the keywords odd or even, which are useful when displaying data that consists of rows or columns. For example, we could use the following:

ul li:nth-child(odd) {
background-color: #666;
color: #fff; }

This would highlight every other row in an unordered list. You might find this technique extremely handy when using tables. For example:

table tr:nth-child(even) { … }

The :nth-child selector can be much more specific and flexible, though. You could select only the third element from a list, like so:

li:nth-child(3) { … }

Note that n does not start at zero, as it might in an array. The first element is :nth-child(1), the second is :nth-child(2) and so on.

We can also use some simple algebra to make things even more exciting. Consider the following:

li:nth-child(2n) { … }

Whenever we use n in this way, it stands for all positive integers (until the document runs out of elements to select!). In this instance, it would select the following list items:

  • Nothing (2 × 0)
  • 2nd element (2 × 1)
  • 4th element (2 × 2)
  • 6th element (2 × 3)
  • 8th element (2 × 4)
  • etc.

This actually gives us the same thing as nth-child(even). So, let’s mix things up a bit:

li:nth-child(5n) { … }

This gives us:

  • Nothing (5 × 0)
  • 5th element (5 × 1)
  • 10th element (5 × 2)
  • 15th element (5 × 3)
  • 20th element (5 × 4)
  • etc.

Perhaps this would be useful for long lists or tables, perhaps not. We can also add and subtract numbers in this equation:

li:nth-child(4n + 1) { … }

This gives us:

  • 1st element ((4 × 0) + 1)
  • 5th element ((4 × 1) + 1)
  • 9th element ((4 × 2) + 1)
  • 13th element ((4 × 3) + 1)
  • 17th element ((4 × 4) + 1)
  • etc.

SitePoint points out an interesting quirk here. If you set n as negative, you’ll be able to select the first x number of items like so:

li:nth-child(-n + x) { … }

Let’s say you want to select the first five items in a list. Here’s the CSS:

li:nth-child(-n + 5) { … }

This gives us:

  • 5th element (-0 + 5)
  • 4th element (-1 + 5)
  • 3rd element (-2 + 5)
  • 2nd element (-3 + 5)
  • 1st element (-4 + 5)
  • Nothing (-5 + 5)
  • Nothing (-6 + 5)
  • etc.

If you’re listing data in order of popularity, then highlighting, say, the top 10 entries might be useful.

WebDesign & Such has created a demo of zebra striping, which is a perfect example of how you might use nth-child in practice.

Zebra-Striping-a-Table-with-CSS3 in How To Use CSS3 Pseudo-Classes
Zebra striping a table with CSS3.

If none of your tables need styling, then you could do what Webvisionary Awards has done and use :nth-child to style alternating sections of its website. Here’s the CSS:

section > section:nth-child(even) {
background:rgba(255,255,255,.1)
url("../images/hr-damaged2.png") 0 bottom no-repeat;
}

The effect is subtle on the website, but it adds a layer of detail that would be missed in older browsers.

WVA-2011 in How To Use CSS3 Pseudo-Classes
The :nth-child selectors in action on Webvisionary Awards.

iPhone Form Example
We could use :nth-child in a few places in our iPhone form example, but let’s focus on one. We want to hide the labels for the first three fieldsets from view and use the placeholder text instead. Here’s the CSS:

form:nth-child(-n+3) label { display: none; }

Here, we’re looking for the first three children of the <form> element (which are all fieldsets in our code) and then selecting the label. We then hide these labels with display: none;.

E:nth-last-child(n)

Not content with confusing us all with the :nth-child() pseudo-class, the clever folks over at the W3C have also given us :nth-last-child(n). It operates much like :nth-child() except in reverse, counting from the last item in the selection.

li:nth-last-child(1) { … }

The above will select the last element in a list, whereas the following will select the penultimate element:

li:nth-last-child(2) { … }

Of course, you could create other rules, like this one:

li:nth-last-child(2n+1) { … }

But you would more likely want to use the following to select the last five elements of a list (based on the logic discussed above):

li:nth-last-child(-n+5) { … }

If this still doesn’t make much sense, Lea Verou has created a useful CSS3 structural pseudo-class selector tester, which is definitely worth checking out.

CSS3-structural-pseudo-class-selector-tester in How To Use CSS3 Pseudo-Classes
CSS3 structural pseudo-class selector tester.

iPhone Form Example
We can use :nth-last-child in our example to add rounded corners to our input for the “Card number.� Here’s our CSS, which is overly specific but gives you an idea of how we can chain pseudo-selectors together:

fieldset:nth-last-child(2) input:nth-last-of-type(3) {
border-radius: 10px; }

We first grab the penultimate fieldset and select the input that is third from last (in this case, our “Card number� input). We then add a border-radius.

:nth-of-type(n)

Now we’ll get even more specific and apply styles only to particular types of element. For example, let’s say you wanted to style the first paragraph in an article with a larger font. Here’s the CSS:

article p:nth-of-type(1) { font-size: 1.5em; }

Perhaps you want to align every other image in an article to the right, and the others to the left. We can use keywords to control this:

article img:nth-of-type(odd) { float: right; }
article img:nth-of-type(even) { float: left; }

As with :nth-child() and :nth-last-child(), you can use algebraic expressions:

article p:nth-of-type(2n+2) { … }
article p:nth-of-type(-n+1) { … }

It’s worth remembering that if you need to get this specific about targeting elements, then using descriptive class names instead might be more useful.

Simon Foster has created a beautiful infographic about his 45 RPM record collection, and he uses :nth-of-type to style some of the data. Here’s a snippet from the CSS, which assigns a different background to each genre type:

ul#genre li:nth-of-type(1) {
  width:32.9%;
	background:url(images/orangenoise.jpg);
}
ul#genre li:nth-of-type(2) {
  width:15.2%;
	background:url(images/bluenoise.jpg);
}
ul#genre li:nth-of-type(3) {
  width:13.1%;
	background:url(images/greennoise.jpg);
}

And here’s what it looks like on his website:

For-The-Record in How To Use CSS3 Pseudo-Classes
The :nth-of-type selectors on “For the Record.�

iPhone Form Example
Let’s say we want every second input element to have rounded corners on the bottom. We can achieve this with CSS:

input:nth-of-type(even) {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px; }

In our example, we want to apply this only to the fieldset for payment, because the fieldset for personal details has three text inputs. We’ll also get a bit tricky and make sure that we don’t select any of the radio inputs. Here’s the final CSS:

#payment input:nth-of-type(even):not([type=radio]) {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border-bottom: 1px solid #999;
margin-bottom: 10px; }

We’ll explain :not later in this article.

:nth-last-of-type(n)

Hopefully, by now you see where this is going: :nth-last-of-type() starts at the end of the selected elements and works backwards.

To select the last paragraph in an article, you would use this:

article p:nth-last-of-type(1) { … }

You might want to choose this selector instead of :last-child if your articles don’t always end with paragraphs.

:first-of-type and :last-of-type

If :nth-of-type() and :nth-last-of-type() are too specific for your purposes, then you could use a couple of simplified selectors. For example, instead of this…

article p:nth-of-type(1) {
font-size: 1.5em; }

… we could just use this:

article p:first-of-type {
font-size: 1.5em; }

As you’d expect, :last-of-type works in exactly the same way but from the last element selected.

iPhone Form Example
We can use both :first-of-type and :last-of-type in our iPhone example, particularly when styling the rounded corners. Here’s the CSS:

fieldset input:first-of-type:not([type=radio]) {
border-top-left-radius: 10px;
border-top-right-radius: 10px; }

fieldset input:last-of-type:not([type=radio]) {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px; }

The first line of CSS adds a top rounded border to all :first-of-type inputs in a fieldset that aren’t radio buttons. The second line adds the bottom rounded border to the last input element in a fieldset.

:only-of-type

There’s one more type selector to look at: :only-of-type(). This is useful for selecting elements that are the only one of their kind in their parent element.

For example, consider the difference between this CSS selector…

p {
font-size: 18px; }

… and this one:

p:only-of-type {
font-size: 18px; }

The first selector will style every paragraph element on the page. The second element will grab a paragraph that is the only paragraph in its parent.

This could be handy when you are styling content or data that has been dynamically outputted from a database and the query returns only one result.

Devsnippet has created a demo in which single images are styled differently from multiple images.

Only-of-type-Pseudo-Class in How To Use CSS3 Pseudo-Classes
Devsnippet’s demo for :only-of-type.

iPhone Form Example
In the case of our iPhone example, we can make sure that all inputs that are the only children of a fieldset have rounded corners on both the top and bottom. The CSS would be:

fieldset input:only-of-type {
border-radius: 10px; }

:last-child

It’s a little strange that :first-child was part of the CSS2 spec but that its partner in crime, :last-child, didn’t appear until CSS3. It takes no expressions or keywords here; it simply selects the last child of its parent element. For example:

li {
border-bottom: 1px solid #ccc; }

li:last-child {
border-bottom: none; }

This is a useful way to remove bottom borders from lists. You’ll see this technique quite often in WordPress widgets.

Rachel Andrew looks at :last-child and other CSS pseudo-selectors in her 24 Ways article “Cleaner Code With CSS3 Selectors.� Rachel shows us how to use this selector to create a well-formatted image gallery without additional classes.

Screen-shot-2011-03-22-at-21 49 46 in How To Use CSS3 Pseudo-Classes
The CSS for :last-child in action, courtesy of Rachel Andrew.

:only-child

If an element is the only child of its parent, then you can select it with :only-child. Unlike with :only-of-type, it doesn’t matter what type of element it is. For example:

li:only-child { … }

We could use this to select list elements that are the only list elements in their <ol> or <ul> parent.

:empty

Finally, in structural pseudo-classes, we have :empty. Not surprisingly, this selects only elements that have no children and no content. Again, this might be useful when dealing with dynamic content outputted from a database.

#results:empty {
background-color: #fcc; }

You might use the above to draw the user’s attention to an empty search results section.

2. The Target Pseudo-Class

:target

This is one of my favourite pseudo-classes, because it allows us to style elements on the page based on the URL. If the URL has an identifier (that follows an #), then the :target pseudo-class will style the element that shares the ID with the identifier. Take a URL that looks like this:

http://www.example.com/css3-pseudo-selectors#summary

The section with the id summary can now be styled like so:

:target {
background-color: #fcc; }

This is a great way to style elements on pages that have been linked to from external content. You could also use it with internal anchors to highlight content that users have skipped to.

Perhaps the most impressive use of :target I’ve seen is Corey Mwamba’s Scrolling Site of Green. Corey uses some creative CSS3 and the :target pseudo-class to create animated tabbed navigation. The demo contains some clever use of CSS3, illustrating how pseudo-classes are often best used in combination with other CSS selectors.

Coreys-scrolling-site-of-green in How To Use CSS3 Pseudo-Classes
Corey’s Scrolling Site of Green.

There’s also an interesting example over at Web Designer Notebook. In it, :target and Webkit animations are used to highlight blocks of text in target divs. Chris Coyier also creates a :target-based tabbing system at CSS-Tricks.

iPhone Form Example
As you’ll see on my demo page, I’ve added a navigation bar at the top that skips down to different sections of the form. We can highlight any section the user jumps to with the following CSS:

:target {
background-color: rgba(255,255,255,0.3);

-webkit-border-radius:
10px;}

3. The UI Element States Pseudo-Classes

:enabled and :disabled

Together with :checked, :enabled and :disabled make up the three pseudo-classes for UI element states. That is, they allow you to style elements (usually form elements) based on their state. A state could be set by the user (as with :checked) or by the developer (as with :enabled and :disabled). For example, we could use the following:

input:enabled {
background-color: #dfd; }

input:disabled {
background-color: #fdd; }

This is a great way to give feedback on what users can and cannot fill in. You’ll often see this dynamic feature enhanced with JavaScript.

iPhone Form Example
To illustrate :disabled in practice, I have disabled the form’s “Submit� button in the HTML and added this line of CSS:

:disabled {
color: #600; }

The button text is now red!

:checked

The third pseudo-class here is :checked, which deals with the state of an element such as a checkbox or radio button. Again, this is very useful for giving feedback on what users have selected. For example:

input[type=radio]:checked {
font-weight: bold; }

iPhone Form Example
As a flourish, we can use CSS to highlight the text next to each radio button once the button has been pressed:

input:checked + label {
text-shadow: 0 0 6px #fff; }

We first select any input that has been checked, and then we look for the very next <span> element that contains our text. Highlighting the text with a simple text-shadow is an effective way to provide user feedback.

4. Negation Pseudo-Class

:not

This is another of my favorites, because it selects everything except the element you specify. For example:

:not(footer) { … }

This selects everything on the page that is not a footer element. When used with form inputs, they allow us to get a little sneakier:

input:not([type=submit]) { … }
input:not(disabled) { … }

The first line selects every form input that’s not a “Submit� button, which is useful for styling forms. The second selects all input elements that are not enabled; again useful for giving feedback on how to fill in a form.

iPhone User Example
You’ve already seen the :not selector in action. It’s particularly powerful when chained with other CSS3 pseudo-selectors. Let’s take a closer look at one example:

fieldset input:not([type=radio]) {
margin: 0;
width: 290px;
font-size: 18px;
border-radius: 0;
border-bottom: 0;
border-color: #999;
padding: 8px 10px;}

Here we are selecting all inputs inside fieldset elements that are not radio buttons. This is incredibly useful when styling forms because you will often want to style text inputs different from select boxes, radio buttons and “Submit� buttons.

Check out our final page.

What’s Old Is New Again

Let’s go back to the beginning of our story and the humble a:link. HTML5 arrived on the scene recently and brought with it an exciting change to the <a> element that gives the CSS3 pseudo-selector an additive effect.

An <a> element can now be wrapped around block-level elements, turning whole sections of your page into links (as long as those sections don’t contain other interactive elements). Whereas JavaScript was once popular for making entire <div> elements clickable, you can now do so by wrapping sections in <a> tags, like so:

<a href="http://www.smashing-magazine.com">
<div id="advert">
<hgroup>
<h1>Jackson’s Widgets</h1>
<h2>The finest widgets in Kentucky</h2>
</hgroup>
<p>Buy Jackson’s Widgets today,
and be sure of a trouble-free life for you,
your widget and your machinery.
Trusted and sold since 1896.</p>
</div>
</a>

The implication for CSS pseudo-selectors is that you can now style a <div> based on whether it is being hovered over (a:hover) or is active (a:active), like so:

a:hover #advert {
background-color: #f7f7f7; }

Anything that decreases JavaScript and increases semantic code has to be good!

Cross-Browser Compatibility

You had to ask, didn’t you! Unbelievably, Internet Explorer 8 (and earlier) doesn’t support any of these selectors, whereas the latest versions of Chrome, Opera, Safari and Firefox all do. Before your blood boils, consider the following solutions.

Internet Explorer 9

Unless you’ve been living under a rock for the last week, you’ll have heard that Microsoft unleashed its latest browser on an unsuspecting public. The good thing is, it’s actually quite good. While I don’t expect people who are reading this article to change their browsing habits, it’s worth remembering that the majority of the world uses IE; and thanks to Windows Update and a global marketing campaign, we can hope to see IE9 as the dominant Windows browser in the near future. That’s good for Web designers, and it’s good for pseudo-selectors. But what about IE8 and its ancestors?

Ie9 in How To Use CSS3 Pseudo-Classes
Internet Explorer 9 is here.

JavaScript

Our old friend JavaScript comes to the rescue. I particularly like Selectivizr by Keith Clark. Keith has put together a lovely script that, in combination with your JavaScript library of choice, adds CSS3 pseudo-class selector functionality for earlier versions of IE. Be warned that some libraries fare better than others: if you’re using MooTools with Selectivizr, then all the pseudo-classes will be available, but if you’re relying on jQuery to do the heavy lifting, then a number of the selectors won’t work at all.

Selectivizr in How To Use CSS3 Pseudo-Classes
Selectivizr.

Keith recently released a jQuery plug-in that extends jQuery to include support for the following CSS3 pseudo-class selectors:

  • :first-of-type
  • :last-of-type
  • :only-of-type
  • :nth-of-type
  • :nth-last-of-type

It’s also worth looking at the ubiquitous ie7.js script (and its successors) by Dean Edwards. This script solves a number of IE-related problems, including CSS3 pseudo-selectors.

So, Should We Start Using CSS3 Pseudo-Selectors Today?

I guess the answer to that question depends on how you view JavaScript. It’s true that pseudo-selectors can be completely replaced with classes and IDs; but it’s also true that, when styling complex layouts, pseudo-selectors are both incredibly useful and the natural next step for your CSS. If you find that they improve the readability of your CSS and reduce the need for (non-semantic) classes in your HTML, then it I’d definitely recommend embracing them today.

You could use two selectors and fall back on a class name, but that would just duplicate work. It also means that you wouldn’t need the pseudo-classes in the first place. But if you did choose to go down this path, the code might look something like this:

li:nth-of-type(3),
li.third { … }

This method is not as flexible as using pseudo-classes because you have to keep updating the HTML and CSS when the page content changes.

If a lot of your users don’t have JavaScript enabled, that puts you in a bit of a bind. Many Web designers argue that functionality (i.e. JavaScript) is different from layout (i.e. CSS), and so you should not rely on JavaScript to make pseudo-selectors work in IE8 and earlier.

While I agree with the principle, in practice I believe that providing the best possible experience to 99% of your users is better than accounting for the remaining 1% (or however big your non-JavaScript base may be).

Follow your website’s analytics, and be prepared to make decisions that improve your skills as a Web designer and, more importantly, provide the best experience possible to the majority of users.

Final Thoughts

It’s hard not to be depressed by IE8’s complete lack of support for pseudo-classes. Arguably, having the browser calculate and recalculate page styles in this fashion will have implications for rendering speed; but because all other major browsers now support these selectors, it’s frustrating that most of our users can’t benefit from them without a JavaScript hack.

But as Professor Farnsworth says, “Good news everyone!� Breaking on the horizon is the dawn of Internet Explorer 9, and Microsoft has made sure that its new browser supports each and every one of the selectors discussed in this article.

CSS3 pseudo-selectors won’t likely take up large chunks of your style sheets. They are specific yet dynamic and are more likely, at least initially, to add finishing touches to a page than to set an overall style. Perhaps you want to drop the bottom border in the last item of a list, or give visual feedback to users as they fill in a form. This is all possible with CSS3, and as usage becomes more mainstream, I expect these will become a regular part of the Web designer’s toolbox.

If you’ve seen any interesting or exciting uses of these selectors out there in the field, do let us know in the comments below.

Other Resources

You may be interested in the following articles and related resources:

(al) (ik)


© Richard Shepherd for Smashing Magazine, 2011. | Permalink | Post a comment | Smashing Shop | Smashing Network | About Us
Post tags: , ,


Using HTML5 To Transform WordPress’ TwentyTen Theme

Advertisement in Using HTML5 To Transform WordPress’ TwentyTen Theme
 in Using HTML5 To Transform WordPress’ TwentyTen Theme  in Using HTML5 To Transform WordPress’ TwentyTen Theme  in Using HTML5 To Transform WordPress’ TwentyTen Theme

Last year, WordPress launched arguably its biggest update ever: WordPress 3.0. Accompanying this release was the brand new default theme, TwentyTen, and the promise of a new default theme every year. Somewhat surprisingly, TwentyTen declares the HTML5 doctype but doesn’t take advantage of many of the new elements and attributes that HTML5 brings.

WordPress-HTML5 in Using HTML5 To Transform WordPress’ TwentyTen Theme

Now, HTML5 does many things, but you can’t just add <!doctype html> to the top of a document and get excited that you’re so 2011. Mark-up, as they say, is meaning, and HTML5 brings a whole bunch of meaning to our documents.

In a recent survey by Chris Coyier over at CSS-Tricks, almost two thirds of respondents said they would not use HTML5 in new projects. In a similar survey by Smashing Magazine the results were almost identical: only 37% of voters said they use HTML5. This is depressing reading. Perhaps developers and designers are scared off by cross-browser incompatibility and the chore of learning new mark-up. The truth is that with a pinch of JavaScript, HTML5 can be used safely today across all browsers, back to IE6.

WordPress seems to sympathize with the majority of CSS-Tricks’ readers. TwentyTen is a fine theme that already validates as HTML5; but in order to cater to users without JavaScript, it has to forgo a large chunk of HTML5 elements. The reason? Our old friend Internet Explorer doesn’t support most of them prior to version 9.

TwentyTenDefault in Using HTML5 To Transform WordPress’ TwentyTen Theme
The default TwentyTen WordPress Theme.

For example, you’ve probably already heard of the <section> and <article> tags, both of which are champing at the bit to be embedded in a WordPress template. But to use these HTML5 elements in IE8 (and its predecessors), you need JavaScript in order to create them in the DOM. If you don’t have JavaScript, then the elements can’t be styled with CSS. Turn off JavaScript and you turn off the styling for these elements; invariably, this will break the formatting of your page.

I assume that WordPress decided to exclude these problematic tags so that its default theme would be supported by all browsers — not just those with JavaScript turned on.

While I understand this decision, I also think it’s a mistake. Three core technologies make the Web work: HTML, CSS and JavaScript. All desktop browsers support them (to some degree), so if any one of them off is disabled the user will have to expect a degraded experience. JavaScript is now fundamental to the user experience and while we should support users who turn off JavaScript, or have it turned off for them and have no chance to turn it on again as they don’t have the right to do so, I question just how far we should support them.

Why Using JavaScript Makes Sense

Yahoo gives compelling evidence that less than 1.5% of its users turn off JavaScript. My own research into this, ably assisted by Greig Daines at eConversions, puts the figure below 0.5% (based on millions of visitors to a UK retail website).

Whilst it’s true that JavaScript should be separated from a site’s content, design and structure the reality is no longer black and white. I strongly believe that the benefits and opportunities HTML5 brings, together with related technologies such as CSS3 and media queries (both of which sometimes rely on JavaScript for cross-browser compatibility), is more than enough reason to use JavaScript to ‘force’ new elements to work in Internet Explorer. I am a passionate advocate for standards-based design that doesn’t rely on JavaScript; HTML5 is the one structural exception.

Yes, we should respect a user’s decision to deactivate JavaScript in their browser. However, I don’t believe that this is a good enough reason for not using modern technologies, which would provide the vast majority of users with a richer user experience. After all, in the TwentyTen example, if the theme had HTML5 tags in it, everything would look fine in modern browsers (latest versions of Safari, Firefox, Opera, Chrome and IE9), with or without JavaScript.

If the browser is IE6 – IE8, and JavaScript is turned off, then users would see the content but it will not be styled correctly. If the content would not be displayed at all, we’d have a completely different discussion. If you are still not convinced, I will briefly discuss another option for those who absolutely must support users with JavaScript turned off.

To make TwentyTen play fair with IE, I suggest Remy Sharp’s HTML5 shim or, if you want to sink your teeth into CSS3, Modernizr. Modernizr not only adds support for HTML5 elements in IE but also tells you which CSS3 properties are supported by the user’s browser by adding special classes to the <html> element.

Mordernizr in Using HTML5 To Transform WordPress’ TwentyTen Theme
Mordernizr.js

So, let’s assume you’ve rightly banished non-JavaScript users with a polite message in a <noscript> tag. We can now start tinkering under the hood of TwentyTen to bring some more HTML5 to WordPress.

Upgrading To HTML5

TwentyTen gets a number of things spot on. First of all, it declares the right doctype and includes the abbreviated meta charset tag. It also uses other semantic goodness like Microformats and great accessibility features like WAI-ARIA. But we can go further.

Important notes:

  • I am referencing the HTML generated at http://wp-themes.com/twentyten/, rather than the simple “Hello Worldâ€� clean installation of WordPress 3.
  • For this article, I’ll be editing the files directly in the /wp-content/themes/twentyten/ directory. I’ve provided all the updated HTML5 theme source files for you to download from TwentyTen Five.
  • Line numbers may change over time, so when I reference one, I’ll usually say “on or around line…â€� The version of WordPress at the time of writing is 3.0.4.

Articles

One of the more confusing parts of the HTML5 spec is the <section> and <article> tags. Which came first, the chicken or the egg? The easiest way to remember is to refer to the specification. The HTML5 spec may be dry at the best of times, but its explanation of articles will always point you in the right direction:

The article element represents a self-contained composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication.

If the piece of content in question can be, and most likely will be, syndicated by RSS, then there’s a good chance it’s an <article>. A blog post in WordPress fits the bill perfectly.

On the TwentyTen home page, we get the following HTML:

<div id="post-19">
…
</div>

Semantically this means very little. But with the simple addition of an article tag, we’re able to transform it into mark-up with meaning.

<article id="post-19">
…
</article>

Note that we retain the id to ensure that this <article> remains unique.

To make this change in the TwentyTen theme, open loop.php, which is in /wp-content/themes/twentyten/. On or around line 61, you should find the following code:

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

We’ll need to change that <div> to an <article>, so that it reads:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

And then we close it again on or around line 97, so that…

</div><!-- #post-## -->

… becomes:

</article><!-- #post-## -->

There are also instances on lines 32, 101 and 124. Opening some of the other pages in the theme, for example single.php, and making the same change is worthwhile. Thus, line 22 in single.php would change from…

<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

… to:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

And line 55 would change from…

</div><!-- #post-## -->

… to:

</article><!-- #post-## -->

So far, so good. These are simple changes, but they already serve to overhaul the semantics of the website.

Time and Date

According to the HTML5 spec:

The <time> element either represents a time on a 24-hour clock, or a precise date on the proleptic Gregorian calendar, optionally with a time and a time-zone offset.

This means we can give the date and time of an article’s publication more context with HTML5’s <time> tag. Look at the code that WordPress generates:

<a href="http://wp-themes.com/?p=19" title="4:33 am"
rel="bookmark"><span>October 17, 2008</span></a>

We can add meaning to our mark-up by transposing this to:

<a href="http://wp-themes.com/?p=19" title="4:33 am"
rel="bookmark"><time datetime="2008-10-17T04:33Z"
pubdate>October 17, 2008</time></a>

This time is now machine-readable, and the browser can now interact with the date in many ways should we so wish. I’ve also added the boolean attribute pubdate, which designates this as the date on which the article or content was published.

Time in the datetime attribute is optional, but because WordPress includes it when you post an article, we can too. Implementing this in TwentyTen requires us to dig a little deeper. In loop.php, the following function on or around line 65 calls for the date to be included:

<?php twentyten_posted_on(); ?>

To make our HTML5 changes, let’s head over to /wp-content/themes/twentyten/ and open functions.php. On or around line 441, you’ll see this:

function twentyten_posted_on() {
printf( __( '<span>Posted on</span> %2$s <span>by</span> %3$s', 'twentyten' ),
'meta-prep meta-prep-author',
sprintf( '<a href="%1$s" title="%2$s" rel="bookmark"><span>%3$s</span></a>',
get_permalink(),
esc_attr( get_the_time() ),
get_the_date()
),

If you don’t know what that means, don’t worry. We’re focusing on the sprintf function, which basically takes a string and inserts the variables that are returned by the three functions listed: that is, get_permanlink(), get_the_time() and get_the_date() are inserted into %1$s, %2$s and %3$s, respectively.

We need to change how the date is formatted, so we’ll have to add a fourth function: get_the_date('c'). WordPress will then return the date in Coordinated Universal Time (UTC) format, which is exactly what the <time> element requires. Our finished code looks like this:

printf( __( 'Posted on %2$s by %3$s', 'twentyten' ),
'meta-prep meta-prep-author',
sprintf( '<a href="%1$s" rel="bookmark"><time datetime="%2$s"
pubdate>%3$s</time></a>',
get_permalink(),
get_the_date('c'),
get_the_date()
),

I’ve included get_the_date() twice because we need two different formats: one for the <time> element and one that’s displayed to the user. I’ve also removed title="[time published]" because that information is already included in the <time> element.

For more details on WordPress’ date and time functions, check out:

Figures

A figure—for our purposes at least—is a piece of media that you upload in WordPress to embed in a post. The most obvious example would be an image, but it could be a video, too, of course. WordPress 3 is helpful enough to add captions to images when you first import the images, but it doesn’t display those captions using the new HTML5 <figure> and <figcaption> tags.

The spec defines <figure> as follows:

The figure element represents a unit of content, optionally with a caption, that is self-contained, that is typically referenced as a single unit from the main flow of the document, and that can be moved away from the main flow of the document without affecting the document’s meaning.

And it defines <figcaption> like so:

The figcaption element represents a caption or legend for the rest of the contents of the figcaption element’s parent figure element, if any.

Currently an image with a caption is rendered like this:

<div class="wp-caption" style="width: 445px;"><img alt="Boat"
src="http://wpdotorg.files.wordpress.com/2008/11/boat.jpg"
title="Boat" width="435" height="288" />
<p class="wp-caption-text">Boat</p>
</div>

Boat in Using HTML5 To Transform WordPress’ TwentyTen Theme
A WordPress image with a caption.

Changing this HTML to include HTML5 elements requires us to first look at media.php in the /wp-includes/ directory, where this code is generated. On or around line 739, you’ll find:

return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">'
. do_shortcode( $content ) . '<p>' . $caption . '</p></div>';

To upgrade this to HTML5, we need to define a new function that outputs our <figure>-based HTML and assign this function to the same shortcode that calls img_caption_shortcode(). I’ve done this in /wp-content/themes/twentyten/functions.php by adding the following to the bottom of the file:

add_shortcode('wp_caption', 'twentyten_img_caption_shortcode');
add_shortcode('caption', 'twentyten_img_caption_shortcode');

function twentyten_img_caption_shortcode($attr, $content = null) {

extract(shortcode_atts(array(
'id'    => '',
'align'    => 'alignnone',
'width'    => '',
'caption' => ''
), $attr));

if ( 1 > (int) $width || empty($caption) )
return $content;

if ( $id ) $idtag = 'id="' . esc_attr($id) . '" ';

  return '<figure ' . $idtag . 'aria-describedby="figcaption_' . $id . '" style="width: ' . (10 + (int) $width) . 'px">'
  . do_shortcode( $content ) . '<figcaption id="figcaption_' . $id . '">' . $caption . '</figcaption></figure>';
}

First, we point the shortcodes for wp-caption and caption to our new function twentyten_img_caption_shortcode(). Then, we simply copy the original function from media.php, and change the last few lines to include our <figure> element. This now renders our boat.jpg example from above like so:

<figure id="attachment_64" style="width: 445px;">
<a href="http://localhost/wp-content/uploads/2010/07/boat.jpg">
<img title="boat" src="http://localhost/wp-content/uploads/2010/07/boat.jpg"
alt="Screenshot" width="435" height="288" aria-describedby="figcaption_attachment_64"></a>
<figcaption id="figcaption_attachment_64">Boat</figcaption>
</figure>

The Comments Form

One of the biggest improvements introduced in HTML5 is how form fields work and respond to user input. We can take advantage of these changes by using HTML5 form elements in the default WordPress comments form in three ways:

  1. We can set the text-input type to email and url for the relevant fields. This not only more accurately describes the input field, but also adds better keyboard functionality for the iPhone, for example.
  2. We can add the boolean attribute required to our required form fields. This goes beyond WAI-ARIA’s aria-required='true' because it invokes the browser’s own required behavior.
  3. We can add placeholder text to our form fields, a popular JavaScript method that is now handled in-browser. Placeholder text allows you to go into more detail about what information is required than a form label generally allows.

Before adding HTML, a typical comment input field might look like this:

<label for="email">Email</label> <span>*</span>
<input id="email" name="email" type="text" value=""
size="30" aria-required='true' />

After our HTML5 changes, it would look like this:

<label for="email">Email</label> <span>*</span>
<input id="email" name="email" type="email" value=""
size="30" aria-required='true'
placeholder="How can we reach you?" required />

To make these improvements in the code, we need to do two things. First, we need to change the HTML for the default fields (name, email address and website URL), and then we need to change it for the comment’s <textarea>. We can achieve both of these changes with additional filters and custom functions.

To change the HTML for the default form fields, we need to add the following filter to the bottom of functions.php:

add_filter('comment_form_default_fields', 'twentytenfive_comments');

And then we have to create our custom function twentytenfive_comments() to change how these fields are displayed. We can do so by creating an array containing our new form fields and then returning it to this filter. Here’s the function:

function twentytenfive_comments() {

$req = get_option('require_name_email');

$fields =  array(
'author' => '<p>' . '<label for="author">' . __( 'Name' ) . '</label> ' . ( $req ? '<span>*</span>' : '' ) .
'<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30"' . $aria_req . ' placeholder = "What should we call you?"' . ( $req ? ' required' : '' ) . '/></p>',

'email'  => '<p><label for="email">' . __( 'Email' ) . '</label> ' . ( $req ? '<span>*</span>' : '' ) .
'<input id="email" name="email" type="email" value="' . esc_attr(  $commenter['comment_author_email'] ) . '" size="30"' . $aria_req . ' placeholder="How can we reach you?"' . ( $req ? ' required' : '' ) . ' /></p>',

'url'    => '<p><label for="url">' . __( 'Website' ) . '</label>' .
'<input id="url" name="url" type="url" value="' . esc_attr( $commenter['comment_author_url'] ) . '" size="30" placeholder="Have you got a website?" /></p>'

);
return $fields;
}

You can see here that each element in the form has a name in the array(): author, email and url. We then type in our custom code, which contains the new HTML5 form attributes. We have added placeholder text to each of the elements and, where required, added the boolean required attribute (and we need to check if the admin has made these fields required using the get_option() function). We’ve also added the correct input type to the inputs for author, email address and website URL.

Finally, we need to add some HTML5 to the <textarea>, which is home to the user’s comments. We have to use another filter here, also in functions.php:

add_filter('comment_form_field_comment', 'twentytenfive_commentfield');

We follow this with another custom function:

function twentytenfive_commentfield() {

$commentArea = '<p><label for="comment">' . _x( 'Comment', 'noun' ) . '</label><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true" required placeholder="What\'s on your mind?"    ></textarea></p>';

return $commentArea;

}

This is more or less the same as the default <textarea>, except with placeholder and required attributes.

You can control exactly which fields appear in your form with these two filters, so feel free to add more if you want to collect more information.

Although relatively simple, these changes to the comment form provide additional (and useful!) features to users with latest-generation browsers. Look in Opera, Chrome (which doesn’t yet support required) or Firefox 4 to see the results.

Header, Navigation and Footer

We finally get around to inserting the new <header>, <nav> and <footer> elements. Currently, the code in /wp-content/themes/twentyten/header.php looks more or less like this:

<div id="header">
<div id="masthead">
<div id="branding" role="banner">
…
</div><!-- #branding -->

<div id="access" role="navigation">
…
</div><!-- #access -->
</div><!-- #masthead -->
</div><!-- #header -->

It doesn’t take a genius to see that we can easily make this HTML5-ready by changing some of those divs to include <header> and <nav>.

<header id="header">
<section id="masthead" >
<div id="branding" role="banner">
…
</div><!-- #branding -->

<nav id="access" role="navigation">
…
</nav><!-- #access -->
</section><!-- #masthead -->
</header><!-- #header -->

You can see that we’ve left the WAI-ARIA role of navigation assigned to the nav element—simply to offer the broadest possible support to all browsers and screen readers.

I have replaced the #masthead div with a <section> because all of the elements in this area relate to one another and are likely to appear in a document outline. It seems you could delete this section altogether and just apply 30 pixels of padding-top to the header to maintain the layout. I’ve maintained the elements’ ids in case more than one of each are on the page—multiple headers, footers and navs (and more) are all welcome in HTML5.

While we’re editing the header, we can introduce the new <hgroup> element. This element enables us to include multiple headings in a section of our document, while they would be treated as just one heading in the document outline. Currently, the code on or around line 65 in header.php looks like this:

<?php $heading_tag = ( is_home() || is_front_page() ) ? 'h1' : 'div'; ?>
<<?php echo $heading_tag; ?> id="site-title">
<span>
<a href="<?php echo home_url( '/' ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a>
</span>
</<?php echo $heading_tag; ?>>
<div id="site-description"><?php bloginfo( 'description' ); ?></div>

We can edit this to include the <hgroup> tag, and also change <div id="site-description"> to an <h2> element:

<hgroup>
<?php $heading_tag = ( is_home() || is_front_page() ) ? 'h1' : 'div'; ?>
<<?php echo $heading_tag; ?> id="site-title">
<span>
<a href="<?php echo home_url( '/' ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a>
</span>
</<?php echo $heading_tag; ?>>
<h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
</hgroup>

In /wp-content/themes/twentyten/footer.php, we have:

<div id="footer" role="contentinfo">
  <div id="colophon">
  …
  <div id="site-info">
    <a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
    <?php bloginfo( 'name' ); ?>
    </a>
  </div><!-- #site-info -->

  <div id="site-generator">
  …
  </div><!-- #site-generator -->

  </div><!-- #colophon -->
</div><!-- #footer -->

We can easily edit this to include a <footer> and another <section> element:

<footer role="contentinfo">
<section id="colophon">
…
<div id="site-info">
<a href="<?php echo home_url( '/' ) ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
<?php bloginfo( 'name' ); ?>
</a>
</div><!-- #site-info -->

<div id="site-generator">
…
</div><!-- #site-generator -->

</section><!-- #colophon -->
</footer><!-- #footer -->

JavaScript and CSS

As mentioned, we should include an HTML5 shim or Modernizr.js to make sure that all of our new elements render correctly in Internet Explorer prior to version 9. I added the following line to header.php:

<script src="<?php bloginfo('stylesheet_directory'); ?>/js/Modernizr-1.6.min.js"></script>

A couple of things to note here. First, we no longer need type="text/javascript" because the browser will assume that a script is JavaScript unless it’s told different. Secondly, we have to use the WordPress bloginfo() function to point the source URL to our theme directory.

Although we are including Modernizr partly to make sure that IE can deal with the new HTML5 elements, I am serving it to all browsers because of the CSS3-checking functionality it provides.

In style.css, we need to make sure that our HTML5 elements have a display: block attribute, because some older browsers will treat them as inline elements. For our purposes, the following line at the top of the CSS file will do:

header, nav, section, article, aside, figure, footer { display: block; }

While we’re talking about CSS, remember that we can now remove type="text/css" from our <link> tags. The simplified code looks like this:

<link rel="stylesheet" href="<?php bloginfo( 'stylesheet_url' ); ?>" />

That should be enough for now. Remember, though, that changing the structure of the page by replacing older HTML elements with new ones might require some additional CSS.

We should let the small minority of users know that we’ve stopped supporting browsers that have JavaScript turned off. A polite message just below the opening <body> tag in header.php should suffice:

<noscript><strong>JavaScript is required for this website to be displayed correctly. Please enable JavaScript before continuing...</strong></noscript>

Add some very basic styling in style.css to make this message unmissable.

/* A message for users with JavaScript turned off */
noscript strong {
display: block;
font-size: 18px;
line-height:1.5em;
padding: 5px 0;
background-color: #ccc;
color: #a00;
text-align: center; }

Still Not Convinced? A Cross-Browser Alternative

There is another option for those of you who absolutely must support users with JavaScript turned off, as suggested by Christian Heilmann. Simply wrap your HTML5 elements with divs which share the same ID name. For example:

<article id="post-123">
...
</article>

becomes

<div class="article">
<article id="post-123">
...
</article>
</div>

Then it’s just a case of adding .article to your article CSS definition. It might look like this:

.article,
article { display: block; background-color: #f7f7f7; }

It’s worth noting that this adds another layer of markup to your code which isn’t needed for most users. I’d only recommend it if non-JavaScript users are a significant proportion of your users and/or sales.

Final Thoughts

TwentyTen was a huge step forward for WordPress; and as a piece of HTML, it is a beacon of best practice. By including some simple JavaScript, we can now open up the theme to the world of HTML5—and the additional meaning and simpler semantic code that it offers.

While we’ve addressed a good number of new HTML5 elements in this article, it really is just a starting point and you can add many more yourself. For example, you could add headers and footers to individual posts, or you might like to add the new <aside> element. Let us know your ideas and how you get on with implementing them in the comments below!

Download TwentyTen With HTML5

To complement this article, I have created a new version of TwentyTen, with the HTML5 elements we have discussed. Download this theme from TwentyTen Five.

Twentyten-five in Using HTML5 To Transform WordPress’ TwentyTen Theme

Other Resources

You may be interested in the following articles and related resources:

(al) (vf) (ik)


© Richard Shepherd for Smashing Magazine, 2011. | Permalink | Post a comment | Smashing Shop | Smashing Network | About Us
Post tags: ,


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress