September 18, 2012Web · Optimization · User Experience · Performance · JavaScript · Front End

Optimizing for the MacBook Pro with Retina display

As an intern on the user interface engineering team this summer, I helped build UI components that can be used across Facebook. The last project I completed before I left was to help improve the user experience on Apple's MacBook Pro with Retina display and future high resolution displays.

The MacBook Pro with Retina display presents a new challenge for desktop web development: the device pixel ratio. This ratio tells developers how many times larger than normal an image must be to take advantage of all the pixels the display has to offer. In the case of the MacBook Pro with Retina display, the device pixel ratio is 2. This means we need to send images that are twice the size of our normal images to these displays. Unfortunately the device pixel ratio is only reported through JavaScript, which means developers won't know what it is until the page has already started loading.

The reason for having a device pixel ratio is simple. While the Retina display has twice as many pixels per inch as the previous MacBook Pro, it doesn't display content at half the size. This would make normal-size websites appear very tiny and make them very difficult to read. Instead, the MacBook Pro with Retina display uses a 2x2 square of pixels to draw the same amount of content the previous MacBook Pro would draw with only a single pixel. In places where a 12pt font is called for, it will render a 24pt font at half the size to make the letters look crisper.

Unfortunately, the problem is a little more complicated for images. Most images have a limited amount of detail and most websites only send images designed for a device pixel ratio of 1. The MacBook Pro with Retina display will up scale these images to twice their original size, which produces a blurry or pixelated result. We also don't want to send images that are too large. These images will be down-scaled, which will reduce the pixel-level detail on small icons and make them less crisp.

Handling the device pixel ratio is not a new problem for mobile web developers. Apple's iPhone 4 and iPhone 4S both have Retina displays with a device pixel ratio of 2. Google's Nexus One has a device pixel ratio of 1.5 and the Galaxy Nexus and Galaxy Note both have device pixel ratios of 2.

The new problem for us was a changing device pixel ratio on desktop. A MacBook Pro with Retina display can be attached to external display that is not Retina. A browser window on the built-in display will have a device pixel ratio of 2 while a browser window on the external display will have a device pixel ratio of 1. A browser window can be moved back and forth between the two displays meaning the device pixel ratio can change after page load. Our solution needed to be ready for these changes and update the server with the new device pixel ratio appropriately.

When we approached the problem of server-side device pixel ratio detection on desktop at Facebook, we set several criteria:

  • It should make a good guess about your device pixel ratio. (If a browser window had one device pixel ratio the last time, it likely still has the same device pixel ratio the next time.)
  • It should correct itself after a refresh. (If a website doesn't load correctly, most users' first instinct is to refresh.)
  • It should try to maintain a consistent pixel ratio within the window. (If the page loaded with one pixel ratio, it should continue to be served images at the same pixel ratio in future dynamic content.)
  • It should send as few extra bytes as possible. (It's wasteful to send the device pixel ratio to the server more often than necessary.)

We met these criteria by having the server store the last device pixel ratio the browser saw, defaulting to 1. Every time a user opens Facebook or navigates to a new Facebook page, the server reports this value to the client via JavaScript. Before navigating to a new page or when closing the browser window, the JavaScript will set a cookie with the actual device pixel ratio if it is different from the value the server reported. This way there are no extra request headers unless the server had the wrong device pixel ratio.

With a standard, non-Retina display, people will continue to experience Facebook the same way they always have. With a Retina or other high-resolution display, they will now see the standard version of the page on first load, but after navigating or refreshing, they will see an appropriately high-resolution version of the page.

Andrew Zich was an intern this summer from the University of Illinois at Urbana-Champaign.

Keep Updated

Stay up-to-date via RSS with the latest open source project releases from Facebook, news from our Engineering teams, and upcoming events.

Subscribe
Facebook © 2017