At the moment of this post, these features [except for Pseudo] are only possible in Safari 5.1, Chrome, and iOS but is a great stride in the progression of HTML5 video. There are a few new methods you can use to implement native fullscreen for video and even go fullscreen with html elements [ie – a div].
In the following code, I’m going to use jQuery for selectors but jQuery has nothing to do with the end result. If you go crazy over typing document.getXXXXX, I’m sure you still get the idea here.
Fullscreen <video/>
$("#myvideo").webkitEnterFullScreen(); |
* #myvideo is the specific <video/> element you want to take fullscreen.
That’s all it takes. This works by opening the video element in the native player. The controls also become native but they look good so it isn’t a huge deal unless you’re definitely concerned about the visuals.
Support: Safari 5, iOS [tested on iPad 2], and Chrome [including Android; tested on XOOM]
Fullscreen Custom
This one actually goes beyond video since you could literally take anything fullscreen. Google, Chrome needs this. Get’er done!
This is a bit more involved but still not a huge deal and if you’ve done any fullscreen work in Adobe Flash it should seem somewhat familiar.
function toggleFullscreen(){ try{ if(navigator.userAgent.indexOf("Safari 5\.1")){ if($(document).context.webkitIsFullScreen) $(document).context.webkitCancelFullScreen(); else $("#mydiv").context.webkitRequestFullScreen(); }else $("#myvideo").webkitEnterFullScreen(); }catch(error){ onFullscreenChange(); } }
Let’s stop here and take a look at the different lines here.
The first thing in the function is a try/catch and is imperative, not for video but for good coding practice. I guarantee things are bound to fail on other browsers/devices so don’t leave your code unchecked here purely due to the fragmentation between all of the browsers. On the flip you could choose to do function checks to make sure your desired functions exist or a user agent check, which we do here.
navigator.userAgent.indexOf(“Safari 5\.1”) is a simple user agent check: is it Safari 5.1? This is a terrible approach, to be honest, since 5.2 would fail when it releases or Chrome, if they add it. The better way would be to test for the functions. After the user agent check, we check to see if there is something fullscreen at the moment by using: webkitIsFullScreen(). It is important to note we’re testing against the document here, not your specific div.
If something is fullscreen, we exit fullscreen by calling: webkitCancelFullScreen(). The inverse is true if we are not fullscreen, we go fullscreen with: webkitRequestFullScreen().
That’s it. You’ll go fullscreen in Safari 5.1+. If you’re on iOS or Chrome though, fullscreen goes to the native player. By checking for Safari 5.1 only means the rest of the browser world will call: webkitEnterFullScreen(). This is where the try/catch comes in handy. If that function doesn’t exist, the catch portion will kick in and you can do a pseudo fullscreen.
If you go fullscreen with the above you’ll get the same exact div in the middle of the screen at the same size. To fix this, just tweak your CSS a bit.
Pseudo Fullscreen
Wait, I leave you hanging with CSS then label this section Pseudo Fullscreen? Yep. Simply put: they are one in the same. I’m no CSS guru so I’d love to know how I could clean this up or improve on it.
.fullscreen{ position:absolute; left:0; right:0; top:0; bottom:0; width:100%; height:100%; overflow:hidden; } |
I’m simply forcing it to an absolute position, touching each corner, full width/height, and hiding any overflow. What’s odd is IE9, without overflow:hidden;, caused video flickering at 100% width/height. This was really weird but turned out to be a simple fix.
What I do is toggle this class [again, with jQuery] on my div and the video so it applies the appropriate styles:
function onFullscreenChange(){ $("#mydiv #myvideo").toggleClass("fullscreen"); } |
Why the video? If you don’t, your video will stay the same size and not resize to the browser. <video/>, much to my surprise, actually properly letterboxes [puts black bars on top/bottom or left/right of video with proper resizing] your video. Sweetness!
Remember this method is called in the catch from above to trigger an in-browser [or pseudo] fullscreen, what I like to call full view, but the method is named onXXXXX on purpose. That means it is an event handler, based on my coding style, in every language I know/use.
Listening for Fullscreen Changes
The last piece to fullscreen is knowing when it happens.
$(document).bind('webkitfullscreenchange', onFullscreenChange); |
When listening for this event you don’t have to maintain the state, since it is already maintained by the browser [don’t duplicate the wheel]. You can also do anything in the event handler. It is your page/experience so your call.
Note: Don’t worry about binding to an event that doesn’t exist as jQuery will not throw an error.
Final Thoughts
Using the above code feels good, as a video/media developer. You really do get a great fullscreen experience from your HTML5 video in Safari. Kudos Apple! I want this experience across every browser…like…now!
It is common practice to also set your video background to black. Be creative though. Maybe try a black background on #mydiv but lower the transparency a bit so you can slightly see through. CSS rocks and you have full control.
Keep your eye’s open. Video is moving fast, as an industry. Plenty of video love coming in the near future and I. LOVE. IT!!
Sidebar: Elephant in Room
I’ve seen a few posts about this taking a feather out of Adobe Flash’s hat. I won’t go there but know any enhancement to HTML5 is better for us all. Why mention it if I won’t discuss it? Simple. I don’t want to see comments about it. 😉 I’ll address that in another post, if so desired.
Update 7/29/11
In my production version I updated the browser check to use something good vs the dummy check I did above for “Safari 5\.1”:
if(navigator.userAgent.match(/(Macintosh|Windows|Safari|Version\/5\.[1-9])/gi).length >= 3) |
A fellow dev, Ryan Gaspirini, suggested not to browser detect. He even used an exclamation mark in his comment so it he’s serious about it. 🙂 His suggestion, as was mine above, is to do a function check:
typeof document.webkitCancelFullScreen === "function" |
Great suggestion.
I also hit a snag with using the above fullscreen approach on the iPad [that’s what I get for blogging at 4 AM]. The iPad does not respect the preload attribute on <video/> so if you go fullscreen prior to hitting play the pseudo fullscreen will trigger. What happens is the metadata isn’t loaded until you start playing so Safari [on the iPad] doesn’t know whether you can go fullscreen or not. This causes an error when calling webkitEnterFullScreen. The docs explain it as this:
webkitSupportsFullscreen
A Boolean value indicating whether the video can be played in fullscreen mode.
readonly attribute boolean webkitSupportsFullscreen
Discussion
true
if the device supports fullscreen mode; otherwise,false
. This property is alsofalse
if the meta data is loaded or theloadedmetadata
event has not fired, and if the files are audio-only.
To get around this simply disable your fullscreen button [I simply added a class to change the button image] until metadata is loaded [listen for the loadedmetadata event]. Once it is loaded, enable it and fullscreen will work as expected on the iPad.
Also make sure you add a check in your fullscreen button click handler to make sure it is enabled. I did mine like so:
if($("#myfullscreenbutton").hasClass("disabled")) return; |
For more information, visit the HTMLVideoElement spec on the Safari Dev Center.