Go back to home page of Unsolicited Advice from Tiffany B. Brown

input type="url", validation and user interfaces

Recently a friend messaged me about the url input type, and how to prevent Opera from automatically prepending http:// to the value of a URL input field if it is missing. I think I've found a workaround, but first, I want to discuss the url input type, and how different browsers handle it.

HTML5 introduces several additional types for the input element. One goal of these additional types is to offload error checking from the JavaScript layer to the browser. The HTML5 specification includes rules and patterns for data validation, including for URLs with the url attribute value.

According to the HTML5 specification, a URL is valid when it is not an empty string, and is a “valid absolute URL.” A complete definition of what constitutes a valid URL can be found in RFC 3986 and RFC 3987. The short version is that a valid URL must, at minimum, consist of a scheme (https://, ftp://, gopher://) and a host name. If it does not, validation should fail, and the browser should throw an error.

Now most recent browsers* take the following steps when it encounters an invalid URL such as foo.com or example:80.

  1. Fire an invalid event on the element in question.
  2. Display an error message to the user.
  3. Prevent form submission.

To prevent careless input errors and guarantee validation, Opera will automatically prepend http:// to the value of a URL input field if it is missing when the field loses focus (and if no pattern attribute has been added). This means that the invalid event usually will not be fired.

Of course, "most recent browsers" does not mean "all." To date, Safari will fire the invalid event, but it will do so silently. No error message will be shown to the user. Form submission will succeed. The value submitted will be the same as what was entered by the user. Android's WebKit behaves much the same way.

Safari also does something else differently on mobile devices: it shows a keyboard layout that is optimized for typing URLs, complete with a .com virtual button.
The iOS

Back to my friend's use case: he wanted the benefit of mobile Safari's UI sugar, so he was using <input type="url">. He was unconcerned with whether the URL was valid because he was using server-side validation. His primary goal was ease of data entry for domain names on iOS devices.

However: that isn't really the purpose of <input type="url">. Validation is, and a domain name by itself is not a valid URL.

But since the ship has sailed, the horse has left the barn, and the chickens have flown the coop, let's talk about how to prevent Opera from automatically prepending http:// to the value of a URL input field.

To do this, we need to do two things:

  • Add a novalidate attribute to the form element.
  • Add a null pattern attribute to the field element.

For example:

<form action="../form.php" method="post" novalidate>
    <input type="url" name="uri" id="uri" value="" pattern="">
    <button type="submit">submit</button>

The novalidate attribute turns off client-side validation for the entire form. The pattern attribute override's Opera's native validation checking.

See for yourself. This will still trigger the URL-entry keyboard layout in iOS browsers, while killing Opera's prepending.

If you use this technique, keep in mind that server-side validation is even more important. Because we are not providing any constraints on this data, we have increased our chances of getting invalid or malicious data. You should be validating anyway, however, since it is not 100% possible to guarantee that the data reaching our form script has actually come from our form.

*And by "recent browsers," I mean the latest versions of Opera, Chrome, Firefox, and the forthcoming Internet Explorer 10, but not IE9.