If you follow these seven simple guidelines, you’ll find your site looks great on any high DPI display.
width=device-widthmeans you only have to care about device independent pixels
- If you don’t set the viewport to
width=device-width, or if you use a fixed width, you’re in a world of hurt.
devicePixelRatioon high DPI devices can range from 1.3 to 3 and is about more than just phones or tablets, there are laptops too!
- Use vector images wherever possible
@mediaqueries to specify appropriate background images
- Highly compressed 2x images work well in many cases
- For sharp
canvasimages, beware of
At Google I/O this year every attendee got a brand new, beautiful Chromebook Pixel – for many, it was their first high DPI (a so called retina) laptop, and I think many people realized how, um, not so beautiful 1x images look on a 2x screen. In other words, how crappy most of the web looks on a high DPI display.
While there, John Mellor and I gave a talk covering the best practices for building sites that look good on high DPI displays. We covered the theory behind the three different types of pixels and how browsers display 1x images on 2x displays, and the best practices for making sure your site looks great on any device, no matter what if it’s a regular screen or a high DPI display.
target-densitydpi in the
viewport meta tag was recently removed from WebKit and with Chrome for Android moving forward to current revisions on WebKit, this change is now rolling out in Android. This change affects only a small number of sites because of the limited implementation of the
target-densitydpi attribute. It brings Chrome and other WebKit based browsers in compliance with the specification and matches the behavior of other modern mobile browsers.
In order to to best understand what’s changed, you need to remember that a device pixel is not the same as a CSS pixel (see CSS Pixels), and that high DPI displays are able to create crisper and sharper images by fitting more device pixels into a smaller space. This means that in order for content to appear at a normal size, the browser treats each CSS pixel as multiple device pixels and the browser scaled up assets and images to fit within the correct number of CSS pixels.
In Android browser and early versions of Chrome for Android, developers could use
target-densitydpi=device-dpi viewport value to force the browser to make a CSS pixel the same size as a device pixel, which may cause content to appear incorrectly scaled on screen (as seen in figure 1).
An Easy, Quick Fix
In most cases, if your site is affected by this change you can fix it easily by serving the same mark-up (including viewport) to Chrome for Android as you serve to mobile Safari (which never supported
Best Practices for Modern Mobile Web Sites
When designing a new mobile site, or updating existing pages, you should use modern techniques for dealing with high DPI displays; including always using
<meta name="viewport" content="width=device-width"> and a flexible layout for mobile sites. Remember, device sizes, orientations and pixel ratios vary which means that your site may be displayed on a screen ranging from 320 to over 600 CSS pixels wide.
One Other Little Note
While writing up this post, I accidentally did a search for sites that used
target-density instead of
target-densitydpi and I came across quite a few of them. If you’re using
target-density (without the dpi at the end), you can just remove it, it wasn’t doing anything!
TL;DR: If you’re using a semi-colon to separate values in your viewport meta tag, your site may break! Use a comma instead.
Browsers can be pretty forgiving most days, they do their best to fix our coding mistakes; but it’s a tough job. Most days, they manage to get it right, but trying to fix all the possible error cases is pretty hard. Worse yet, sometimes one browser fixes our code for us, while others don’t.
The viewport meta tag seems to be one of those elements that’s a little bit persnickety. The CSS Device Adaptation spec says the correct syntax uses a comma to separate the values. Unfortunately some sites use a semi-colon, which causes the browser to ignore your viewport settings completely!
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0" />
If you want to see this in action and how bad things can look, use the remote debugger with Chrome for Android Beta to change the comma to a semi-colon in the viewport meta tag on Google.com. The site will suddenly go from looking good, to looking awful.
The Developer Tools also warn you in the Console when it comes across an invalid viewport meta tag with the warning:
Viewport argument value "device-width;" for key "width" is invalid, and has been ignored. Note that ';' is not a separator in viewport values. The list should be comma-separated.
Go make awesome, but use a comma!
Using meta viewport to optimize rendering on mobile devices
What is the viewport?
Imagine if every web page you opened on your phone or tablet got the same version as your desktop, and was displayed on the small screen of your device. On a phone, that might mean you would see only the top leftmost corner, a tiny 320px by 480px view, and you’d have to scroll around the page to be able to see everything. (See figure 1). Unlike a desktop or laptop, there is no way to resize the browser window to fit the content that you want to see. Thankfully, on mobile devices, almost every modern browser scales and renders the page so that you can more easily see and interact with it, panning and zooming into the areas you’re most interested in.
Most mobile browsers define a default viewport width of 980px CSS pixels, meaning that they lay out the page on a 980px wide area, then scale it down to fit within the width of the screen. (If you’re unfamiliar with CSS pixels, device pixels, device pixels ratios, or the like, check out the Smashing Magazine article Towards a Retina Web. This works great for most desktop sites that don’t take into account mobile devices and were designed for big screens. Sites that were designed to be compatible with narrow screens however are likely to be unnecessarily stretched and scaled. For example, see figure 2 – there is no viewport set, and the image is 1600px wide, that means users need to scroll left to right to see all of the content.
The meta viewport tag allows you to override the browser default value, allowing you to adjust the display and zoom level to best suit your web page.
Using meta viewport
Setting a specific viewport width
To override the default viewport defined by the browser you simply need to add a viewport meta tag in the
<head> section of your page:
<meta name="viewport" content="width=320" />
Setting the viewport width to 320px, is similar to resizing your laptop browser window to be 320px wide, now the browser will render the page on a canvas that’s 320px wide. If your device is 320px, then you’re all set, the browser doesn’t have to do any scaling and you’re pretty much all set. Obviously not all devices are 320px wide, and your site most likely isn’t 320px wide.
But what happens if you rotate the phone from portrait to landscape, and suddenly the device is now actually 480px wide? If this happens, the browser scales the content up by 50%, so that the 320px width, so that the 320px wide document is stretched to fit in the 480px wide browser window. Unfortunately, when this scaling is applied, less content will be displayed above the fold, and the content may look oversized.
If you’ve designed a site for a fixed width desktop, for example, you know your page is 600px wide, then you can simply add
<meta name="viewport" content="width=600" /> to the
<head> of your document, which will scale the content to fit within the window. Depending on the density of your content, this may work well, but you’ll want to test it to make sure.
Adding a specific width viewport, is discouraged unless you’re adding it to a legacy site as a stop-gap measure until you can build a more responsive site.
Setting the viewport width to the device-width
Consider the sustainability of a fixed width website and how it would look given the huge variety of mobile web devices, each with a different screen size, it becomes even more of a challenge when those devices are used in landscape mode. For that reason, building your site using a responsive approach and placing it within the viewport without any zooming will help to make your site look great across all of those devices. It doesn’t need to be responsive from phone all the way to desktop, but it should at least flex from a small portrait phone, to a mid-sized mobile tablet in landscape; about 320px to 640px.
When you design your page or web app using a responsive approach, you don’t want the browser to render your responsive content in a viewport that is 980px wide and then scaled down to the tiny screen; instead you want the content to render in the actual viewport size. To do that, you can tell the browser to set the viewport to be the width of the actual device by applying the following meta viewport tag:
<meta name="viewport" content="width=device-width" />
This means the viewport will be proportional to the width of the device’s screen, for example on any portrait iPhone (whether or not it is retina) the width would be 320 CSS pixels, on a landscape iPhone 3 or iPhone 4 it would be 480 CSS pixels, on a portrait Nexus 4 it would be 384 CSS pixels, and on a landscape Nexus 4 it would be 640 CSS pixels
Setting the viewport scale
When you specify a specific value for the viewport width, the browser will automatically determine the appropriate scale factor needed. For example, if you set the
width=640 on a device that has a screen width of 320px, the browser will scale the content by 0.5.
In some cases, you may want to specify the scale used by the browser. You can do this by setting
<meta name="viewport" content="width=device-width, initial-scale=1" />
Initial scale forces the browser to an initial scale, but still allows the user to pinch-zoom on the content to be able to make things larger or smaller. By using
maximum-scale, you can set a boundary on the amount of scaling the user can do.
You can also prevent zooming by adding
user-scalable=no, or setting the
maximum-scale to the same values. This is particularly useful for mobile web applications where it doesn’t make sense to allow the user to zoom or scale content.
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1" />
Currently the user-scalable property does not work in Chrome for Android (m18).
Setting the viewport height
In addition to setting the viewport width, you can also set the viewport height. While it’s not something that’s used often, it’s good for mobile web applications that may pan horizontally only.
<meta name="viewport" content="height=device-height" />
Practices that are no longer recommended
- Adding a specific width viewport, is discouraged unless you’re adding it to a legacy site as a stop-gap measure until you can build a more responsive site (you’ll need to replace the 320 with the width of your site):
<meta name="viewport" content="width=320" />
- The viewport property
target-densitydpihas been removed from the CSS Device Adaptation specification and should not be used. It has been deprecated in Chrome for Android, and has never been supported in Mobile Safari or Firefox for Android. For more information, see Mozilla Bug 797090 or WebKit bug 88047.
Best practice for using meta viewport
- Use a comma to delimit different viewport properties. Although semi-colons may work, they do not behave consistently across browsers.
- For a responsive website, designed with mobile in mind and where the user may want to be able to zoom in to particular areas of content:
<meta name="viewport" content="width=device-width, initial-scale=1" />
- For a mobile web application where you don’t want to allow zooming of the content:
<meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1" />
Currently, the only consistent way to specify the viewport for a page is via the meta viewport tag, but the W3C is currently working on a CSS Device Adaptation, that will provide a way to specify the size, zoom factor and orientation of the viewport in CSS using the
@viewport rule. As of late 2012, only Opera Mobile 11+ and Internet Explorer 10 provide support for it using a vendor prefix.
Over the last few months, I’ve spent a lot of time thinking about how to make it easier for developers to build web applications that work offline, its a tough problem to solve. The web has the features/technology to do it, but I think there are two things preventing us from getting there easily. The first is a perception issue for users, many people think that the web only works when they’re online, no internet, no web. That leads to a bit of a catch-22, users aren’t asking for it, so developers aren’t prioritizing it. The second problem is that it requires a change in the way we build web applications. Instead of building server side web applications, we need to build more client side web applications that use web-based APIs to get what they need.
More than just ‘offline’
But applications that work offline isn’t the only reason to start using these new techniques. There are lots of other scenarios that benefit from the offline experience. For example, the intermittent connection where someone may have a connection for 5 minutes, then lose it for 2 then have it again for 3 minutes. The low bandwidth connection, for people connected maybe by dial-up or 3G modem. It also benefits the person with a great net connection – because any time you load data from the local machine, it’s almost guaranteed to be faster than if it were to come across the network. The performance benefits are pretty significant here!
Reuse the same code for different platforms
If you’re already building native (iOS, Android, Desktop) applications, you probably already have the set of server-side APIs, build your web application to take advantage of those to get the data that it needs. Architect your web application in the same way that you’re building native applications – using the same set of APIs and XMLHTTPRequests! If you’re worried about performance (and everyone should be), you should cache data locally, so that after the first time the app is run, it only needs to get the newest data from the server, and there is some available immediately at start up.
HTML5 offers lots of great ways to cache data locally, localStorage, indexed DB and web SQL. Unfortunately, the only consistently available storage feature today is localStorage, but it’s got a few drawbacks. WebSQL works across most browsers, but it has been deprecated, and could go away at some point. The recommended method, is indexed DB, but it’s not available in all browsers yet, but it’s coming. Check out http://caniuse.com for more info about implementation.
Up next – how do we get users to demand offline?
Have you ever wanted a fun and beautiful way to publish videos on your own site like the new 60 Minutes or RedBull.tv apps from the Chrome Web Store? I’m excited to announce the release of The Video Player Sample! The Video Player Sample is an open source video player web app built using the same architecture as the 60 Minutes and RedBull.tv apps. It can be customized, extended, or just used out of the box and populated with your own content.
How it works
When a user opens the Video Player Sample web app, they can choose to watch a single video or create a playlist of videos/episodes from a list that they have uploaded and populated to the app. The Video Player Sample is configured and information about the videos is stored in JSON files (config.json and data.json respectively), both of which are located in the data directory.
- A beautiful video watching experience, including a full screen view
- Ability to subscribe to shows, watch episodes, create play lists
- Support for multiple video formats depending on what the user’s browser supports (including WebM, Ogg, MP4, and even a Flash fallback)
- A Categories page with an overview of the different shows/categories available in the app
- Notifications of new episodes (when the app is installed via the Chrome Web Store)
- Built in support for sharing to Google+, Twitter and Facebook
- To ensure easy customization, all source files, including the Photoshop PSD’s, are included
How it’s built
- Compiled with the Closure Compiler
- Distributed through the Chrome Web Store to take advantage of notifications
In addition to working as an app that can be installed through the Chrome Web Store, the Video Player Web App has been tested and works in all of the modern browsers.
Try it out
You can grab the code from Google Code.
Everyone wants “apps” these days, on their phone, their tablets, Apple, has the App Store to sell apps for the Mac. The demand is coming from all over the place, including consumers who have no idea what apps are, to people who are seeing this as a new revenue opportunity (which, it is)! I even heard from one developer who said that his boss came to him all panicked because he got a call from the company’s chairman of the board, wanting to know what their app strategy was. So far, most of the focus has been on apps for mobile devices, tablets, but thankfully it’s really starting to take off on the web, and we’re seeing more web apps appearing.
One piece of the puzzle that hasn’t really solidified yet is what defines a web app, and how does it differ from a web site? Are app like experiences on the web part of a website, or are they web apps? What about web sites that provide the same functionality as an app, but looks like a web site?
Is it a web site, or a web app?
TripIt is a great example, it’s concept is absolutely an app, it helps me to coordinate my travel plans into a single place where I can easily organize my trips into a single online experience. Here’s where it gets confusing, compare their web application to their tablet application. I can do exactly the same sets of things, but one looks like an application, and one looks like a website. They both let me do the same tasks, but they provide very different experiences to complete those tasks. So what is the TripIt web app, is it a site or an app?
How do we define a web app then?
A web application is an application utilizing web and [web] browser technologies to accomplish one or more tasks over a network, typically through a [web] browser.
That answer is almost as good as saying “because it’s not orange” to the question why is the sky blue.
It can’t be a single criteria
Single criteria definitions don’t work for me either. Can we say something is an app because of a single property? For example, creation vs. consumption, or architecture. Add the diversity of web apps to the mix, and I think we hit a wall when it comes to defining web apps with a single criterion.
A web app checklist
The diversity of apps makes it impossible to have a single go/no-go checklist that we can use to define apps. A criterion for one app may be completely inappropriate for another app. Instead, I think we need to judge apps based on reaching a particular bar of ‘app-y-ness’.
- Does the app have a tight focus around a single point or purpose?
- Is the app self-contained, keeping me within the app to complete my task?
- Does the app encourage interaction, engagement and completion of tasks?
- Does the app look beaultiful and have a rich user experience?
- Does the app have an action oriented interface that uses similar paradigms to native applications, for example dialogs, buttons instead of links and new pages?
- Is there at least a functional offline experience?
- Does the app take advantage of the capabilities of the device, like geolocation or device motion?
- Are traditional websites elements and links are hidden from view?
- Is the app architected to uses a primarily client side architecture model?
Now, let’s look at TripIt’s web “app” vs. their tablet app:
|Web “app”||Tablet app|
|Encourage interaction, engagement & task completion||Yes||Yes|
|Beautiful & rich user experience||Maybe||Yes|
|Action oriented with native design paradigms||No||Yes|
|Traditional website elements hidden?||No||Yes|
|Client side architecture||No||Yes|
By this criteria, even though their web site is super functional, I can get the things done that I want and has some of the qualities of an app, it clearly could be more app-y. Could TripIt build the same experience as a web app? Absolutely! Heck, it might even be less work because then they could reuse a lot of their design and UI components across the web and tablet versions.
But who really cares?
I do! With more and more people demanding apps, I think we’re missing a huge opportunity to provide our users with web applications that are better, faster, and more fun to use than their mobile or native counterparts. People will pay for mobile and native applications, but we have given them very few web apps that are worth their money. We need to step up and change that, let’s build a more app-y web.