Pixel-Perfect UI in the WebView

There are a number of options you can use to create the perfect UI, this article
will outline some of the best practices for the mobile web in general and then
some specific tricks you could use for hybrid applications.

Viewport

The viewport meta tag is of the most important tags you need to add to your web
app. Without it, the WebView may act as if your site is designed for desktop
browsers. This causes your web page to be given a larger width (typically 980px)
and scales it to fit the WebView’s width. In most cases, the result is a tiny
overview version of the page that requires the user to pan and zoom to actually
read content, like the image on the left.

If you want the width of your site to be 100% of the WebView’s width, as shown
on the right, you need to set the viewport meta tag:

<meta name="viewport" content="width=device-width, initial-scale=1">

Setting width to the special value device-width will give you more control over
the page layout.

By default the WebView will set the viewport to device-width, rather than
defaulting to a desktop viewport. However, for reliable and controlled behaviour
it’s good practice to include the viewport meta tag.

Desktop Sites

In some cases, you may need to display content that isn’t designed for mobile
devices – for example, if you’re displaying content you don’t control. In this
case, you need to force the WebView to use a desktop-size viewport:

If these methods are not set and no viewport is specified, the WebView will try and set the
viewport width based on the content size.

In addition to doing this, you may want to use the new layout algorithm TEXT_AUTOSIZING
introduced in Android 4.4, which increases the font size to make it more readable on a mobile
device. See setLayoutAlgorithm.

Responsive Design

Responsive design is the notion of changing your UI depending on the dimensions
of the screen size. Here we will look at some simple examples of how you can
adapt your UI and images, but if you want to dig in to other topics then this
article on HTML5Rocks
is a good point of reference.

One of the main CSS features you’ll want to use is media queries.

A media query is a way of applying CSS to elements based on a device’s
characteristics. For example, suppose you wanted to go from a vertical layout
to a horizontal layout based on orientation.

These are minor changes, but depending on your UI, media queries can help you to
make much larger changes to appearance of your application, while keeping the
same HTML.

Tip: Try to change the UI based on width as a component
starts to look out of place, rather than focusing on device sizes. By doing this,
your app will look great on a range of devices, not just the ones you test on. An
easy way to do this is play around with the size of a browser window. But remember that
actual devices have different screen densities than your monitor, so always test on a
range of devices.

Images

The variety of screens sizes and densities also presents challenges for images.
Smaller images require less memory and are faster to load, but blur if you scale them up.

The images below show the blurring that occurs when you scale a low-density image up for a
high-denity screen, compared with the crisp display of an appropriately-sized image.

Here are a few tips and tricks to make sure your images look crisp and clear on any screen:

Use CSS for scalable effects.

Use vector graphics.

Provide high-resolution photos.

Use CSS for scalable effects

Make use of CSS3 where you can for borders, drop shadows, border-radius,
and so on instead of images. These features can scale easily. However,
some combinations of CSS properties can be expensive to render, so you
should always test the specific combinations you’re using. (For some
sample data on fast and slow CSS properties, see: CSS Paint Times and
Page Render Weight
on HTML5Rocks.)

Use vector graphics

Scalable Vector Graphics (SVGs) are a great way of providing scalable
version of images. For images that are well-suited to vector graphics, SVG
provides high quality images with very small file sizes. For more
information, see Splash Vector Graphics on your Responsive
Site on
HTML5Rocks.

Provide high-resolution photos

Use a version suitable for a high-DPI device and scale the image using CSS.
This way the image has a high quality across devices. If you use
high compression (low quality setting) when generating the image, you
may be able to acheive good visual results with a reasonable file size.

This approach is simple, but has a couple of
potential downsides: highly-compressed images may show some visual
artifacts, so you need to experiment to determine what level of
compression you find acceptable. And resizing the image in CSS can be an
expensive operation.

If high compression is not suitable for your needs, try the WebP format,
which gives a high quality image with relatively small file size. See the
official WebP site for details. Don’t forget that you’ll
need to provide a fallback for older versions of Android where WebP isn’t supported.

Fine grained control

In many cases, you can’t use a single image for all devices. In this case, you can
select different images based on the screen size and density. You can use media queries to select
background images by screen size and density. You can also use JavaScript to control how images load.

Media queries and screen density

To select an image based on the screen density, you need to use dpi or
dppx units in your media query. The dpi unit represents dots per CSS inch,
while dppx
represents dots per CSS pixel.

Looking at the table below you can see the relation between dpi and dppx. 1dppx
is equivalent to 96dpi, 2dppx == 192dpi == 2 x 96dpi, and so on.

Device pixel ratio

Generalized screen density

Dots per CSS inch (dpi)

Dots per CSS pixel (dppx)

1x

MDPI

96dpi

1dppx

1.5x

HDPI

144dpi

1.5dppx

2

XHDPI

192dpi

2dppx

The generalized screen density buckets are defined by the Android native platform
and are used in other places to express screen density (for example,
http://screensiz.es).

Background Images

You can use media queries to assign background images to elements. For example,
if you have a logo image with 256px x 256px size on a device with a pixel ratio
of 1.0, you might use the following CSS rules:

You might notice that the max-height and max-width are set to 512px for 2ddpx
resolution, with an image of 1024x1024px. this is because a CSS “pixel” actually takes
into account the device pixel ratio (512px * 2 = 1024px).

What About <img />?

The web today doesn’t have a solution for this. There are some proposals in the works, but
they aren’t available in current browsers or in the WebView.

In the mean time, if you generate your DOM in JavaScript, you can create
multiple image resources in a sane directory structure: