Designing Responsive Web Experiences

Session 517 WWDC 2014

As your user base grows, so will the variety of devices you'll need to support. People expect modern web sites to be fast, visually appealing, and rich functionally, regardless of a device's performance characteristics, resolution or size. Learn how to use the latest web technologies in WebKit and Safari to create engaging, attractive, and adaptive layouts across all devices.

[ Silence ]

Good morning, everyone.

Good morning.

Hey, [applause] it's great to see some hardcore web people here, especially on, you know, the morning after the beer bash.

So I know you're all hardcore if you're here.

And welcome to the Designing Responsive Web Experiences session.

My name is Casey.

And I'm Ted.

And today we're going to show you how you can build one website that's going to look great everywhere.

And by the way, any time that we say "website" during this session, we mean any web media.

I'm on the iBooks team.

And I'm on the WebKit team.

And we want both your digital books and your websites to look great everywhere.

So we don't have to tell you that your website is being viewed on a whole variety of different devices and screen sizes.

What we can do, though, is teach you some really easy techniques that you can use to ensure that your website looks great on all of these.

I want to be very clear, though.

What we are not going to talk about today is building multiple versions for each of these devices.

In fact, today's session, it is the antithesis of the mobile-specific site.

There will be no m.domainname here.

So instead, we're going to build one website that looks great on all of these.

And a site that has a design that can adapt and adjust to always look good on all of these different devices is usually referred to as a website that has a responsive design.

A responsive design, it's just-it's just a buzzword.

It just means that your website is sensitive to its environment, which will allow it to adapt and change and just simply always look good.

And so today, Ted and I are going to show you not only what a simple idea a responsive design is, but really how simple it is to implement.

We're going to look at responsive columns.

Columns are a really great way to both add some visual interest to your website as well as improve the legibility of your site.

We'll also teach you about font-relative units and how you can use them to make sure that your layout has fidelity at every font size.

And then Ted's going to show you how you can use CSS Shapes to wrap text around images, and we'll make sure that those images are Retina ready.

And for the larger design changes that we need to make, we'll use media queries.

And finally, the finishing touch will be hairlines, where we can really dive in deep and make use of those beautiful Retina screens.

So why are we talking about this anyway?

You know, WebKit does a really great job of making sure that your website looks just as great on the iPhone as it does on the desktop.

It just shrinks your site down and makes it fit on the phone screen.

And then the user can double tap or pinch to zoom in to make sure that they can read that text.

The text becomes larger that way.

And it looks great.

It's not a lot of work for you.

And WebKit does the same thing for more complex sites, like this one that Ted and I made.

It just shrinks all that formatting and layout down into one screen.

And that seems great, right?

Can you read that text?

Barely? At all?

Not really, and many mobile designers or website designers have looked at this and said, "Pshht, I can't have that.

I'm going to have to make a mobile-specific site."

You know, we get it.

You want your website to look great, and you want it to be clear and easy to read without your users having to double-tap and pinch to zoom in and pan around.

And some of you may be thinking, "Well, of course it doesn't look great.

You need to add a meta viewport," right.

And that's a great first step.

A meta viewport's going to make your text larger in relation to the screen size.

But the thing is is that your layout is still all tiny and shrunk down.

So now you've got these big words in a shrunk down layout, and it just it looks awful, right.

So lest you think, "OK, Casey, no, really, we're going to have to make a mobile-specific site now," please keep in mind that we're not building websites for just the iPhone, the iPad, the desktop.

And to prove this, if you were to look at our website on the desktop, looks great, right?

We designed it for this window size basically.

But if I shrink down the window, ooh, I've got the same problem here that I do on the phone.

So we need to make sure that we're building a site that looks great no matter what our window size.

So, so far I've laid out just a whole lot of no's.

I've said, "Well, you can't make a mobile-specific site.

Using a meta viewport isn't going to get you all the way there.

And you have to build a website that works for every single possible permutation on the desktop."

So what can we do?

Well, hold on.

Our goal here is to use some simple responsive design techniques.

And it seems like the best way forward is just to identify specific problems that we're seeing right now and just work through them one at a time.

Sounds good.

I mean, the first one that's obvious to me is that masthead up top becomes so tall on the phone that I have to scroll to see any content.

And the other thing is is those columns are just really skinny like so it's completely illegible.

And that caption on our galaxy is blowing right out of the image and covering our initial text there.

Yeah, that's pretty horrible.

Where do you think we should start?

I think we should start with the columns.

Those look really terrible.

OK, let's start with columns 'cause I personally really like columns.

I love that they add both a visual interest to my website and that they improve the legibility.

It's really the perfect combination of form and function.

And columns are great for this because they're able to divide up big blocks of text into more legible chunks.

So where I might've had a big block or really long lines of text, I'm now able to have very consumable size, right.

Now, the problem we ran into with our website and why those columns weren't looking good is because we defined a set number of columns that had to be there for every screen size, right.

So when our windows shrunk down, those columns had to become really narrow and we were only able to have a few words per line.

So to make your columns responsive, all we have to do is instead of defining a column count or a set number of columns on our page, we just define the column width.

So to give you an example of this, I have two web pages here, very simplified, of where one has the columns defined in column width, one has the columns defined by the column count, like Ted's and my site.

Now when I resize that window resize that window the page that we defined the column width we have two columns.

And we've maintained that legible width, whereas the column count had to shrink down like we saw before.

So responsive columns are really great, defining the column width is really great because WebKit will automatically add or eliminate columns as room becomes available or is removed.

And we recommend when you are defining your column width that you use a font-relative unit.

Font-relative units are really great because if your user resizes their text, the column's width will also resize to match that.

So give you a simplified example.

Here we have the alphabet, right.

There's five letters on that first line of the first column: A, B, C, D, and E.

Now, because my column's width is defined in a font-relative unit, when I make my text smaller, I will maintain those five letters across the top.

And the same thing goes with the number of words on your column.

You'll maintain a legible link of words.

So all of this great functionality, these responsive columns, it seems like you're getting a lot here, right?

It's just one CSS property.

You just define column width and define it with the font-relative unit.

In this case we're using 15 rem.

So to show you how great columns are in real time, here's Ted with a demo.

OK, thanks, Casey.

Here we are.

So here's this website that Casey and I built, and it's looking pretty great at this-wow, that scrolls really fast-at this window width.

But as you saw, when we make it more narrower, the columns start getting harder and harder to read until a point where you hit here and it's just very illegible.

So you can see up in the corner I have a little bit of JavaScript showing you what the window width is so I can make adjustments as necessary.

So as Casey suggested, let's try setting our column width instead of our column count.

So over here in Xcode, you can see I have the column count of 3.

Just kill that and replace that with setting the column width to 15 rem like Casey suggested.

We'll save that, we'll hit reload and nothing's changed.

Our window width is still wide enough to accommodate three columns like we had before.

But this time as we get more narrow, we'll hit a point-let's see where it happens-right, OK, here.

Right around 1100 pixels we drop down to two columns.

It's still really legible.

And, again, as we get even smaller, we'll hit a point right around 700 and some odd pixels where we go down to one column, which, even at the narrowest window width, is still a very legible amount of text.

I mean, we're not done; that sidebar still looks terrible.

But that's really all you have to do to get simple responsive columns with just a single property.

Let's dive a little bit more into the features of the CSS columns column module.

OK, so you've seen the column count and column width properties, which are pretty straightforward.

When you are laying out a page with columns, it's best to have some white space between the columns.

If you don't, the lines can run together and it can be really hard to read.

And this is controlled with the column-gap property.

You might want a decorative line inside that gap.

You can define such a line with the column-rule property, whose syntax is just like the border properties you're used to using already.

And finally, if you'd like an element to pop out of your columns and span across them, you can easily do this with the column-span property, which looks really great.

So to sum up, making responsive columns that adjust to a different environment is super easy.

CSS gets you a lot of that for free by using the column width property.

I want to expand a bit, though, on why we chose to use a font-relative unit there.

Font-relative units are exactly what they sound like.

They're CSS units that are defined in terms of your current font size or some other text metric that's related to font size.

And it's very common to use these to set the font size itself, but you could also use them for any part of your layout whose size should be proportional to the current text size.

An obvious example would be the margins around your paragraphs.

As font size increases, you'd like those margins to also increase in proportion to that.

And the big benefit here is that by using these units, your layout will automatically adjust to different font sizes.

Now, you set a font size, but your user might change it.

They could use Cmd+ and Cmd- or perhaps they've changed the minimum font size setting, which is very common for low-vision users.

So you should always make your layout adjust to a font size that you're not expecting.

There are four font-relative units in CSS.

There's the em, which I'm sure you're all very familiar with; it's very popular, very common on the web.

And an em is defined in terms of the font size of the current element, which may be inherited from its ancestors.

Less common is the ex, which is approximately half an em.

It's really supposed to be basically the height of a lowercase letter.

This is very useful when you're trying to size an element inside a line of text so that it looks natural next to the rest of the text in the line.

The ch is based on the width of the numeral 0, which may seem random.

That is a typical character width, and so you can use it for sizing an input element where you're expecting, say, 30 characters.

You can say 30 ch and it'll be approximately the right size.

And finally we come to the rem, which is the unit that Casey was using.

The rem is just like the em that you're already familiar with, but instead of being based on the font size of the current element, it's always based on the font size of the body, or the root element.

So why would you want to use rems instead of ems?

You're already using ems; they're great for you.

So here's a simple example.

I've got a simple website with a header, "Hello," and on the left I've sized it with ems and on the right I've sized it with rems.

OK, so far they're identical, everything works the same.

Well, a few months from now, I've made a change to my website.

I've added a container element that happens to have this header inside of it.

And because someone told me to use font-relative units, I went ahead and sized that font size with ems as well.

So what I expect to happen is this: I want nothing to change.

But if I had used ems for my header, what happens?

The browser says, "Oh, this font size is in ems.

OK, well, what's the parent font size?

Oh, that's in ems."

And it keeps looking up until it finds a concrete font size and then computes this sort of compound font size.

And so the result is something way bigger than I intended when I first sized that header a few months ago.

Unlike that, in the case of rems, it's always looking back to the body element.

It's skipping its whole ancestor chain, so I never have a different font size than I expected.

OK, so we've taken a quick look at font-relative units and why I think the rem is pretty great.

Let's take a look at our website and see where we are.

OK, it's looking pretty good.

Yeah, that's definitely better.

We definitely still have the sidebar there that is a significant issue.

But I think let's tackle that one later.

All right.

What do you want to do next?

Well, so what's kind of bothering me is all that white text around the moon, right, all that extra white space.

I just-I feel like we're not making a good use of the screen real estate, and it just feels kind of clunky.

Yeah, I mean, the whole point of adjusting our column width in the first place was to have nice, readable lines.

And our moon is really interfering with that.

We have these really narrow lines of text next to it.

Definitely.

So let's take a look at that.

So to simplify, here's our moon.

We've floated it in our column.

And those lines next to it, they're floating around the image element and they look really narrow.

Well, I don't have a whole lot of time to fix this, so the easiest thing is, you know, we could just not float the moon and that way there's no narrow lines next to it.

It looks pretty good, right?

OK, yeah, Ted, you could do that.

I have a feeling, though, that you have a much cleverer, easy solution to that.

And this just kind of feels like a copout.

OK, fair enough.

So with a new feature called CSS Shapes, which is available in Yosemite and iOS 8, we can actually flow that text around the curvature of the moon.

It'll look really great.

So what's going on here?

CSS Shapes, it's a simple feature that allows you to flow text around a floated element with an interesting shape or geometry.

So in this case a triangle or a circle, like our moon, or Casey's favorite, Mr. Pacman.

Go, Mr. Pacman.

So how can we use this for our moon?

So like we saw before, we have our moon element.

It's just an image element of course.

And we've floated it within our column.

Now, it just so happens that this image of the moon is on a transparent background.

And CSS Shapes has a great feature where you can provide it with an image and it will use the visible, or opaque, part of that image to define the shape.

You do this with one property.

The property is called shape-outside, and in this case we're providing it the image of the moon.

It'll look into the image data and say, OK, here's the opaque part.

And as you can see, our lines of text are now flowing around the edge of the moon.

It's that easy.

Pretty cool, right?

Of course.

It's that easy.

[ Applause ]

Of course it's that easy because I lucked out.

My moon is on a transparent background already.

But a lot of times it's not.

You have an image that's entirely opaque and you don't have the Photoshop skills to go in and fix it up; I certainly don't.

Actually, a lot of you do, I'm sure.

So what do I do now?

So as you can see, I still have that shape-outside property, but this is an opaque moon, so Shapes doesn't have anything to go on here.

Fortunately, we can also, in addition to using an image of a source of the shape data, we can simply use some basic geometric shapes as well.

And of course the moon, luckily for me, is a circle.

So what I want to do is somehow tell the CSS Shapes module to use this circle to flow the text around.

And I do that using the circle() function.

Pretty straightforward.

It takes one argument, the radius.

In this case, I used 50 percent because I wanted the diameter of the circle to be the full width of the image element.

And that's looking pretty good.

There are other predefined shapes.

Just to take one example, you can use an ellipse.

Of course, an ellipse with the same dimensions in x and y is just a circle, so I really haven't changed anything.

But you can get really interesting with this too.

There is a polygon function which allows you define a fairly arbitrary shape.

So as an example, I drew an octagon around my moon.

The polygon function takes just a sequence of x, y coordinates and, hey, that looks pretty great actually.

And all of this was still, again, with just one CSS property.

OK, cool. We see how easy it is to use CSS Shapes to get a really great visual effect that was basically impossible to do before.

What do you want to do next?

Well, let's take a look back at our website.

So now we have the text flowing around our moon really well, which I think looks much better.

The one thing that I'm seeing, though, is those images look a little fuzzy on the phone, don't you think?

I agree.

I mean, look at that galaxy.

Yeah. I definitely think that we need to make our site Retina-ready.

Yeah. It's all pixelated.

Yeah. That's not just having too many beers at the beer bash last night.

So let's provide a higher resolution image for this.

You know, in the past, at previous WWDCs, we've talked about how to Retinafy-I think that's a word, right, Retinafy?

Sure.

It's a word now; you can write it down.

We're going to talk about how to Retinafy your website so that you have some brilliant, clear images on all of your websites.

And in the past when we've talked about it, we've talked about how to use kind of alternatives to images, so, you know, one example of that was like instead of using an image for a gradient you should use a CSS gradient, right?

The one thing we haven't talked about, though, is how like what do I do with just just my photos?

Like if I have a website with all my photography, what do I do with that?

We haven't tackled the image element yet.

What the heck, right?

So new to OS X and iOS 8 we have Image Source Sets.

Image Source Sets let you really easily add both a standard resolution image and a Retina resolution image, and then WebKit will just magically pick the right one, depending on what type of screen your website's being viewed on.

And it looks kind of like this.

So here's my galaxy image on a standard screen.

It looks pretty good, but here it is on a Retina screen.

It's pretty pixelated.

So fortunately, it's very, very easy to fix this.

And all you have to do is just start with the image element.

So here's my image element.

It should look pretty familiar to most of you.

It hasn't really changed since the '90s, right?

But because I'm always look for an opportunity to text, I'm going to go ahead and walk you through it.

So our first attribute in there is our alt attribute.

Please always include it because anyone who's using a screen reader needs to understand what is going on in this big, beautiful image you've provided.

And then second, I have my source attribute, which is just the location of the image.

So to make this standard image element into an Image Source Set, all we have to do is add the source set attribute: srcset.

So inside my source set attribute is literally a set of images.

I have my standard galaxy.jpeg and my super-galaxy.jpeg for my Retina screens.

And the difference between those is this modifier of 1x for standard and 2x for Retina, right.

So then WebKit can then automatically understand which image is for which screen.

Now, some of who you are actually reading through my syntax might have noticed some redundancy in there.

Yeah. You're saying galaxy JPEG twice.

Yeah. So galaxy.jpeg, my standard resolution image, is in there two times.

And you might think, "Well, let's just ditch the source," right.

But browsers that do not understand srcset are not going to know what to do with that.

So for backwards compatibility, let's keep the src and instead we will back out or remove that 1x resolution image from the source set.

So that's like very little amount of markup, right.

With just this small amount of markup, we've made our website and our image element Retina-ready.

Image source sets are really great.

They load only the right image, so you're going to avoid that double download.

There's no additional CSS.

You don't have to go in there and muck around with your dimensions or anything like that.

And it's backwards compatible with just this little amount of syntax, this one attribute.

So, so far I've talked to you about image source sets in your HTML.

It just so happens that there is another feature that we talked about at WWDC in the past that has an incredibly similar name and an incredibly similar function.

So we're going to go over that real quick, too, so that you can understand when you use which and why.

So image source sets, which we just covered, are in your HTML, but image sets live in your CSS.

And they are intended for styling your website, like borders or background images.

So image sets, let's say I do have one of those background images that I want to make Retina-ready.

I'll just start with my background image.

You'll see I have my URL with my galaxy.jpeg.

And to make it into an image set, I add a second background image property.

And within it is the image-set() function.

And that function then contains both of my images.

It contains the galaxy JPEG modified with 1x and my super-galaxy JPEG with 2x.

And then WebKit from here will automatically select the right one.

And I'd like to point out that you do need to have both of your background image properties there for backwards compatibility.

So image sets, image source sets.

They're great, they're easy.

They make it super easy for adding both standard and Retina images.

WebKit will pick the right one.

Just remember that your HTML image source sets are for your content-those big, beautiful photographs we talked about-and your CSS image sets are for your style, so your background images, your borders.

So I think both are going to be a really great solution for your websites.

Should we see where we're at?

Yeah. Let's-well, that looks way better.

Really happy about that.

I was worried that maybe I had too much fun at the beer bash last night.

OK, so where are we now?

We've got our Retina image.

And we still have a bunch of basic layout problems on this page that we haven't addressed yet.

Yeah. Our Retina image looks nice, except that you can't really see it.

Right.

It's got that giant caption over it.

It's ridiculous.

Yeah.

So let's fix up some of our remaining layout problems by using CSS media queries.

And I'm sure a lot of you use these all the time.

So let's just jump right in and take care of these remaining issues.

OK, here we are again; this should look familiar.

You can see the text loading around that moon now.

It's looking pretty good.

I'm a big fan of that.

OK, let's see, and as you know, as we make our page narrower, the layout gets more and more crazy.

In particular, I don't like how the masthead of my page here is taking up so much vertical space.

This caption is really awkwardly overlapping my image.

In fact, it's blowing right out of it and overlapping the heading below it.

And then the sidebar is really, really narrow and hard to read.

So let's fix each of these.

I'll start with the header.

So as you can see up in the corner, like I mentioned, I have that handy bit of JavaScript to show me how wide my window is.

So where does the header start to go off?

It seems like between 650 and 700 pixels, somewhere around there, we hit multiple lines.

And as you saw earlier on the phone, we end up with like four lines of text.

So I want to adjust the size of my header somewhere around, what, 690 pixels or something.

OK, so let's do that.

To do this, I'm going to use the @media rule.

So here I have an @media rule.

This is the part of CSS where you can provide a media query, in this case a max-width of 675 pixels.

And then inside of braces you basically provide a whole style sheet of things you'd like to change at that point.

In this case, I'm finding that masthead header and adjusting its font size down.

OK, so we've made that change.

Let's refresh.

Nothing changed because this is wider than that breakpoint of 675 pixels.

So let's make our site more narrow, and there we go.

Our header got smaller, it looks great even here at this very narrow size.

Well, OK, next I think I'll take care of this caption.

So just like with the header, I need to figure out where it starts looking bad.

It looks great out here at two lines.

I'm still pretty happy with it here.

And it seems to be right around where it goes to four lines where that bottom right corner is intruding into my galaxy and really kind of ruining the mood.

OK, so where was that?

That seems to be between 700 and 750 pixels.

OK, so just like with my header I'll use an @media rule, this time with a max-width of 750 pixels.

And what I'm doing here is initially my caption is absolutely positioned so that it can be an overlay on top of my image.

And its width is set at 50 percent so that it takes up about half the size of the image, like so.

So in my media query here, I want to override both the position and width properties so that it will simply appear below the image and take up the full width of the column.

And that's it.

So we'll save and let me come out a little bit and refresh.

And as you can see, just like before nothing's changed because I'm still wider than that media queries test.

But as we get closer to the bad part, there it goes; it pops down.

It's quite legible below our image and doesn't interfere with it, no matter how narrow our window screen gets.

OK, cool. Let's take care of that sidebar.

That's I think the last bit that looked pretty bad at a narrow size.

So where does that get unreadable?

In this case, I feel like right around here is where the block quote inside my sidebar is getting to be, you know, one or two words per line.

It's really too narrow.

So let's make an adjustment around 800, 850 pixels.

By now I think you know the drill.

This adjustment is exactly like the other ones.

We have an @media rule for a width of 800 pixels.

Currently, this sidebar is floated over, so I'm disabling the float just like with my caption.

I'm resetting the width so it will automatically be the width of its container.

And I'm killing some of the margins that we had there so that the sidebar will be offset from the columns next to it.

So if we come back and refresh, still there.

But as we get smaller, there we go, the sidebar is popped in and is now in line with the rest of our document.

And even in the really, really narrow screen size this is starting to look pretty good.

OK, so let's talk a little bit more about media queries.

As you saw, we use media queries in CSS by using an @media rule, which takes a media query to test and then some CSS to apply when that media query matches.

So here, I'm fixing our caption like we saw earlier by using a max-width media query, and then I'm overriding the position and width properties.

This is in general how you use an @media rule.

You have some rules somewhere else in your style sheet and then you say, OK, but and sometimes I need to override those.

In all three cases, we used the max-width media query because we were adjusting for when things got narrower.

There are several other media queries that you'll often want to use when doing responsive design.

There's a corresponding min-width media query where you can adjust things as the site gets wider.

And also an exact-width media query.

When you're adjusting your site to be Retina-ready, in addition to using the features that Casey showed you earlier, you might need to make some layout adjustments.

And you can test for a Retina device by using the device-pixel-ratio media query, which, just like width, takes a min and max variance.

When adjusting your layout with a media query, there's a few things you should keep in mind.

First off, the @media rule is actually a very blunt instrument.

What you're doing is making an entire alternate style sheet that applies in certain circumstances.

You have to duplicate the selectors you're using in your default style sheet to override particular properties.

And as your site grows, this can lead to a really large maintenance burden.

You might double or triple or quadruple the size of your style sheet.

So instead, when possible, you should try to use CSS features that naturally adapt your site without having to duplicate all your work.

We saw two earlier: The column width property allowed us to adjust the number of columns magically basically without resorting to a media query.

And the image set function allows us to pick the right image for our display without having to use the device-pixel-ratio property media query.

And secondly, when I was adjusting our layout there, I was doing it experimentally.

I loaded my site, fiddled with my window width and found where each part of my layout went bad and then made adjustments for that width.

I didn't look up the dimensions of a particular screen on Wikipedia.

I let my content actually tell me where it needed to be adjusted.

This will make your content more resilient to an ever-increasing range of scenarios where it might be loaded.

OK, so we've made our final layout adjustments with some media queries.

There's just one little bit I wanted to address before we can call it a day.

And this is some of these borders on our site.

So you can see up top there we have this little byline of "This is the Friday edition of the Daily Space Digest," and we've got some borders around it.

And they look great on my laptop, but they're a little thick on my phone.

I made a 1 pixel border and I wanted it to be a 1 pixel border, but of course, as you already know, when I say 1 pixel in CSS, I don't actually get 1 pixel on my display.

The CSS pixel is defined to be a sort of abstract measurement that roughly corresponds to 1 physical pixel on a pre-Retina display.

But now, with the Retina device, a 1 CSS pixel actually contains 4 device pixels.

So what I want to do is sort of reach into the CSS pixel and make full use of each of those device pixels.

I want to draw hairline borders.

OK, so right now I'm drawing my border with 1 pixel in CSS.

And when that draws on a standard display, I get the thinnest line I could possibly get.

And on a Retina display, I get this line that's twice as thick as I actually want.

So what I want to do is really only use 1 row or column of device pixels to get this line.

So how do I do it?

Let's look at our CSS.

Here, I'm setting my border with 1 pixel.

I'm not the only one who's wanted hairline borders; a lot of you have too.

And I've got to say, some of the solutions people have come up with are amazing and horrifying.

Here's my favorite.

This is pretty brilliant.

It uses an inline SVG image and a data URL as your background image.

Everyone got that?

It's really easy to remember how to type this, as I'm sure you can see.

All right.

Let's cut this out; this is ridiculous.

And now, I'm really pleased to say that in Yosemite and iOS 8, WebKit has enabled a feature that we call subpixel layout.

Now, mostly, this won't affect what you're doing at all.

It's just a magical, under-the-hood improvement that just makes things a little bit better.

But we can take advantage of it to get the hairlines we want without having to do this sort of thing.

OK, how do we do it?

So here we have our 1 pixel for our standard display.

And now, just like we saw before with our media queries, we're going to check device-pixel-ratio to see, are we on a Retina screen?

We are? Great.

And all we're doing is saying we're on a Retina display, great, just use a half a pixel.

Remember, the CSS pixel is 2 device pixels in each dimension, so a half a pixel corresponds to that beautiful, thin device pixel.

And now I can actually read this and remember what I meant when I wrote it, so that's exciting.

And here we are.

I've got my retina iPad.

And if we use the magic of Keynote to zoom in on that, you can see those lines are as thin as they could possibly get.

Ooh, aah.

[ Laughter ]

Thanks Ted.

[ Applause ]

All right.

So our website now looks so much better minus our sad engineering design skills.

And it looks great on every device, and with very little markup.

Like how many lines of code did we do?

I think we actually only changed about 20 lines of code.

That's pretty good, right?

Yes? Thank you.

[ Applause ]

All we had to do was make our columns responsive.

We defined the width of our column instead of a column count.

We also designed our layout so that it was in font-relative units, which means that if our users change their font size, we are going to have fidelity to our layout.

Also, Ted showed you how to use CSS Shapes so that now we have the text flowing beautifully around the curvature of our moon, and both our galaxy and our moon image are Retina-ready.

Then, we also covered how to use media queries, our blunt instrument for making larger layout changes when necessary.

And the icing on the cake are those beautiful hairline borders that really reach into the retina screen.

So for more information, as always you can contact Apple Evangelism.

And check out our documentation in the Safari Developer Center and participate in the wonderful conversations over at our Developer Forums.

It's Friday morning, so our related session was of course earlier this week.

And if you missed it, definitely check out the video; it's really great.

And we've also talked about several things that have come up in previous WWDCs.

In 2012, we introduced the image-set function for CSS in a great talk that goes in extreme depth into how to make a content Retina-ready.

It's really, really wonderful.

And then last year, we introduced several new layout features, which we didn't go into here, like CSS Regions, Flexbox, and there's some really great advanced layout you can do in CSS that will make your site really great.

And please do check that out.

I know some of you traveled from quite far to be here.

I hope you have a safe travel home.

Thanks, everyone.

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US