Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-344
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 344
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2008] [Session 344] Adding Rich...

WWDC08 • Session 344

Adding Rich Graphics and Media to Web Content in Safari

Essentials • 42:44

Adding sophisticated graphics and media to your website or application has never been easier with the powerful, W3C standard technologies available in Safari. Learn how to leverage cutting-edge features of HTML5 to deliver media with standard HTML audio and video elements and discover how to create rich, animated graphics with new features of the canvas element and SVG.

Speakers: Adele Peterson, Stephanie Lewis

Unlisted on Apple Developer site

Downloads from Apple

SD Video (381.8 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Welcome to session 344, Adding Rich Graphics and Media to Web Content in Safari. Everyone loves the rich media. I'm Adele Peterson. I'm an engineer on the Safari and WebKit team. So before we get started, I just want to do a quick survey of the crowd. Okay, who here has ever created any web content using the image tag? All right, so we're all awake here. That's good. That's good.

All right, for those images, who here has ever used an image editor like Photoshop to get just the right visual effect for those images? Okay, actually, still a lot of people. Who here has ever used a plug-in to add video or audio to their web content? Wow, a lot. Okay, great. Well, today we're going to be talking about some new ways to integrate those rich media and graphics into your web content using some technologies that are built right into Safari.

So a lot of the things I'm going to talk about today are actually already available in Safari 3.1, which is out there in the wild. Everyone's using it. But a lot of the things I'm going to talk about are new to the Safari 4 developer preview. And that was actually announced this morning in the Safari and WebKit overview session. And it is available in your Snow Leopard seats and on Leopard, Tiger, and Windows. So let's get started. The three main topics that we're going to talk about today are media, graphics, and effects. And let's just dig right in and start with media.

So video and audio are becoming more and more important on the web. Sites like YouTube have become part of our day-to-day internet culture. I don't know about you, but I don't know how I would be able to live without Harry Potter puppet pals as constant entertainment. So this is becoming more and more important. But all of these sites listed right here actually accomplish that video and audio integration by using plug-ins. And plug-ins are great. They're really powerful. It's like having a separate little application as a box inside your page. But it's not standard web technology.

Video and audio should be just as easy to integrate into your page as images and text are. Just imagine for a second if you required your users to download a plug-in just to view an image on your site. A lot of them might just throw up their hands and say, no, I'm not doing that. I'll go find some other content out there.

In the future, we want to start making video and audio first-class citizens on the web. We want them to be just as easy as that other content that's built right into the browser. The way we're going to do that is by using the next evolutionary step for HTML called HTML5.

HTML5 is the new specification being developed by both the W3C, which is the World Wide Web Consortium, and the What Working Group together. And Apple has actually been participating with both these groups in developing the specification. Specifically, we've been working on something called HTML5 Media Elements. And that is both the video tag and the audio tag, just as simple as adding an image into your page.

So let me show a quick example of how you might have achieved this media integration in the past. Here we have a video, and in this example, we use the embed tag to use a plug-in to play the media. And moving forward, We want it to look like this. Simple and clean and easy to just put up there. Get that content on the web.

So using the embed tag or an object tag, if that's the past and the video tag is the future, many of you are probably wondering, well, what about right now? So there's actually a pretty good solution for that. In HTML, you can have content fallback. So here's an example of how you can use the video tag or the audio tag right now in conjunction with your existing solution. So you can try out this new technology and start seeing what it can do while not completely abandoning the code that works in other browsers that don't have this new support.

So another type of fallback that you might want to use is source fallback. HTML5 specifies a way to have these source elements, which are actually children elements of both video and audio. And this is how you can specify different types of media. So in this example, I've used media queries for each source element, which specify different things about the screen size, you know, for the device the media is being played on.

And in the last example there, there's a media rule for print. So this is just one example about the browser will see all these different media resources and choose the best one that fits. There's also a way to specify different codecs. And actually in the session tomorrow night, preparing and delivering video for iPhone Safari and Apple TV, they'll give lots of great examples of how to do this source fallback. So definitely check it out.

So most of the things that I'm going to talk about will apply to both the video element and the audio element. But I just wanted to make a quick mention of some things that are special about each of those. For the video element, there's a special attribute called the poster attribute, which allows you to specify the URL of an image to show up while the video is preparing to play. So that's something handy to keep in mind for video. And for audio, well, audio is kind of special because it doesn't usually actually have a visual presence in the page.

So most of the time, you're going to want to use the audio element by creating it from JavaScript, you know, creating an audio, you know, new audio. And you'll have that audio element to manipulate in all the ways I'm going to talk about right now. So just a few quick notes about this individually. But for the rest of the talk, I'm going to talk about things that apply to both of those elements.

So the HTML5 specification for media elements supplies a lot of different attributes and functionality that gives you as a developer a lot of fine-grained control over your media. So we're going to go through a few of those examples. All right. Here I have an example of the controls attribute.

At the bottom, you'll see a set of controls that are actually pretty similar to what you see in the QuickTime plugin, and they'll appear and disappear as necessary. They have some of the default behavior that you'll probably want just to get your video up and going on your web page. So it has play, pause, mute, slider timeline, and seek buttons.

And you don't have to worry about leaving room for it when you're specifying the size of your media, which is really great. So this is the easiest way to just get your content up and running on your page. When I think of this example, I think of a novice user for HTML who can maybe put up a web page and have a few image tags with pictures of their family. Maybe they want to put a video of their kid on their web page.

If they do this, it's just as simple as anything else on the web. So I see this as a great way to just get people up and running with video and audio. And actually, the controls attribute will give the audio element a physical presence on your page and have it just show up with those default controls.

But the great thing about video is that it's just another element on your page. So it's going to integrate and work with different styles and layers on your page, just like any other element. So you can do a lot more than you can with just a box for your media on the page.

So many of you may want to get creative and create your own custom controls. So we're going to go through some examples of how you create those custom controls, which will sort of illustrate the different-- The different ways that you can have that fine-grained control when you're programming with these elements. So the first example would be a play-pause button.

The code here is actually pretty straightforward. You have access to a paused attribute, and you can call play and pause directly on your video or audio. You can also listen for events in JavaScript, like the ended event. So maybe when one video ends, you want to start another. Maybe you want to wait until the video is loaded enough that it's ready to play before displaying a certain image.

Another example of a custom control would be a special timeline. Maybe you would actually have a clock displaying it or, like in the default controls, a slider that you can scrub the media. So you have access to the current time and the duration, the playback rate, and also to many events like progress and load. And time update is a great one because you get that event any time the actual time changes. So if you want to design a counter control and every time the seconds change, display the seconds, then you just listen for that time update event and you've got it.

and the You can check to see if the video is muted. You can make it muted if you want. And you have access to the current volume that you can get and set and listen for volume changes in the media itself. and the last example here is that you can control loop properties on your media. So setting a loop start time and end time and the number of times you want something to loop.

So that's all pretty straightforward, and I think now is a great time for a demo to show you some of these things in action. So I'd like to invite my colleague Stephanie Lewis up on stage to show you a little bit of the power of video as a first-class citizen on the web.

Hello. Everybody hear me? So my name is Stephanie Lewis, and I'm going to show you some cool video. So you may have seen this earlier in the Graphics Day of the Union. It's a pretty prototype thought together by our team over at Apple.com. The entire page is made solely of CSS and JavaScript and HTML, no plugins at all.

And I guess, given we have our pretty nanos, they can now play video. We want to highlight that. And what's kind of cool about this demo is you can move things forward, move things backwards, stop it so you can actually hear me and not listen to the ad.

And it's all integrated right into the page. And then what's even more fun is nano's, of course, come in multiple colors. So you can have multiple videos going. Because it's integrated directly into the page, you can have more than one going at any time. You can fade the video in and out. Listen to exactly what you want to listen to. If you're curious about these animations and transitions, I recommend you stick around for the rich UI talk. And then I'm going to show you how we put some of this together.

So going to Xcode. Actually, not going to Xcode yet. So I'm going to start off with our basic-- we used to use the ad and we'd have the nano, and it's kind of boring and we want to spice that up, right? So I'm going to edit video. It's a one-line change, as she showed you. I've listed my source. I'm going to throw controls in there. Quick deploy. Had to do it the night before.

If it loads, oops, sorry, wrong step. Okay, so we've got the controls, it plays it, I can brush through, skip back, mute it. But what we really want to do is because Nano has these beautiful controls already built in, we'd rather use those. So I'm going to show you how we added that.

So down here at the bottom, I've added three anchor classes. Using CSS, I was able to place the buttons directly over the image of the nano. And then I've called in some simple JavaScript functions. At the top, I'm doing a little bit of initialization just so that everything can work together.

But the important part here are these new functions. Play/Pause. It just checks to see the video's pause and it's going to play it. And skipping backward and forward is doing nothing more than adding to the current time or subtracting from it. And then I'm going to show you again what that looks like.

So again, I can skip forward and pause it. And then one of the things that I like about the Video Tag is that it integrates so easily with JavaScript. And so you can obviously listen for events. What I want to do is I want the Nano to be able to play more than one video. So I'm going to listen for the video to end and then switch to a new video. And so I'm going to show you the code for that.

So again, I've added a listener in my notification function. It's going to listen for the video to end, and what it's doing is it's going to call a few functions. The first function it calls is fade audio. I want to fade it out to fade the new one in.

The only thing that's really new here is the video volume. I'm adding and subtracting from that, but I'm doing this by setting an interval at a regular time so that it slowly degrades. And then, of course, when I'm done, I want to clear the interval. And then what that does is then it calls start next movie.

All that does is it finds the next movie that I want to use, kind of loops through an array, loads the source, loads it, and then starts it playing. And so now let me show you that. Back to Safari. And so, again, I can skip all the way through so we can get to the end. And it'll finish up the video. And then I'm going to start playing something different.

So that's it for that demo. So I'm going to give you back to Adele, and she's going to tell you about some pretty graphics. I love that demo because it really illustrates how the video fits in with the rest of the page so well. Actually, there's a version of that demo as sample code that's associated with the session, so definitely check it out and see how we made all that work. There's actually also another piece of sample code that shows the content fallback technique using the plug-in solution for browsers that don't support audio and video.

Okay, graphics. So the simplest meaning of graphics would be the image tag, like we talked about before. We're gonna go beyond the image tag and talk about some more advanced technologies. Specifically, we're going to talk about the canvas element and scalable vector graphics, SVG. So first, the canvas element. The canvas element was first introduced in Safari 2. And the best way to describe it is to call it a scriptable bitmap, an element in your page that you can draw into with JavaScript.

So when Safari 2 shipped, it shipped along with OS X Tiger. And Tiger was the first OS that had Dashboard. And Dashboard widgets actually are great examples of how Canvas is useful. The stocks widget has the dynamic graph that is drawn with Canvas. The hands of the World Clock widget.

And some of the other animations are done with Canvas. So after we shipped that in Safari 2, other browser vendors thought, hey, this is really cool. We all want to use this. So it is actually now included in the HTML5 specification, and it's also implemented in Firefox and Opera.

So let's start with a basic example of canvas. So here I have the canvas element. I've given it a width and a height. So now we're ready to draw into it. Here's a basic example of how that works. You get a 2D context for your canvas and then you call graphics functions like fill rect here to draw into it.

Now, for those of you who are familiar with graphics programming, there's actually a lot you can do here. But we're not going to go into all that detail. Actually, let me show you an advanced example that uses some of these other graphics techniques. So, one of my colleagues, Oliver Hunt, actually made this in a short amount of time. It's a particle generator and it uses things just like fill rect to get this motion effect. So, it's kind of a pretty little animation there.

So mostly I want to talk about some new features we've added in the Safari 4 developer preview. Mostly they're all about setting and getting image data from a canvas element. For these functions that I have listed up here, there's really a few different steps. And we're actually going to use an example of image processing to illustrate how these new functions are useful. So we want to get image data from a canvas. We want to know how to create that image data, how to process it, how to put image data back into a canvas, and how to save it. So let's start with get image data.

Well, first let's talk about the image processing. So we have Bentley the dog here. I know, everyone's a sucker for puppies. So we have Bentley the dog here, and there's a really easy way to get that image into a canvas element. There's a drawImage method. So using drawImage, we have Bentley the dog in our canvas element.

So now let's start with Get Image Data. It's a pretty simple syntax. And what you get out of that is an image data object. Image data has a width and a height, and most importantly, a data member. And that data member is just a pixel array. Let's say you want to create your image data from scratch.

We have a create image data function. In this example, we're using it to create what is going to be the output of our image processing. So, actually, if I step back a slide, in this example, we have an image data object input and that's going to be Bentley the dog's image data.

and now we're creating output. OK, so now let me show you an example of some simple image processing. This is actually how you would do the invert effect for image data. You can see here there are a few different for loops that are going to loop through the data structures. And we take the input data, do some math, and compute what we want our output data to be. And so for input and output, which are image data objects, we use the data member as an array to manipulate that image data.

So we've done all this fancy math, and now we want to see what it looks like. So we're going to put that image data, the output image data, back into our canvas element. It's pretty simple. Just use put image data. And now this is what would show up in your page in the canvas element.

Okay. So now let's say you want to save that image. Use it on the client side, maybe without, you know, making a server round trip or maybe with. So here are some ways to use this new function to data URL to have more control over what happens to that new image.

So in the first example here, well, so to data URL has an optional parameter. You can pass it a MIME type or you can not. I think the default is actually image ping. And what you'll get is data colon as your URL. You'll actually see this in an upcoming demo. But so there's three examples here. The first one is setting window.location to your data URL. And this will just load as the main document of your page the canvas. And the second example, we're setting the text area's value to the data URL.

And that way you could upload it in a form if you wanted to let the server have some information about that. And the third example is to save it with local storage. And actually, this is just a little preview of the offline data session that you'll see later in the week. So definitely check that out if you're interested in learning more about local storage.

There are a few safety measures to keep in mind for getting image data. If you draw into your canvas with an image from another domain, we're going to consider that canvas context to be unsafe for getting data out. So, two-data URL and get image data aren't going to work in that case. And the same is true if you draw from another unsafe canvas into your current canvas. So, that's just something to keep in mind.

The last new feature I want to tell you about is the new ability to use Canvas as a CSS image. Anywhere in CSS that you currently use an image URL, you can use a Canvas image. In this example, we've specified an identifier when you get the 2D Canvas context, and then you can use that identifier later from CSS.

Here in this example, it's backgrounds, but you can use it for borders and pretty much anywhere else that you use an image. So now is a great time for another demo to show you some of the power of what these new functions can do for you. So, Stephanie.

Hello again. So what I'm going to show you is the new features we've added, so specifically get image data, implements data, and two data URL. I've written up a quick little image processing app. As you can see, we have our beautiful Safari icon. And with the code that I've talked about, I can easily add effects, say like grayscale or something a little more exciting, use some displacement maps and ripples, easily stack them together so I can say do an inversion. They make it kind of big.

And then when I'm ready, I can decide, when I've decided on what I'm going to look at, I can easily pick what kind of output I want. In this case, I'm going to just take a ping and export the file. Up at the above, you can see we have a dated image URL. It specifies the MIME type and then goes on for quite some time. And then I can easily just save the image to my downloads, open up in preview, do whatever I want with it.

Do you think they'll let me replace the default icon? And so now I'm going to show you what I did to get to that code. For HTML, all I have is a canvas. I didn't have to add any special processing there. Most of the work is done in JavaScript. At the beginning, I have a new image, draw my compass image so it's up there and pretty. Get the canvas, get its context.

Clear any previous effects out because who wants to have multiple effects on top of each other? Then I draw the image out, get the pixel data, this gives me the pixel array. At which point I can do whatever fancy math I want to do. Go see Graphics 101 if you want to know how I'm doing it. And then I can just put the image data back.

And then finally, when I want to export the image, most of this is dealing with choosing the mind type, but I'm just saying the window location. So, what, three lines of code? And so then before I finish, I'll show you one more effect. This one's my favorite. Oops, didn't quite work with both of them. And then I'll give you back to Adele.

Thanks, Stephanie. I love the glass boxes. So that was a quick run-through of Canvas. Definitely check out these new methods and see what you can do with them. Scalable Vector Graphics, SVG. SVG is an XML graphics language. And it's kind of a bigger fish in some ways than the canvas element.

A canvas element, you have this element on the page and you draw into it and what you've drawn is just part of that one element. But SVG is a whole XML document that you can navigate using normal DOM traversal methods. And also, it's scalable. That's one way it's different from canvas. So, when you have an image made in SVG, you know, it can scale up in your page and look beautiful at any size.

So here's a basic example of an SVG document. Now, this is what you would load as the main document in your page. SVG content can also be mixed with HTML and-- well, XHTML. But a document like this could be the source of an iframe. With this basic example, you have different elements for all the graphical things that show up in your page, so you can get to them later and manipulate them.

One of the new features in Safari 3.1 was the ability to reference SVG from HTML and CSS. So here we have an example of it as the source of an image tag and also as a URL that can be used anywhere an image can be used in CSS. So these are really handy for reusing your SVG artwork in beautiful, awesome ways within your normal HTML content.

Another way to use SVG from HTML is to use SVG fonts. Well, here's an example of how you would draw a glyph for a font in SVG. But that's not really the point. The point is that once you do have this awesome, beautiful, scalable font in SVG, it's really easy to use from HTML. And here's an example of how we've used font face and defined a font family name that can be used later that references that SVG font.

This is actually kind of part of the new web fonts feature that will be talked about a little bit more in the Creating Rich User Interface session coming up at 5 p.m. That's sort of the same technique with TrueType fonts. There are a lot of benefits to doing this with, you know, referencing a font, a custom font from HTML. Usually, this type of font is not going to be used in SVG. So, this is really handy.

Another new feature in Safari 3.1 is SVG text on a path. So this is kind of cool. You can define paths in SVG, as you can see here with some arcs and lines. And then it's really easy to just tell your text path to use the path that you specified earlier in your document.

And another big feature in Safari for developer preview is SVG animation. Again, here's a very simple example of how I move that box across the screen. I just have a rectangle and I use that animate motion tag to tell it where to move and how long to move to.

And there are a few different things that you can tweak here. We actually have support for a bunch of different advanced features for animation here. And I actually want to show you a quick example of something I came up with a few days ago to illustrate some of this.

So here we have the funny bee. I actually got the funny bee from openclipart.org, which has a bunch of SVG images that are in the public domain. I myself am not artistically talented, so it's a good thing they had this library out there. Basically, what I did is I went in and I found the different elements that represented the bee's wings, and I animated those. And they also defined a path and had the bee move around that path. So here in the code example, we have the animate motion tag, and it just references this path that I called Bee Motion. So that's how the bee is moving around the page.

Here's the example of how I made the wings animate. I used this animate transform tag and told it to rotate, at certain times, a certain number of degrees. Some of them go from 0 to negative 15 degrees, back to 0, and some from 0 to 15 to 0. And this actually uses an additive animation because the bee itself is already scaled and transformed in other ways. So this is just a short example of some of the powerful things you can do with SVG animation.

Some of the references that you should probably check out if you're interested in this is, of course, the W3C site about SVG, their animation spec, and I'm a big fan of openclipart.org, so I wanted to just tell you about that as a quick way to get started with SVG.

That was an overview of some of the more advanced graphic techniques. Now we're going to talk about effects. When I talk about effects, I mean all the things that you might do to your image beforehand in an image editor. So a few examples of those types of effects that are now included in CSS and have been, some of them for a while, are things like rounded corners or drop shadows.

So these are all things that are all over web UI and desktop UI. And for some of them-- for example, rounded corners. Before border radius was added to the CSS3 spec and browsers started to implement that, people had all kinds of complicated techniques for coming up with this effect.

Some of it used different images stitched together in just the right way. And I know for some of box shadow effects, people either had to pre-process the image and add the shadow beforehand. Or some people even wrote complicated canvas libraries to add the shadow on the fly, which is great.

It just is a lot of code. So some of the new CSS effects that I want to show you will take something like this, which is an example of how you used to do rounded corners, to this, which is how we now do rounded corners with border radius in WebKit.

So that's all great, but of course, you're probably wondering again, what about the other browsers that don't support these new properties? Well, the great thing about CSS is that it does degrade gracefully. If there's a CSS property that a browser doesn't understand, they just ignore it. So you can either choose to specify simpler properties for those other browsers, or you can just rely on the fact that they'll not react crazily to these new properties.

So going forward, just a quick note about the dash-webkit CSS prefix. This is a standard thing that we do for things that aren't in, properties that aren't in a final specification. So other browser vendors do this too, and this allows us to prevent any future conflicts as the spec is in flux. You know, so the dash-webkit border radius, if it ends up being different from border radius, the final version, there's no conflict with the content that's already out there. So that's just something to keep in mind.

So the first effect I want to talk about is gradients. These are all over the place. We use them in webkit.org. And this is actually achieved on our website using images. And if we wanted to have our site be pink instead of green, we'd have to use a different image.

We'd have to do that work beforehand. So there's a lot of benefits to doing that work on the fly. Simpler code. And why shouldn't it be as easy as adding a background color? You can now use CSS Gradients for backgrounds and borders and pretty much anywhere that you would currently use an image.

and this is new in the Safari 4 developer preview. So here's a simple example of how you would do a linear gradient. We specify that is linear, a beginning point using some keywords. There are also some other syntax that you can use, an endpoint, and a beginning point for your color and an endpoint for your color.

Now, that looks pretty simple, but you can imagine if it were the background of a button that it might look a little fancier. Here's an example of a radial gradient. Again, it's a pretty simple example, but when it's used with the power of CSS and applied in different places, I think you'll find that it can be really useful.

Okay. The next example I want to talk about is CSS masks. Aw, Kate Hyatt. So here we've used an SVG image as our mask image and a picture of Kate Hyatt as our main image. And CSS masks allow us to do this effect. I've actually seen, I mean, let's take the example of a photo gallery. Let's say you want all the photos in your photo library to have a certain shape.

And you don't want to have to do it in Photoshop. So this is an easy way to say, you know, all images with the class, you know, circle are going to get this effect. And here's just a quick rundown of the different versions of that property for backgrounds and borders.

Okay, the last and I think the coolest effect is CSS reflections. Here I have a really simple example, dash webkit dash box reflect below. Just one word. There are actually two other parameters that you can pass, but they're optional. So you can tell it to reflect below or above or left or right, and you get this really simple reflection.

This is another one that I've actually seen a cool canvas library that people have included to get those reflections on the fly. But again, it's a lot of code. And this is also something that's really common. You see all over the place in different kinds of UI. So people do a lot of preprocessing for this type of thing to get that effect.

And here's a slightly more advanced example where I've actually used as a mask image a gradient. So now we're kind of tying things together here. And this to me is a really cool thing to do. So I'm going to go ahead and show you a little bit of a preview of what I've done. So this to me looks like something I would see, you know, on a professional desktop application. So I wouldn't be surprised if this were all over the place in a short amount of time.

So we talked about effects and graphics and media. And when you put them all together, you get something pretty special. Safari ties that all up for you and gives you, I think, a pretty powerful set of tools to create this rich, beautiful content. So now I'm going to do a quick demo for you, showing you how to put it all together.

I have to be on my tiptoes to see everyone. OK, so actually, let's go back to the nano example that Stephanie showed you at the beginning. Let's pause it just for a sec. All right, so here we have two iPods side by side. And the one on the right has a little reflection built in. And actually, that's something that was added to the image beforehand.

Somebody probably spent a little bit of time doing that effect on each image for each nano. So let's use the new CSS reflections to add that same reflection on the other nano. . Let me show you some CSS that I've written. I've cut two different reflection classes. The only difference between these is where the color stop begins and ends. Let's try this out.

So here I've got a div that actually contains all the different, you know, nano images. And I'm just going to go ahead and add this reflect class. Save it. And here we go. So now, hopefully you can see it from there, but the nano on the left also has a reflection. But this reflection is live. So you can actually see that when I pause, that highlight is live.

Oh, it just gets better. All right. So OK, we'll come back to that. OK, so now let's try that other reflection. I think it'll show a little more of the nano. I think you'll see there that the video is reflected live as well. You know, I think an even better way to illustrate how this all fits in would be to give you a little preview of the new CSS transitions and transforms. So we actually built in some of those to this demo.

I'm going to hit this menu button. I'll just give you a little show. And as it tilts, you'll see the video is reflected. And it starts up again. And it's just part of the page. The CSS reflection is working with all those elements. And it's just another element on your page. Let's have it rejoin its friends here. So now you can see all five videos are playing. And they're all reflected live. And as each nano moves around, the video follows it. It all just fits together beautifully.

Next slide. So that just gave you a taste of how putting all these different techniques together can give you something pretty awesome. Those are the kinds of things that you can do with web technology before all this new stuff. I mean, you probably have to use a plug-in. So this is all built right into Safari. It's using the technologies you know and love. And I just think it's pretty cool. I hope you will, too. So definitely check out the Safari 4 developer preview. And I can't wait to see what you guys come up with.

For more information, you can contact Vicki Murley, the Safari Technologies Evangelist. And I have a few links up here to the WebKit open source project and a few specifications that might be useful to you. I'll just give you a second if you need to make any notes. We can also come back to this.

and some related sessions right after this at 5:00 p.m. in North Beach. Definitely check out Creating Rich User Interfaces for Web Content in Safari. They're going to talk about web fonts and CSS transitions and transforms. It's going to be pretty -- it's actually kind of related to this session, so definitely check it out.

And also the Preparing and Delivering Video for iPhone, Safari and Apple TV session, especially if you're interested in, you know, what kind of encoding you want to apply. And we have two labs, the Rich Graphics and Safari Lab tomorrow at 5:00 and the Safari Compatibility Lab on Thursday night.