[How to] Customise web form fields on Android

About two weeks back, we touched upon our custom design solution for forms on Android and why we felt that overriding the styles of the form fields was the best thing to do:

Android’s default rendering of form fields is downright fugly – they don’t follow any consistent visual language or proportions. What’s worse, is that some types of fields suffer from serious usability issues. For instance, a select box or dropdown menu isn’t very usable on touch devices because of how thin it is; an unchecked checkbox can be easily mistaken for one that is checked.

Today, I’d like to share our experience of designing custom form fields for Android using CSS. Even though we’re picking Android as an example, the steps laid out in this post should also work for Safari on iOS & Blackberry OS6.

Here’s a look at what the Android’s default form fields look like:

Reset all styles

First, we need to reset all the default styling of the form fields by applying the -webkit-appearance property. This will give us a blank slate to work with.

input, textarea, select {
	-webkit-appearance:none
	}

Here’s how things look after resetting the styles:

Base styles

Next, we put in a few basic styles to harmonise the visual appearance of different types of form fields. (We haven’t covered the radio button & checkbox here since they follow a different approach.)

select,
input[type="text"],
input[type="tel"],
input[type="email"],
input[type="number"],
input[type="password"],
textarea {
	padding: 6px 8px;
	border: 1px solid #ccc;
	text-shadow: 0 1px 0px #fff;
	-webkit-border-radius: 6px;
	background-color: #fff;
	}

You will notice that the rendering of border radius isn’t as smooth as we’d like it to be, but till Android gets the anti-aliasing right we’ll manage with this. I would suggest using a low contrast border color so that the jagged edges are less noticeable.

Text fields

We then added some touches to text fields and textarea to give it an inset.

input[type="text"],
input[type="tel"],
input[type="email"]
input[type="number"],
input[type="password"],
textarea {
	border-top-color: #666;
	-webkit-box-shadow: inset #eee 0px 0px 5px;
	} 

Select menus

We gave the selected menu a subtle gradient so that it differentiates itself from the text fields and also looks clickable.

select {
	padding: 6px 8px;
	border-bottom-color: #666;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#ddd))
	}

Remember, the key is that we don’t deviate too much from conventions that users are used to. So, let’s bring in an arrow on the right which will clearly establish the behaviour of the select menu. For the arrow, we’ll need to use a background image and position it to the right.

Alas, we cannot use the -webkit-gradient property anymore. But we do have a work around – I used an inset box shadow, to behave like a gradient– works like a charm.

select {
    padding: 6px 20px 6px 8px;
	-webkit-box-shadow: inset #eee 0 -10px 40px;
	border-bottom-color: #666;
	background: url(/images/mobile/select-arrow.png) right center no-repeat;
	}

Radio buttons & checkboxes

Now that we’ve taken care of the text fields and select menu, it’s time to work on the radio buttons & checkboxes.

It’s essential that the form fields scale nicely to different font-sizes so that you can easily use them in different contexts within the app. Therefore it’s important that we use a relative unit while defining sizes or dimensions. We will use em over px for the font-size, height and width which will ensure that the radio buttons & checkboxes are proportionate to their adjacent labels.

input[type="checkbox"],
input[type="radio"] {
	display: inline-block;
	width: 1.25em;
	height: 1.25em;
	font-size: 1em;
	/* to scale with the parent font-size */
	padding: 0;
	vertical-align: text-top;
	}

One could use the -webkit-border-radius property for the base styles, but util Android fixes anti-aliasing of rounder borders we can go with images all the way.

We will need two sets of images – one for the unchecked and another for checked state:

As you can see the images we used are much larger so that we have the flexibility of using larger checkboxes & radio buttons if we ever to and also support devices that have a higher pixel density. We will use the -webkit-background-size property to scale it down to fit within the container of the radio button & checkbox.

input[type="checkbox"],
input[type="radio"] {
	display: inline-block;
	width: 1.25em;
	height: 1.25em;
	font-size: 1em; /* to scale with the parent font-size*/
	padding: 0;
	vertical-align: text-top;
	background-position: center center;
	background-repeat: no-repeat;
	-webkit-background-size: 100%;	 /* scale background-images to size */
	}

We’ll now set the background images for two different states of the radio buttons & checkboxes

input[type="radio"] {
	background-image: url(/images/radio.png);
	}

input[type="radio"]:checked {
	background-image: url(/images/radio-checked.png);
	}

input[type="checkbox"] {
	background-image: url(/images/checkbox.png);
	}

input[type="checkbox"]:checked {
	background-image: url(/images/checkbox-checked.png);
	}

Voila! We have ourselves a new & improved look for form fields on Android.

As you’ve learnt, the process of customising the look and feel wasn’t all that difficult – thanks to the web-kit engine for its excellent support for CSS3. Having said that, I would strongly recommend that you don’t deviate too much from standard user interface conventions since users are accustomed to how things look and work. So customise responsibly and only in the interest of your users.

1 Response