Sunday, January 1, 2012

On the Eight Day of PhoneGapping: Multiple Screen Sizes

This is another question that comes up on the mailing list frequently, how do you support multiple screen sizes (portrait, landscape, phone, tablet)? Luckily there is a pretty good technique in web development that can be used in your PhoneGap application. It is called responsive web design and there is a book by Ethan Marcotte coincidentally called Responsive Web Design that I've recommended so often that I feel like I should be getting a kick back from the author (Full disclosure, I don't get a kick back). The book is only $9 and after you are done reading this post you should just go buy it.

In a nutshell, responsive web design uses CSS media queries to determine the width of your display and deliver different layouts based upon screen size. This would allow you to show a single column interface to portrait based phone users of your application but a multi-column approach to landscape table users. Let's run through a quick example.

For our phone users we'll setup our CSS so that our navigation sidebar shows up at the top and the main area of our application is underneath it. That would require some CSS that looks like this:
#wrapper {
            width: 90%;
            min-width: 0;
          }
          #main {
            margin-left: 0;
          }
          #sidebar {
            width: auto;
            float: none;
          }
We'll set our wrapper div to have a width of 90% because we don't want any text going right up against the screen as it make it hard to read. We'll give our main content a left margin of 0px so it is left justified against the wrapper div. For our sidebar we'll make the width auto so all the text will fit. So you app will look like this:


Now for the tablet version of the app you have a lot more screen real estate to work with so you want to have two columns. The left column will be the sidebar for navigation and the right column will be the main content area. Your CSS will look like:
#wrapper {
              width: 80%;
              margin: auto;
            }
            #main {
              margin-left: 40%;
            }
            #sidebar {
              width: 40%;
              float: left;
            }
The first thing you will notice in the CSS is that the wrapper div width is now 80% as we have more screen to work with so we can pad the sides a bit more. The main div is going to float over to 40% of the width of the wrapper div and the sidebar will be 40% of the wrapper div floating to the left side. And your app would look like this:


So that is all well and good but how does our app choose which version of the CSS to use depending on if it is running on a phone or tablet. Well that is the magic of CSS media queries. We'll wrap up our CSS with:
@media all and (max-width: 800px) { ... }
for the phone version of the CSS and:
@media all and (min-width: 801px) { ... }
for the tablet version. Simply screens up to 800px will get the phone version of the CSS and any screen over 800px wide will get the tablet version.

Here is a full HTML file for you to test out.


Interestingly enough for Android 3.2 and greater they've adopted a similar technique to responsive web design to handle multiple screen sizes on Android.

7 comments:

  1. Thanks so much - for the book recommendation and code. No excuses not to properly support tablets now!

    ReplyDelete
  2. You know you could get some kickbacks if you link to the book on amazon with an affiliate acct.

    ReplyDelete
  3. @Loren

    Yup, but I think the book authors will get better residuals if the book is sold directly from A Book Apart so I went with linking to them.

    ReplyDelete
  4. Hi Simon,

    Thanks for the recommending the book.

    I used the CSS styling to set widht and height of my wrapper to 90%.The problem is my UI seems to extend off the bounds on >160dpi screen....like the WVGA800 emulator with more than 160 dpi density.Below or equal to the 160 it adjust perfectly to the screen.I am still finding a solution for this.
    Another problem would be the "window.innerWidth" and "window.innerHeight" attributes.Just couldn't rely on them for adjusting my Layout.On Samsung Galaxy S2 it gave two distinct values simultaneously for each width and height.Also on my iBall Slide tablet it swapped the values with width for height and vice-versa.I had to write a native method in my Activity to calculate actual screensize and then call it in my JS....Can you suggest something better?.I need to the device dimensions because I am generating my UI layouts from a webservice call and adjust to both Landscape and Portrait Orientations.

    Thank you

    ReplyDelete
  5. Thanks, if I ever get to using Phonegap this will be very helpful!

    ReplyDelete
  6. Thanks Simon. Very easy to understand.

    ReplyDelete