ProPublica

Journalism in the Public Interest

Cancel

The ProPublica Nerd Blog

Adaptive Design, Fixed Widths and Tablets

.

If you’re trying to make your fixed-width site adaptive, there are some things you need to know about the viewport tag.

If you don’t know what viewport is, there are some excellent developer guides on the web that will catch you up. Peter Paul Koch has a great technical primer on using viewport with media queries, and Apple’s documentation on how viewport works on Mobile Safari is quite detailed and clearly written.

Briefly, viewport is a meta tag that was created by Apple to give web developers control over the behavior of the layout viewport in Mobile Safari. Imagine the layout viewport as a little window that is as big as your mobile device’s screen. When you scroll around a page in Mobile Safari, you’re actually moving that little window around a larger web page. Likewise, by “pinching” the screen, you’re really setting the zoom level of the window relative to the page behind it.

Viewport isn’t actually a true standard, but other mobile browser vendors support it, though not without some quirks. The part we’re talking about here generally behaves the same in most mobile browsers: When you set your viewport width to device-width, it disables “overview mode,” which is the behavior whereby the larger web page fits inside the viewport window and everything is very zoomed out until you pinch open or double click on parts of the page.

That’s just fine if you’ve got a fully responsive, fluid-width site, which stretches or shrinks to the full width of the screen no matter what the screen size is set to. But that’s not at all what ProPublica has. We’ve got a pretty traditional fixed-width site, with a single adaptive “break” for a mobile screen. On our site, smartphones get a full-width 320 pixel-wide page, and desktop browsers see the full 960 pixel-wide page.

In all of our testing, everything looked great — until we spent some time testing on tablets. Because we set the viewport width to device-width so the media queries would work their magic on narrow screens, tablets simply disabled overview mode and loaded our pages at their full desktop width. The tablet screens showed as much of our pages as they could and hid the rest. The Kindle Fire (device-width: 600px) was particularly forlorn, and the iPad (device-width: 768px) showed some elements in overview mode but somehow set background images to the wrong size, with unspeakable results.

We liked overview mode on tablets, so after trying a few things, we hit upon a workable solution: In order to restore the old overview mode behavior, we created a media query for each tablet we wanted to target and used CSS zoom to shrink the page to fit when it first loads.

Rather than using the width media query, we used device-width so that the styles would only be applied if the screen was a given size, not just the browser window. That way we weren’t applying a new set of styles when people’s browser windows happened to be open to a certain size.

To get the zoom value we simply divided the apparent device width by our optimal width (985px), and multiplied by 100. Like so:

<meta name="viewport" content="width=device-width">
<style>
  /* Samsung Galaxy */
  @media screen and (device-width: 800px) { html { zoom: 81.21827%; } }
  /* Kindle Fire */
  @media screen and (device-width: 600px) { html { zoom: 60.91370%; } }
  /* iPad */
  @media screen and (device-width: 768px) { html { zoom: 77.96954%; } }
</style>

But, but…

Sure, we could have done this via JavaScript and made it more dynamic. You can target viewport in WebKit browsers, and we suspect changing initial-scale would do as good a job as our CSS zoom technique. But there would have been a visible flash after the page has rendered, which we wanted to avoid.

Also, as SASS converts, we thought to make a SASS mixin out of this, but we discovered that SASS doesn’t allow variable interpolation in the @media directive. So for now we’ll need to have a media query for each tablet screen width. Not ideal but not the end of the world by far.

By passing along our solution we’re hoping that either somebody way smarter than us will see a more elegant or effective fix, or somebody hitting the same problem will find this solution helpful.

Portvie.ws

We made a very simple web page you can use with devices you’re testing. It displays what the handset thinks the layout viewport dimensions and screen width are. Go crazy: www.portvie.ws

Further Reading

Great tutorial!  I was able to fix a scaling issue I was having with my Nexus 7. I did notice an odd behavior though. .

The Samsung Galaxy Note and the Nexus 7 both have the same resolution (1280 x 800).  The code works nicely with the nexus,  and I figured that it should work the same on the Note, but instead the page on the note is not zoomed out at all.  Any ideas on why that would be?

Rafał Komorowski

Dec. 30, 2012, 1:56 p.m.

Hi. Thanks for the http://www.portvie.ws tool - it was very helpful for my recent development and learning. However I noticed that it reports false values on my iPhone 4S (iOS 6.0.1) - device is still 320*480, instead of 640x960. For all other devices and emulators I’ve checked, it reports real hardware values. I’ve checked it on iPhone 3G, Samsung Galaxy Mini II, Galaxy S II and emulators: Opera Mobile Emulator for Mac (various phone/tablet settings) and Android Emulator from Android Development Toolkit. Any hits why?

Rafał Komorowski

Dec. 30, 2012, 2:35 p.m.

Answering to my own question: as in: http://www.javascriptkit.com/dhtmltutors/cssmediaqueries.shtml “On an iPhone- including iPhone 4, the device-height is 480.” But why emulators and real Samsung Galaxy S II with Firefox report hardware values?

Add a comment

Email me when someone responds to this article.