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
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
- Fire an
invalidevent on the element in question.
- Display an error message to the user.
- 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.
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
novalidateattribute to the form element.
- Add a null
patternattribute to the field element.
<form action="../form.php" method="post" novalidate> <input type="url" name="uri" id="uri" value="" pattern=""> <button type="submit">submit</button> </form>
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.