Internet & Web • iOS, OS X • 50:12
Safari on iOS was the first browser to deliver web content that responded to gestures such as panning, double-tapping, and pinching. Now, many of the basic principles behind gesture-friendly layout and gesture recognition have been carried over to Safari on Mac OS X Lion. See how to make web content that already looks great even better by learning the concepts behind gesture-enabled web layout. Understand how scrollable content and fixed positioning works in zoom-able interfaces, learn best practices for handling overlay scrollbars, discover optimization that speed up back-forward navigation, and more.
Speakers: Beth Dakin, Vicki Murley
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
This is Understanding Layout and Gestures in Safari on iOS and Lion. I'm Beth Dakin, and I'm an engineer on the Safari and WebKit team. The devices on which we browse the web have evolved. iPads and iPhones go everywhere with us. We use them on extremely fast networks and on extremely slow networks.
And when we use them, we don't even interact with them with a mouse. These facts affect all of us as developers. For example, take the fact that there's no mouse. Web developers simply can't rely on hover effects the way they once did because hovering on an iPad just isn't the same as hovering on an iMac. But that's not to say that iMacs haven't evolved as well. This is Apple after all, and we're constantly innovating here. And our iMacs now have magic trackpads. Trackpads, of course, are still mice, but they have all of the power of multi-touch gestures built into them as well.
And with Lion, we've introduced evolved software that really harnesses the power of this new hardware. There are innovations in here that will affect the way we browse the web and will impact our web content. So today we're going to take a look at Safari on Lion and Safari on iOS, and we're going to peek under the hood and look at how WebKit behaves in these evolved environments. And along the way, we're going to give you some tips and tricks for how you can bring your web content into these new environments as well and have them really harness this new power.
So I mentioned WebKit briefly. You've probably heard a lot about WebKit already this week, but in case you haven't, WebKit is the engine that powers Safari. It's open source, and it's responsible for loading, parsing, interpreting, rendering, and managing web content in Safari. Not just Safari, though. WebKit's used a lot of places. It's used in many of the core applications on Mac OS X.
It's used on many more apps that you'll find in the Mac App Store, and it's used in tons of apps in the iOS App Store. WebKit is used in so many places these days because of its flexibility as a content rendering engine. As we make Safari and WebKit a better and better platform, we really want to work together with you as web developers so that we can deliver an amazing experience to end users.
So in that vein, we're going to cover three main topics today. First, we'll dive into a few meaty issues that really get to the heart of getting that pixel perfection on iOS, getting your layout just right. Then we'll talk about the new scrollbar redesign on Lion and how it impacts web content. And finally, we'll talk about the new multi-touch gestures on Lion and the gestures that we've always had on iOS.
The topics that we're covering today are things that just work and work beautifully almost all the time, probably 95% of the time or more. But we're talking about them anyway for two main reasons. First of all, sometimes you'll be in that 5% of the time where you'll see your web content interacting with these features in a way that's not exactly how you want it to. You'll hit some gotchas. And we want to be able to help you out of those situations. We think we have a few easy tips to get you out of those holes that you might find yourself in.
And secondly, sometimes you'll just want to craft a really custom experience built for the particular platform that you're on. And in those situations, we think you really need to understand some of these underlying issues. Then you can really use the tools like a master. So without further ado, I would like to invite my colleague, Vicki Murley, to the stage to talk to you about Safari on iOS.
Thanks, Beth. So, Safari on iOS. You might be developing a great Web application. Facebook is one company that delivers a native app, but also gives you a great experience when you visit their URL in Safari. Or you might be a strictly native application that is leveraging Web technologies inside of UI WebView.
So, regardless of which approach you're taking here, you might end up in some scenarios where the layout or behavior or other things just aren't quite exactly how you want them. So I'm going to address three of these areas today. The first is undesirable results for layout and behaviors. Things just aren't quite right.
The second is pixelated images on retina displays. And finally, I'm going to talk about fixed positioning. Many of you have been trying to get CSS fixed positioning working in your web content. You want that element to stay on screen as you're scrolling, and it hasn't been working for you. So I'm going to address that topic today.
So let's start by talking about these undesirable results for layout and behaviors. So what exactly do I mean here when I say that? Well, as the Safari Technologies evangelist, I get a lot of feedback from people like you. And some of the things that I've heard are, I have this empty space on the sides of my web page, or my web app doesn't fit the screen the way I want it to. Or maybe I've got it kind of fitting the screen the way I want it to, but I'm still seeing horizontal bounce, and I want to get rid of that.
And also, you know, double-tap and pinch gestures are great for web pages viewed in Safari, but I'm making a web app, and I want to disable those behaviors. So all of these problems or issues that I just mentioned can be solved by one key concept in Safari on iOS, and that is the viewport. So I'm going to spend a bit of time today explaining the viewport, how it works, and how it relates to your content.
So in Safari on iOS, we're looking at a web page here in Safari. The URL bar has been scrolled out of view. We have this first area, and I'm just going to call this the window. It's not the DOM window. I'm really just talking about this as a fixed area that you're peering through to look at the web content, sort of like a portal on a ship. Beth Dakin, Vicki Murley In the same area, on the same line, we also have what's called the viewport. And when we first load the web page, these two elements match each other. They're almost one on top of each other, matching.
So when users pinch to zoom to get a closer look at some web content, what happens is we still have that window that we're using to peer at the web content, but our viewport changes scale. The height and width values remain the same. It's really the scale factor that changes.
So since the viewport has gotten bigger, users can also pan the viewport right and left to view different parts of the page. And this also means that if Wikipedia was using fixed positioning to position its title and make it stick at the top of the page when users scroll, this element would be off-screen at this point. Because by definition, elements that use fixed positioning use the viewport as their containing block.
So that's the viewport on Safari on iOS. On the desktop, again, we have both of these elements. We have the window, and then we also have the viewport. The difference here is how users interact with the viewport. Instead of scaling it, users can actually change the size of the viewport as they resize a window in Safari. As they make it bigger, the content expands. As they make it smaller, Wikipedia has a flowable layout. So some of these elements are overlapping, and scrollbars appear to help us move right and left to view more of the content.
So to recap, in Safari on iOS, the viewport height and width values don't change. It's the scale factor that changes. Users scale and pan to view different parts of the page. In Safari on the Desktop, the viewport height and width values are adjustable by the user by resizing the window.
So, you know, you might have noticed I'm not using Lion screenshots here, and that's because, you know, this is what we were working with when we invented Safari on iOS. And one of the problems that we had to solve was how do we go from this layout, you know, existing web content designed to fit into this model where you can resize the viewport yourself, to this, where we want users to be able to scale, pan, etc.
Well, the answer is actually pretty straightforward. What we do is we assume a width of 980 pixels for the content, and then we scale that down to 320 pixels in the case of iPhone. So this means that our default viewport settings have a width of 980 pixels and a scale factor of 320 divided by 980, which is about 0.32653, and probably some extra numbers there as well.
So this is why you sometimes see this underutilized white space on the edges of your content, because we're assuming that you need 980 pixels to lay out all of your content. Really, sometimes you don't need all of that space. So here, looking at the Wikipedia page, we have some unused white space on the right and left. And then we also have this area at the bottom with all the different languages that I can switch between for Wikipedia. The main content that I really care about is in that central area around that sphere.
So how can we tell Safari on iOS that we only need, we don't need 980 pixels, we need a different amount of pixels to layout our content? Well, the answer is through the viewport tag. So here is what it looks like. It's a meta tag. The name is viewport, and you can set the content value to a width. And here I'm setting the width equal to 540.
So I actually came up with that value because I, you know, downloaded the Wikipedia site and kind of eyeballed how much space I think was needed to lay out that central area, and it was about 540 pixels. And just adding this one tag to the Wikipedia page took me from something that looked like this to this.
And, you know, none of our content is lost. We still have, you know, if we scroll down, we still have all those languages that people might need to switch between. But we're really focusing on the content. We've told Safari on iOS that all we need is 540 pixels to layout our content.
So we've seen what setting the width means, but the viewport is configurable in other ways as well. So besides setting the width, you can set the height. You can set the initial scale. We talked about what the default initial scale is, but you can set that yourself as well.
And you can set these things in combination. So here I'm setting a width of 540, a height of 800, and initial scale of 2. So when you do something like the last example here, set multiple values within one viewport tag for your page, you should be aware that when you set a single viewport parameter, the others are inferred. So for example, if I set the width to 540, the height and initial scale are inferred. You can get that fine-grained control by setting multiple values altogether, comma delimited.
For me, though, it's hard to kind of imagine, it's hard to mentally get your head around what it might mean to have a width of 540 and a height of 800 and an initial scale of 2. Like, off the top of my head, I'm not sure what exactly that would look like on that Wikipedia page. So, a lot of the time, I find myself just setting the width and letting all the other values be inferred. And that seems to work really well for web content, both for web apps, web pages, and inside of UI WebView.
So you might have tried setting the viewport tag already, and you might run into this thing where you get a little bit of bounce to the right and left. So basically, that's a cue that your content doesn't actually fit the screen exactly. You might have something like this, where you've set the viewport width to 300 pixels, then you have a div inside the body that's also 300 pixels. So you're thinking, OK, these should match.
I shouldn't have any extra horizontal space. But the fact is that you do. If you've ever opened up a simple web page like this one in the Web Inspector on the desktop, you may have seen this field here, User Agent Style Sheet. So all web browsers have their own style sheet that's part of the web browser that defines the default styling for HTML elements like the body tag. So here, we see that the default styling for Safari is a margin of 8 pixels.
So even though we have set our width to 300 for both the viewport and inside our main content, we're actually getting an extra 8 pixels on each side. And that's why we're getting this tiny bit of horizontal bounce to the right and left in a web app. This is really easy to fix. You can just set the CSS style for the margin to zero pixels, and that will completely solve your problem.
Okay. So we've seen lots of ways to customize the viewport for your layout, but what about those behaviors that we talked about, double tapping and pinching to zoom? You want your web app to fit the screen and not be zoomable. Well, the viewport tag comes to the rescue again. We can set a value user scalable equal to no. And that will disable all of the zooming, double tapping to zoom, et cetera, for your web app.
Two other parameters for the viewport that are related to scaling, you can set the minimum scale and the maximum scale as well. So, just to recap, you know, there are several different ways to configure the viewport related to both how things layout and how things behave. They have their own default values, and they have minimum and maximum values as well.
So that kind of covers this class of problems, undesirable results for layout and behaviors. Let's talk for a minute here next about pixelated images on retina displays. So the iPhone 4 Retina Display, you know, it has sort of the same dimensions as an older iPhone. It's 320 pixels wide by 480 pixels tall.
Or you might say 320 units wide by 480 pixels tall. And on an older iPhone, each of those units corresponds to one pixel. On an iPhone 4 Retina Display, each of those units corresponds to four pixels, a two-by-two little box. So that's how we get the text super sharp.
This means that sometimes your content can look a little grainy. And there's a couple different solutions that you can use to make things look perfect in your web pages. The first is for your graphics, instead of using an image, you could use a technology called SVG. So it's a declarative API for drawing and animating shapes, lines, arcs, and more. It's drawn by the web browser, so it looks good even if users zoom in to the maximum zoom level. your content is still going to remain sharp.
So with the advent of these new devices that people are able to zoom in on super close to the text, a lot of people are adopting SVG for content that they really care about. So the New York Times is a great example. They've chosen to draw their logo with SVG. So here's an actual screenshot of zoomed in on the New York Times. Other elements on the page look a little bit grainy, but the logo remains sharp, even though I'm completely zoomed in.
Okay, so that's for graphics. You could use SVG. What about just plain old images? Well, there's a couple different solutions here as well. So one is if you have just a simple web app with a couple images, something that you could do is, like, we have this image. It's 300 pixels by 450 pixels wide.
One approach you can take is to actually create an image that's double the size. So now we have an image that's 600 pixels by 900 pixels. And then set the height and width of that image to half of those dimensions in CSS. So here, again, we're going to be packing four pixels into every unit instead of just one pixel every unit.
You're probably familiar already with CSS media queries. They've been around for a long time to do things like provide different layouts if your web page is viewed on a screen versus a printed version of your website. So these are probably some media queries that you're familiar with. There are additional media queries to measure or check the device width. So here's a media query for iPhone and one for iPad.
And media queries have a new value, and that's device pixel ratio. So if we wanted to look for an iPhone 4 retina display, we could use this expression in our media query, device pixel ratio. There's variants of it, of course, min device pixel ratio and max device pixel ratio.
So in my second example here of a media query, I'm querying for a device that is 320 pixels wide and has a min device pixel ratio of 2, because I want to load this image for iPhone 4 retina displays and any displays in the future that have an even greater device pixel ratio.
So that's in your style sheet. You know, you can load different background images for different devices and different displays, but you can also evaluate a CSS media query from JavaScript. So we can check here for the style media property and call the match medium function on that, and then we're just passing the exact same CSS media query that we saw before on the previous slide that we had in our declarative CSS.
If that evaluates to true, I can set the source of my image to my retina, my JPEG that I want to use for the retina display, and then I'm going to just append that image to the document. Or you could insert it anywhere, really. Okay, so that solves kind of our second class of problems, pixelated images on retina displays. Let's move on to this last one, flaky fixed positioning.
So you've probably all seen different websites that use CSS positioning. Here's one. It's united.com, booking, travel via frequent flyer miles. And the code that may show this bar at the bottom of the screen as I scroll, we're setting position to fixed and bottom to zero pixels. So on the desktop, as I scroll, that bar is going to stay at the bottom of the screen. But if I have the same web page, the same exact code on iPad, as I scroll, the bar is going to scroll along with the content. And that is not exactly what I want.
There are a lot of JavaScript libraries out there that are designed to work around this problem. Entire JavaScript libraries are designed to help you keep an element on screen as you scroll. So we know it's something that people have been really interested in. While these libraries are great, they have a shortcoming in that scroll events are only emitted once a user lifts their finger from the screen. So as their finger is down and they're moving to scroll up and down, scroll events are not firing. So they can really only move that bar into place once the user has lifted their finger from the screen.
So to show you how to make this work, CSS fixed positioning in Safari on iOS, I'm going to invite Beth Dakin back up to the stage, and we're going to do a quick demo. All right. So we have this website. It was created last year by one of our engineers, Jing Jin, for her awesome session on CSS last year. It was pretty much equally awesome this year. So if you didn't go, you should catch it on video.
But I have these elements. I have this badge here. I have this navigation bar at the top and this sticky note. And right now, these are all using absolute positioning. So as I scroll, they're scrolling along with the page. So I'm just going to go ahead into my CSS file here, and I'm going to change these to use fixed positioning.
OK, so I've changed the navigation bar at the top, the sticky note, and the badge to all use fixed positioning. So I'm going to save that file. Reload this page. And now, when I scroll, those elements are staying put. They are not moving with the rest of the content. So Beth, will you show us what that looks like on an iPad? BETH DANKIN: Sure.
Let me reload the page here so I get the latest and greatest version. I'm going to scroll, but I'm not getting any of the fixed position awesomeness that you just added to the desktop. Oh, well, you know what? I actually have another iPad here to show you. All right. Let me just also reload the page to make sure that I have the latest version. And now I'm going to scroll.
How did you do that, Vicki? How is your iPad different than my iPad? Well, the iPads, you know, they're pretty much exactly the same. They're both iPad 2, so they're both pretty awesome. But this iPad has something different about it, and that is that it's using Safari on iOS 5.0. So, as you may have noticed, if you've downloaded the seed already, fixed positioning is now working in Safari on iOS. So, it definitely deserves applause.
So that looks great when you're scrolling, but what does it look like when you zoom in? That is a really good question, Beth. You know, we have these zoomable interfaces now. How do we account for the fact that people are going to want to zoom in? What's going to happen to those elements? Let me show you.
OK. OK. So I'm going to zoom in. And as you can see, the elements are growing in size and they're also staying put. So we have some Z-ordering so that the badge is behind our content in the middle here and the sticky is in front of that. But as I pinch to zoom in, they're getting bigger.
But then at some point, Safari notices that if I had these two things that are fixed on the side and they kept just growing in size and stayed put where they were, then they would start overlapping. So what we do is we start moving those a little bit off of the page. So if you watch this really closely, like here on the badge, watch the H.
It's still on screen, still on screen. Now we've reached a threshold. We're Safari saying, OK, it's getting too close. These might start overlapping. I'm going to start moving things off the screen. And that's basically what happens. So they're still accessible but not overlapping. And we think that this is going to be something that works great for existing web content out there. The web is big and there's lots of content. And any new content that you guys might create. So I hope you enjoy it because it was pretty tricky to get going.
So about this CSS fixed positioning that's new in iOS 5, something, you know, just watch for kind of overlapping elements. We had some Z ordering there, so some of our elements were overlapping. Our content in the middle was semi-transparent, so it didn't matter, but test your content to make sure that it works well with this new model.
So you might be saying to yourself, oh my gosh, this is great. I get to make that web app that I always wanted with that element fixed to the top or bottom, and it's going to be super great. Well, you could use that approach, but there's a second approach that I think might be even better for that specific use case, a web app that fits the screen and has a menu fixed to either the top or bottom. And that is to use an overflow scroll area.
So the code for doing that might look something like this. I have a header. It's 320 pixels wide. I made it 56 pixels tall. I gave it a background color. And then I have my content. And that's got the overflow style set to scroll. And that has a height of 300 pixels.
Then in my HTML, I'm just going to order those elements one after another. The heading that I want fixed to the top of the screen followed by the content below it. So you might be saying to yourself, overflow scroll. You've got to be kidding me. That content is only going to be scrollable with two fingers. It takes a two-finger gesture to scroll content in Safari on iOS.
Well, I'm happy to tell you that in iOS 5, overflow scroll areas are no longer going to require two fingers to scroll the content. So... One might say that we've given one finger to two-finger scrolling. In the scene that you have, it's looking pretty good, but we're going to be continuing to improve it in other ways as we get closer and closer to shipping iOS 5. So please watch the release notes for more information about this feature.
You know, as we continue to improve this, there's something that makes this a really attractive thing if you're trying to make a really great-looking web app, and that is the scrollbar behavior. So if you keep your eye on this area, if I were just using an element with fixed positioning, the scrollbar would show up at the top and then overlap, you know, my heading at the top. If I'm using an overflow scroll area, then the scrollbar behavior is much more like I would expect. It's only showing up in the scrollable area. And that's going to be what you want if you're creating an app like this one.
So, thanks to the Safari engineering team, we solved that final problem, flaky fixed positioning. And that covers all three areas that I wanted to discuss with you today in Safari on iOS. So I'm going to hand it back to Beth to talk about Lion. Thanks, Vicki. Let's move on to Lion.
I want to cover a few topics today with regard to the new scrollbar design on Lion. First, I want to give you an overview of the new scrollbar design. I'm sure you've--well, I know you've all seen it because it was talked about in the keynote, and I'm sure some of you have installed Lion, and maybe you went to other sessions that discussed it, but I want to make sure we're all on the same page, so I'm going to give you an overview of the design. Then we're going to talk about how that design affects web content. I want to tell you a particular part of the implementation about our color heuristic to give you a little idea of what's going on there.
And finally, we'll talk about scrolling. So let's begin with the new design. The theme of Lion is back to the Mac. So Mac OS X has been inspired by iOS, just like iOS originally inspired-- wait, I said that wrong. iOS has inspired Mac OS X, just like Mac OS X originally inspired iOS. And as I mentioned earlier, we now have these great Magic Trackpads on our Macs. So we have multi-touch gestures available to us everywhere.
It's really a natural progression for Lion to change the way it indicates interaction to the user with regard to scrollbar and scrolling in this new multi-touch world. The new Lion scrollbars really have that look and feel of iOS, and it really makes sense in a world where you interact with your computer with gestures. So before we take a look at the new design, let's remind ourselves of what scrollbars look like on Snow Leopard.
So this is what they look like on Snow Leopard. Probably the two most obvious features of this scrollbar is the big blue scroll thumb and the fact that this is a scrollbar that's always visible and always taking up space on the page. Now, Lion actually introduces two new scrollbar designs. There's a legacy style that's actually very similar to the Snow Leopard look. So we'll look at that one first.
It looks like this. There is a bit of a redesign here. Instead of that big blue scroll thumb, we have a more slender gray scroll thumb. But otherwise, this behaves just like the Snow Leopard scroll bar. So this is a scroll bar that's always visible, and it's always taking up space on the page. And just so you know, users who have Lion on a machine that does not have a multi-touch input device hooked up to it, their system will default to using this legacy style of scroll bars. But it is able to be controlled manually in system preferences.
So the new, new design, of course, is the overlay scroll bar. Overlay scroll bars just sit on top of content. They take up zero pixels of additional space. And of course, most of the time, they are not visible. So that's a big part of the new design, is the fact that they're not visible a lot of the time. And so I want to explain to you when you should expect them to be visible. Because that's a big part of understanding its behavior.
But also, there's actually a bug in the developer seed you have. So I want you to know how to expect these to behave in the future. So first of all, when a web page finishes loading, the scroll bars will flash to indicate that there is content to scroll to. Then if the window is ordered out for any reason, when it becomes the frontmost window again, the scrollbars will flash then as well.
The scroll bars are always visible when scrolling a page, but just hovering in the scroll bar region will not cause them to appear. However, clicking in the scroll bar region does cause the page to scroll, so that's important to know for hit testing purposes, that little scroll bar region, even when there's no scroll bar visible whatsoever, it's still swallowing clicks.
So if you happen to be on a website where there is a link or something right against the edge of the web page, if you tried to click the link in that little narrow 10-pixel area that's the scroll bar region, you wouldn't click the link, you would click the scroll bar region. So that's one thing to note.
And finally, if you happen to hover over in the scrollbar region when the scrollbar is showing, you'll see this additional little track-like thing. It's really hard to see on this particular recording, so we'll take a closer look on the next slide. Here's a closer look at the scrollbars in general. On the left here, we have a snow leopard scrollbar, and on the right, we have the new overlay scrollbars. Of course, the big blue scroll thumb is now this slender gray knob thing.
Also note the controls at the bottom that we always had on Snow Leopard, these arrows in the resize corner. Those aren't there in the new Lion legacy design either, so controls are officially a thing of the past. Then we have this track on Snow Leopard, and we have this only rarely visible track with the new overlay scrollbars. Again, you only end up seeing that when you hover over a scrollbar when it happens to already be showing, then a track will also appear.
Okay, so hopefully we're all on the same page now in how we expect the new overlay scrollbars to behave. So let's talk about how they affect web content. So I also took Jingjin's awesome demo from last year and adapted it to my amazing blog. I've added an overflow scroll div in the middle, which brings us to my first point, which is that all scrollable areas honor the design. You'll see that my overflow scroll div has an overlay scrollbar just like my main document does. And if I had legacy scrollbars, they would both have legacy scrollbars. So everything will be the same there. Of course, most of the time, they'll look like this.
So you may have noted that I said this was an overflow scroll div. So this may look a little bit different than you might expect an overflow scroll div to look because there are no empty scrollbar tracks. So to give you a visual of exactly what I mean, this is what the same page looks like with legacy scrollbars.
You'll see that even though there's no content to scroll to horizontally in that overflow scroll div, there's still an empty horizontal scrollbar track. And that's just part of what overflow scroll means on Snow Leopard and on any platform really that has this track look of a default scrollbar. And just to really emphasize that, if there was actually no content in this div, you would still have empty scrollbar tracks.
But not in an overlay world. In an overlay world, there are no empty scrollbar tracks. That track-like thing that shows up sometimes when you happen to hover over the scroll thumb when it's showing, it's just too much of a different paradigm. It doesn't apply here, so it doesn't make sense to show that for overflow scroll in an overlay world.
[Transcript missing]
So you really just see more. You have 15 more visual pixels. Most DOM metrics remain the same despite this difference. Things like offset width, scroll width. These things never really factored in scrollbars. They're about the outer limits of the element. They're the same. However, some are different. Client width, for instance, is defined as a measurement that subtracts out the width of the scrollbar. And if the width of a scrollbar is 15 pixels or if it's zero pixels, you'll end up getting a different number there. So that's something to look out for.
Really, you should just test your content in both of these worlds, in the overlay world and the legacy world. And you should make sure you like what you see. I can say, having been browsing the web for months now with overlay scrollbars, that I don't expect existing content to really change with these changes.
I haven't seen any of these things appearing as gotchas. I've seen one instance of it, actually. But it's something to be aware of, that you can't expect scrollbars to be the same size on every platform, and that some DOM metrics take that into account and some don't. Just something to think about.
Okay, so hopefully that gives you an idea of how the new design affects web content. There are a few other things. One I'll mention just briefly is that if you happen to do any amount of custom CSS styling to your scrollbars, they'll look exactly the same on Lion as they would on Leopard. They'll default to that legacy style look where they'll always be there and they're always taking up space, and they'll look the same way you styled them. So that won't be affected, just so you know.
So let's talk about the color heuristic. I've shown you lots of pictures of scrollbars today. I'm sure you've seen them a lot this week. They usually look like this, this gray scroll thumb. However, on a page with a darker background, you'll see a scroll thumb that looks like this. It's a lighter color.
So what we're doing in WebKit is we're trying to assess the background color of -- or the background of the window that you're viewing, and we're trying to decide if we think it's a light or dark background. And then we decide which scroll bar thumb to use based on whether it's a light or dark background. So I want to explain to you our current heuristic for assessing whether a page has a light or dark background.
Basically, we take relevant colors and we composite them together using the Porter-Duff source over equation. And what we decide are the relevant colors as of now are the background color of the HTML element, the background color of the body element, and the base background color. The base background color is really just white. It's the color of the window. But this is relevant in cases where the background color of the HTML or body element has some alpha in it, in which case that white blends through.
So all of those colors are blended together, and then the result is converted to an HSL value, and that L gives us the lightness. If it's a light background, we'll use a dark scroll knob that shows up really well. If it's a dark background, we'll use a light scroll knob that also shows up really well.
So a few things to note about the heuristic as it's currently implemented is that background images are ignored. So if you have a really dark background image covering your page and no background color set, then you might run into a situation where you're not seeing the scrollbar thumb that you expect to see. However, that's a really easy fix because you can just set a dark background color that's similar to your dark background image, and you'll never see the color, but it will be picked up in this heuristic, and the correct scroll thumb will be chosen.
And all other elements are ignored as well. So just to give you an idea of that, if I take this example that I used earlier and I take a giant white div and I position it over my content, I'm not really going to get something that's exactly what I'm looking for or super useful.
So a few things to note here is that the scrollbar can be one of two colors. And you should make sure you like what you see. You should test this out. And if you think the heuristic isn't working for you and you can't work around it, you should file bugs, bugs.webkit.org or bugreporter.apple.com. So hopefully that gives you an idea of what you can expect in terms of different scrollbar colors. Finally, let's talk about scrolling. So there's some elasticity in scrolling on Lion. We call this rubber banding sometimes.
During a rubber band scroll on Lion in Safari, scroll events continue to fire. So the on-scroll event, on-mouse wheel event, they will continue to fire while the rubber band is actually happening. The scroll offset can be negative if you're at the top of the page and you're pulling it down to see the linen behind it. At that time, the scroll offset of the body will be negative. It can also be greater than you expect if you're doing the same effect at the bottom of the page.
And another thing to note is this is different on iOS. As Vicki mentioned earlier, scroll events on iOS fire when you lift your finger from the screen. On iOS, you're really not scrolling. You're panning around. It's really a different paradigm. So this is just something that's different between the two platforms.
And that's an overview of scrollbars and scrolling and how you should expect them to affect your web content. So let's move on to fluid gestures. As you saw in the keynote on Monday, we support some really cool new fluid gestures in Safari on Lion. We have a double-tap, a pinch-to-zoom, and a pretty sleek back-forward swipe navigation.
So with regards to those new gestures, today I want to talk to you about how you can optimize your web content for double-tap. Of course, this is extremely relevant to iOS as well. And then we're going to talk about how you can ensure back-forward performance, which is, it's really great when you have a page that loads quickly back-forward when you're using the swipe navigation. Beth Dakin, Vicki Murley I'll begin with double-tap. So to explain the best ways to structure your web content for double-tap, I want to explain to you the double-tap algorithm.
It's the same algorithm on Lion and iOS. So this is the same algorithm that you've been using already for years. It begins by finding the tapped element. So let's say I tapped on the beginning of this text in this article. And then it finds the first block or image ancestor of that element. So in this case, I tapped on some text, so it will find a block ancestor.
And it will probably be like a div that the text is being laid out in, or a P element, something like that. In the case of a block, which is what we have here where I've tapped on the text, the block will be zoomed to fit width-wise. So it will look something like this.
If I instead tapped on this image at the beginning of this article, the image would be zoomed to fit. So the distinction here is that with an image, you make sure you see the full image. The height and the width will both be taken into account. If it's just a block, we won't take the height of the block into account.
And another thing to note is that there is a maximum scale factor on both platforms, and it's different. We find that what starts to seem ridiculous as you keep zooming in more is somewhat related to the size of your screen. So there is a slightly different maximum scale factor.
Double-tap is definitely an example of something that just works the vast majority of the time. But there are some things that you can keep in mind if you really want your site to work well with double-tap. First is to avoid wide blocks of text. Something like this, if you double-tap on it, it doesn't change much. It's not really doing anything interesting for the feature. But if your page is organized into digestible little sections, then there's lots of opportunity for double-tapping to be a really interesting user experience.
Okay, so moving on, let's talk about ensuring back-forward performance. Back-forward performance is really important everywhere. It's always been an important issue. As I mentioned earlier, it's relevant today because we have this new back-forward swipe navigation in Safari on Lion, and it really does have the best experience when going back is quick. But going back and forward being fast has always been really, really important on iOS. If you're on a really slow network, it can be a total drag to go back and have to wait 30 seconds for a page to load all over again.
It's really a relevant issue on all platforms and all browsers, so getting good back-forward performance is a great goal everywhere. The key to back-forward performance is making sure your page gets into the page cache. So a lot of times when people hear caching, they think caching resources or an HTTP cache or storing these things on disk. But that's really not what I'm talking about.
I'm talking about the page cache. So normally, when you navigate away from a page, it's just totally torn down. The whole DOM tree is destroyed. JavaScript objects are collected. It's just gone. But the whole point of the page cache is to not do that. It's to actually keep those things around, keep around the whole DOM, keep around all of your JavaScript objects. When you go back to a page that's stored in the page cache, it's practically instantaneous.
You can kind of think of it as if when you're normally viewing a page, you have a play button going, and when that page goes into the page cache, you've just hit pause. Going back to a page where you've just hit pause, you just hit play again, it just works.
So the key to getting your page in the page cache is not to do something special. It's to not do a few things. You just want to avoid things that are uncacheable. So let's talk about what's uncacheable. First of all, unfortunately, HTTPS is uncacheable for security reasons. There's not much way to work around this. It's just not safe to keep around the DOM or JavaScript objects of an HTTPS site. And if you are creating an HTTPS site, it's probably because it has to be that way. It has to be secure. So unfortunately, there's not much of a way around this one.
Plugins are also not cacheable. Plugins run native code in the browser, and there is no trivial way to say to that native code, stop, and don't do anything bad for the next few minutes. So unfortunately, you have to try to avoid plugins if you want to get into the page cache.
But I think that there have been a lot of sessions this week that have given really great ideas for how to avoid plugins on your sites, such as the HTML5 video session that happened earlier and the great CSS effects session. So hopefully, you'll get some ideas of how to avoid using plugins.
The next thing that's a really, really big one is unload event handlers. Unload event handlers were designed as a way to allow a web developer to do some page teardown at the end of, when you're navigating away from the page. So it's sort of in the API contract that a website author is allowed to totally destroy the page in the unload event handler. And therefore, it's just completely unsafe to cache a page that uses an unload event handler. There are no browsers, many browsers, have a concept of a page cache.
For example, Firefox calls theirs the back-forward cache. And they, and we, no browser, caches pages that use unload event handlers. Except, actually, new in iOS 5, in an effort to make back as fast as possible, Mobile Safari now ignores unload event handlers on pages that can otherwise be put in the page cache. So there is an exception there.
But if you really feel like there's critical work that you need to do in an unload event handler, I strongly encourage you to change, make a simple change, instead of using unload and load, to use page show and page hide. Page show and page hide, first of all, will run on Mobile Safari. So if you feel like you really need to do some work when you're unloading your web page, use these.
But also, they're totally cacheable. The thing that makes these cacheable is that, actually, the load event fires at the single discrete moment when a web page is loaded. Page show fires at exactly the same time but it also fires when it's being restored from the page cache. So any work that was undone in page hide can be redone in page show. I strongly encourage you to use these instead of load and unload as they are extremely cache-friendly and they're also implemented on all major browsers.
So that's sort of just the tip of the iceberg of a really big topic in terms of website performance, but it's a really easy way to get pretty awesome back-forward performance. So we've talked about a lot of things today. I think one of the big messages here is that most things will look great as is. We told you about a lot of browser features today, and most of them are things that just work.
However, customizations and improvements are available when you need them or when you want them. We work really hard here at Apple to make existing content work better and better, and you probably saw that with the new fixed positioning in iOS 5. But sometimes you will need to adjust to things, and sometimes you'll just want to make something better and better because it's all about the user and delivering an amazing user experience. And finally, you should just test your content. This is especially applicable to the scrollbars. Just looking at overlay scrollbars and legacy scrollbars will make a big difference.
If you have any more questions, you can always contact the fabulous Vicki Murley, the same Vicki Murley that was on this very stage a few minutes ago. All of the relevant sessions already happened, but I encourage you to look at the videos if you didn't get to attend them. The whole internet and web track really is somewhat relevant to this topic, so I encourage you to look at all of the sessions, really.