My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, September 19, 2013

iOS7 - The Return Of The Splash Screen

Spoiler: code and examples showed or used in this post are meant to be working, for demo purpose, on iOS7 iPod or iPhone only. One day I might improve the demo in order to work the same in other browsers too.

If you haven't read yet this great post from @firt entitled Safari on iOS 7 and HTML5: problems, changes and new APIs you probably should before you can understand what is this about ... done? Great!

Some Clarification

Maximiliano took mobile twitter to show what happens when you visit a webpage in landscape mode where no previous, well known and tested, iOS trick would make it in order to have a better, full screen resolution.
However, problems are the same in the portrait mode: there's no way, if you use any overflow: auto; or touch in your page, to see the magic morph happening in the surrounding Safari Mobile UI.
On top of this, when you apply or pay for Apple Beta Testing or Developer, you are under an NDA/EULA you can hardly report problems even to Apple itself since it's very easy to be in troubles even saying "hey, I've tested stuff here and didn't work" ... where the place is publicly reachable and you are showing premature problems... right?
... oh well, back to this post ...

ReIntroduction To Safari Mobile Full Screen

One example is usually better than thousands of words ... so here the example that will work as expected on iOS7 on iPod or iPhone, 'cause as Maximiliano said in his post, there's no way to obtain a proper full screen on iPad (but probably that ain't needed anyway).

It's very important that you visit the example page before I can explain what is this about so please do it and come back after if the source code isn't explicative enough :)

Insert Coin, And Press Start!

Even if the Wikipedia definition is jurassic, since the splash screen has been used in Flash WebSite since ever and most of the time in a totally dynamic way, Apple gave us only one possibility to have a full screen on its devices: we need to teach the user how to reach a full screen experience!

Actually Not So Bad As It Sounds

Thanks to CSS position:fixed and a background that keeps moving regardless in the OS itself, we could make the road to the full-screen playful and fun.
Somehow, reaching the full screen in the phone through the browser could be used as leveling-up the user itself when it comes to a game.
In my example you can try to rotate, change, do things with the device, until you reach again the full screen possibility. Why couldn't this be an option? It works in both portrait and landscape too and we have an extra "bonus" for the playing user ^_^
As summary: isn't a playful splash screen a way less boring introduction to an app or game than just a static image, as native apps guys are used to these days? ;)

The Trick In A Nutshell

In order to be able to reach a full screen in iOS7, the body of the document must have style.height = (screen.height + 1) + 'px';, where the height needs to be the width once in landscape ...
And that's pretty much it! Test This Page if you don't believe me, and you'll notice that just scrolling up in both portrait or landscape section you'll find yourself on a full screen.

Enjoy yet a new modern web era hack because we haven't learned yet that W3C APIs are there for good reasons and nothing bad would have ever happened simpyl following them rigorously.

Pssss, hey ... in portrait, just screen.height will do, without the plus one ... however, plus one puts the browser in a sort of "must go full screen" state so ... you've been warned ;-)

Is iOS7 Full Screen ?

If you'd like to go dirty and obtrusive with this approach, here a very simple functions that could help you instruct users when you recognize the screen is not full anymore:
function iOS7isFullScreen() {
  return Math.abs(orientation) == 90 ?
    innerHeight == 320 :
    innerHeight == 529
Feel free to adjust size if needed or use display to check when is necessary and not, as example, in a setInterval.


Ian Ippolito said...

Andrea, kudos to you for coming up with a creative solution to this. It's the 1st one that I've seen so far...everyone else is just complaining and scratching their heads. So great job there. Unfortunately, even after forcing the user to do a swipe, it isn't necessarily permanent. If the user rotates the device after swiping, the address bars come back again. If a user is playing a game in bed/laying down this can happen, for example. I suppose the user could be forced to swipe again, but I think many users might get upset with that.
Still, this is the best solution yet. So good job on that.

Andrea Giammarchi said...

Ian thanks but as I've been creative, developers using this solution should use some creativity too :-)

The very first time it goes full screen it's the time you have full size and you can store it either in localStorage or in RAM and check on rotationchange if things changed badly.

You can put the game in pause and ask the user to swipe again.

Bear in mind the use case is the real one, where the user will use the phone in only one way (either portrait or landscape) and the rotation accident would be sporadic so that it isn't a real world problem, imho, but I agree it might happen.

Last, but not least, this solution is in any case not so user friendly due edges swiping behavior, something only once pinning the app in the home screen improve.

So, this is actually the even better solution: instruct the user how to pin the app to the home screen so that it will be a full size, no edges problems, situation.

Good luck and remember to complain with Apple too :P

Ian Ippolito said...

Hi Andrea,

Yes, complaining in full force! :)

I agree that one solution *should* be pinning it to the homescreen. However, iOS7 introduced several severe bugs (that only occur in that mode), that cause hangs, apps replacing other apps, cookies not working, etc.

If Apple gets it working smoothly and fixed, then it will be the best solution.

>>The very first time it goes full screen it's the time you have full size and you can store it either in localStorage or in RAM and check on rotationchange if things changed badly.

Let me give you an example. My current app runs in landscape and most of the time Safari correctly runs it in full screen ( didn't do this in early betas of iOS7)! So it actually works most of the time. But, it doesn't work reliably. For example, if the user refreshes the page in landscape mode, the browser forgets it's in full screen and nav bars show (even though orientation didn't change). Same with redirecting to a 3rd party website (for payment processing, login) and coming forgets and the nav bars show (even though orientation didn't change). I have not found a way to progamatically detect with certainty that the nav bars are/or are not showing. For example, Javascript/CSS return the same height, whether or not nav bars are showing (which is obviously a bug/incorrect).

Right now I'm forced to post a dialog at the beginning warning iOS7 users that at random moments the nav bars might cover the app, and if it happens, that they need to rotate to portrait and back to workaround it. Obviously this is not ideal! :)

Anyway, I like your blog...lots of great posts and interesting reading. Keep up the great work!

Andrea Giammarchi said...

I've just updated this post with extra info on how to detect if it's full screen or not. The function is called iOS7isFullScreen

Ian Ippolito said...

Andrea, huge *like* on your new code addition, and am going to try it right now! Thanks for sharing!

Andrea Giammarchi said...

bear in mind `display` won't probably fired on `resize` because Safari Mobile on iOS7 doesn't so the `setInterval` for such browser might be the only sad way to solve this.

In that case, `setInterval(checkAndNotify, 1000)` should be a decent compromise.