I’ve been delaying this post since I wrote a rant about the iPad. The delay is mainly because I never found time to create sample files or record screencasts showing the bugs so I decided to publish it without any working examples since I don’t think I will have enough time or patience to isolate the problems and document it anytime soon, so you will have to believe that what I’m saying “is true” and that the bugs exist… Think of it as a reference in case you have any of those issues and not as a definitive way of making those things work, some bugs are only present on older versions of iOS and may not be easy to replicate. I’m sure I will leave a lot of important stuff behind but at least I’ll try to cover some bugs and how I solved them. I will try to be brief.
Bugs and Hacks
The HTML5 video element have a
preload attribute, which is used to specify if any data of the media element should be loaded before an user interaction, unfortunately Apple decided to not support this attribute on iOS to reduce bandwidth usage.
Here is an example of the code required to preload a video after user interaction on iOS 3.2+:
As you can see on the code comments it requires a series of hacks to make it work properly.
PS: On previous versions of iOS you could simulate a click event to trick the browser to start downloading the video but I don’t recommend using any technique that abuses flaws on the system, it can cause way more troubles than it solves, future updates on the OS may invalidate your whole application.
Loop video / Seek
The HTML5 video element have an attribute
loop which doesn’t work on iOS (as of iOS 4.2), the video element also expose the property
currentTime which is used to read the current playback position or to seek to a specific position. Setting
currentTime to zero on “all” browsers makes the video start playing from the first frame, unfortunately doing that on iOS 3.2 breaks the
currentTime property (value isn’t updated during playback) and also breaks the
ended event dispatch. The way to fix it is to seek to
0.1 instead of
0. Here is an example of how to make an inline video loop (won’t work on fullscreen play).
Seeking to float point numbers with a single decimal digit in my case also solved some weird seeking behaviors on iOS 3.2. So instead of seeking to
12.3456 I started seeking to
12.3 - I haven’t done exhaustive tests on this but on my case it worked fine and I wasn’t able to replicate the bug anymore.
Hide QuickTime logo
The iPad displays the QuickTime logo sometimes while the video component is being instantiated, this can be very annoying and sometimes it can take a long time before it downloads the video metadata and/or poster image. My first attempt to solve this issue was to add an overlay on top of the video while it was loading and then fade it out after the video started to play or just set the video opacity to zero (since I wanted to fade the video after it finished loading), but unfortunately the QuickTime logo doesn’t respect the z-index or opacity of the video element, so it appears over any element. Another issue that I’ve found out is that setting
display:none blocks the video download and that
visibility:hidden also doesn’t solve the issue.
The solution is to set
-webkit-transform:translateX(-2048px) on the video element (any value small/big enough to push the video outside the window area) than listen for any of the media data events (progress, loadedmetadata, load, canplaythrough, etc..) and set
video.readyState gets bigger than
1, that way the QuickTime logo will be off the screen while video is getting ready to play. After that moment you can even fadeIn the video and or add overlays on top of it.
In some cases it was also breaking the z-index of the video and overlays, after applying the translate hack the z-index bugs disappeared.
Play button doesn’t show up on the placeholder
In most cases I still find that having a simple link pointing to the video file is the simplest and most reliable solution for video playback on mobile devices, specially since some devices cannot play files while progressively-downloading it but can play the same video files if they are downloaded to the device (Blackberry and some Androids), iPhone and Android will still play the video fullscreen using the native media player as if it was an HTML5 video tag (if files are properly encoded and served with right mime-type).
Click and touch events
Click and touch events doesn’t work properly on a video element, it seems that the video element doesn’t bubble the events. The way to “solve” it is to add an overlay on top of the video and attach the events on the overlay. (thanks Hugo for reminding me that this issue exists)
It’s important to notice that items over the video element will only trigger click/touch events if the video player isn’t using the native controls.
As a said before on another post, the closer to the edge you are the more problems you find and since HTML5 video and the iPad itself are fairly new technologies, they still need a long time to mature and become stable. This post doesn’t cover all the bugs I’ve found and all the tricks I came up but it covers some of the most recurrent ones. I focused on the iPad and HTML5 video since it was the major cause of headaches on one of my last projects but Google Chrome also have some strange rendering issues and other bugs as well… - Developing cutting-edge websites for the iPad is not as “magical” as Steve Jobs wants you to believe.
- User Control of Downloads Over Cellular Networks
- Making HTML5 Video work on Android phones
PS: a lot of people commented on my other post that “all” iPad users update the OS constantly but on one of my latest projects 17% of the iPad users where still using iOS 3.2 (version that came with 1st gen iPads) and I don’t want 17% of the users (and specially the client) thinking that the website is broken while in fact the fault is of their broken OS…