On the styling of forms

The earliest incarnation of the specification that we now call “HTML5″ was an extension of HTML forms, called Web Forms 2.0 (Working Draft 5 February 2004 – almost nine years ago!). It contained lots of cool stuff that’s in the spec today, like <input type=”date”>, <input type=”email”>, the required attribute, and cool stuff that never made it to the final spec like <input type=”location”> and repeating templates (the latter was implemented in Opera, and subsequently removed in 2010).

When I first started talking about HTML5, I’d show these new forms controls to developers, who were all initially very excited. After all, who wants to code JavaScript date-pickers, or email validation routines? But the excitement dissipated after the inevitable question about how you can style the forms and their error messages.

The answer is that unfortunately you can’t very well. You can apply some styling – for example, making invalid or out-of-range inputs have a different border colour with CSS pseudoclasses, as defined in the CSS Basic UI module input:invalid {border:2px solid red;}, but this was badly thought out because, for example, fields with a required attribute are “invalid” at page load and therefore take the ugly styles before the user has even begun to interact with the form. Mozilla implemented their own -moz-ui-invalid mechanism that solves the problem:

If the element is required, the preceding rules apply only if the user has changed the value or attempted to submit the form.

It’s only implemented in Firefox, as it’s proprietary, but it’s a really good idea and informed a W3C proposed :user-error pseudoclass:

The :user-error pseudo-class represents an input element with incorrect input, but only after the user has significantly interacted with it.

This is good, but only deals with styling erroneous input fields. Error messages can be styled in WebKit using proprietary pseudoelements ::-webkit-validation-bubble, ::-webkit-validation-bubble-arrow-clipper, ::-webkit-validation-bubble-arrow, ::-webkit-validation-bubble-message. There’s no cross-browser proposal at W3C, but Peter Gasston has interesting ideas. The only reliable way at the moment to control the appearance of validation is turn it off with <form novalidate …> and script your own, which rather defeats the purpose.

There are no real ways of styling the controls themselves. The HTML5 spec is mostly silent on styling matters (and rightly so); the CSS Basic UI module would be a natural place for it, but that hasn’t been touched for a year, and before that update had languished for half a decade. Of course, this isn’t a trivial problem. <input type=”date”> might be rendered as a pop-up calendar widget on a desktop browser, and you may wish to “grey out” weekends – but are weekends Saturday and Sunday? or Friday and Saturday? How would you achieve that in CSS? input[type=date]::friday {color:gray;}? And the same browser’s mobile version might use the operating system’s native date picking UI, in which case it would probably be unstylable anyway.

And what of sliders? When you have a pointer/ grabber, its track and tickmarks, what would input[type=range] {color: red;} change? Bear in mind that most browsers don’t follow the one styling suggestion that the spec does offer, which is to render vertical sliders when the input’s CSS height exceeds the width.

One thing that working in the web for a decade has taught me is that where there’s a will, clever people will solve the most head-pulsing problems. But I’m beginning to wonder if there is a will. Phenomenally brainy Tab Atkins wrote

I think any arguments that sites will refuse to use the native controls because they don’t match the site’s theme are countered by the observation that most sites using JS-library equivalents today still don’t theme them very well, or at all. I usually just see a very plain mostly-white calendar, using whatever the default color scheme is for the given library.

This doesn’t meet my experience of developers telling me they’ll continue to use things like jQuery UI because of the themes it offers.

It means that developers continue to make forms out of non-semantic elements like <div> and pile on contenteditable attributes and (hopefully) ARIA attributes and tabindex to make them accessible, even though native form controls are accessible by default.

Anne van Kesteren discusssed this in his clean markup plea:

Write whatever the fuck you want with some WAI-ARIA sugar on top is in some scenarios the only thing what works right now. I do not believe that means we should just let it run its course. The real solution to making a button implemented using five div elements and some scripting accessible is not WAI-ARIA. It is to drastically improve the styling capabilities of <input type=”button”>.

Quite.

Co-chair of the W3C HTML5 Working Group, Apple’s Maciej Stachowiak tried to get some traction for specifying form styling in 2010:

Popular sites are applying a great deal of custom styling to form controls. One example page we love to use here is google.com. If you take a peek in, say, Safari or Firefox, you can see that Google has put a lot of custom styling on the text field and the two <input type=submit> buttons on their home page. This lets them have a custom look while still working in old or obscure browsers, or in browsers with script disabled, and to provide good accessibility while maintaining fairly compact markup. But by styling form controls at all, they are in a no-man’s land in terms of standards. We need to bring this technique into the real of interoperable-specified behavior.

…but to no avail. So what is to be done? The Shadow DOM may help. Shadow DOM gives you access to the internals of browser widgets; for example, the buttons in a <video> element that the browser provides when you specify the controls attribute. It’s a work in progress, part of the suite of specifications called Web Components. Spec editor Dimitri Glazkov writes

Shadow DOM specifies that all HTML elements must behave as if they already have an existing, UA-provided shadow tree, which in turn allows the author-created shadow trees to properly override and even include) those UA-provided shadow trees.

You should be able to do the same exact thing with every other element (though there’s a very tricky issue with IMG, VIDEO, OBJECT, et al. about the nature of “the insides” of the actual replaced content that will need to be first resolved by CSS WG).

So, again, back to the CSS Working Group. I’d like to ask them, when they’re specifying the insides of replaced content, that they do the same with form controls, and give us pseudoelements.

As Tab Atkins continued:

…us devs are mostly lazy, and love being able to write a simple element instead of piping in a library just to do a crappy calendar.

Tab’s absolutely right. And developers really start to use features when they’re specified in languages they already use. We’ve seen this with CSS transitions, animations and filters, all of which were possible for ages in SVG but that was something extra to learn.

The Shadow DOM is potentially a great advance in web development, but it’s a whole new set of technologies. Allowing form styling through CSS would make it simple and allow developers to satisfy the marketing department’s demand for sliders in corporate heliotrope and goldenrod, while using native, accessible controls rather than JavaScript libraries, ARIA bolt-ons and abusing semantics.

If you’re a developer, let me know if you use the native HTML5 form inputs, or – if you use some JS library – do you adjust them to suit your site?

20 Responses to “ On the styling of forms ”

Comment by Charlie

Great post, Bruce.

While I personally think HTML 5 forms are the best thing about HTML 5 as the Opera implementation demonstrates, take up by developers has been lukewarm at best. I think that is starting to change now that Chrome, apparently developers’ favourite browser, is improving support for HTML 5 forms.

As usual, it is only when people start working with stuff, that rough edges and unthought of problems appear. Discussing this with other developers the other week some points did come across: why do we only provide one error at a time any only on submit? ie. a form has several required fields but if they are all empty, only the first will have an error message; there is no event-handling so tabbing from an e-mail field with an invalid value does not raise an error until submission.

I also think that the idea of using native widgets is so far failing in practice: at least calendars in Opera and Chrome on Mac OS look significantly less sophisticated than we’re used to. This probably needs extending to cover what happens when that isn’t the case and we might even need to consider form themes similar to what’s available on some OSes or in some window managers.

Comment by Bruce

“why do we only provide one error at a time any only on submit?” that’s an implementation decision that all browsers seem to have agreed on.

However, there’s no reason at all why, when moving focus out of an erroneous field, the error message shouldn’t pop up. The spec has nothing to say about how and when error messages should be shown.

Comment by Peter Winnberg

Very interesting post.

The thing with client side form validation is that you can never trust it. You always need to have server side validation because client side validation is very easy to bypass. With that said there are good reasons to have client side validation in addition to server side form validation because it can be much more responsive, you can for example detect some problems with the form almost instantly. So that is 2 techniques, one in the web framework on the server side and one Javascript-based one for the client side (or if you’re really lucky, the web framework could generate the needed Javascript for you) to do more or less the same thing.

This is nothing new, this alongside with widgets like small calendars that help you select a date for the form that you’re filling out has been used for many many years. And is probably why an attempt to standardize it was included in what eventually became known as HTML5.

The thing is that the way that it is done in HTML5 is completely different compared to how the developers used to do it before HTML5 came along. The question that I keep asking myself about this is why developers should move away from a solution that they know well, where they have control over the styling, and works well in older web browsers. To the HTML5 solution that has very little control over the styling and does nothing at all in older web browsers (and even the very latest versions of the web browsers do not implement everything relating to this today).

The answer is of course about accessibility, but because the styling cannot be controlled it seems like we’re back to “if we want it to be accessible then it needs to be ugly”. And I really thought that we had moved away from that.

I think that because the benefits of using the HTML5 form features are not visible enough developers will continue to use their own scripts to do this, which allows them to control the styling and also better support in older browsers. Hopefully they will include ARIA so that it will be more accessible.

Comment by steve faulkner

“why do we only provide one error at a time any only on submit?” that’s an implementation decision that all browsers seem to have agreed on.

I believe IE 10 shows multiple messages

Comment by Constantine Vesna

The joy of simple CSS, the promise of easy styling, semantic web ..

No. Sorry. This stuff has failed. Hard.

I started using css for layouts in 2003, i was waiting for css2, then css3, but now i am free of illusions. CSS is as low-level, as assembler was.

SCSS/LESS, are steps in right direction, but its too late, and too little.

WebComponents are bringing a light of hope to web applications, because developers will not be forced to fruitlessly wait for years for simplest features to get implemented.

Form styling. Yeah, “security”, – and because of that false claim – we style LABEL tags, we overlay divs, we abuse spec in every imaginable way.

What is the purpose of html5 form validation, if you cant validate anything beyond regexp matching ? (yes, there is Constraints API, but afaik its only supported(?) in FF16+) With Javascript we have had validation since 90s.

And more, – now we have touch input, we have camera and microphone input, we have AJAX (for ages) and single-page apps, – what is the place of forms in this new world ? are they even relevant at all ?


hmm, a rabitse. What a perfect illustration to current state of CSS

Comment by Charlie

@Constantine – what, exactly, is your point with reference to forms?

JS validation fails as soon as JS is not available which is on more machines than you seem to be aware of.

To compare CSS with assembler is simply to announce what an idiot you are.

Forms that provide immediate and uniform feedback to users are better forms. This is usability. Maybe you think that, as a programmer, mundane aspects like this are beneath you.

Comment by Charlie

@Steve Faulkner – thanks for the tip. I’ll see if I can setup IE 10 on my Windows 7 VM to give it a try. That is, assuming of course, that I can install it but still keep IE 9.

Comment by Bruce

@stevefaulkner I installed IE10 Platform preview (thereby obliterating IE9 it seems – gah!) . Didn’t see multiple messages. Nice implementation of slider (tooltip to show current value), no implementation of calendar picker.

Comment by Daniel

Native controls all the way for me, with fallbacks of course.
Although ideally we’d be able to style form elements to match our colour schemes (and I believe this will come eventually), users come first. If we could have a web where the usability of controls such as calendars is consistent from site to site, then I’m happy to sacrifice customisation and aesthetics.

Comment by Ivan

I’m using HTML5 input types since that can be easier to use for users on mobile devices (e.g. date pickers), but for “desktop version” I’m mostly still sticking to the components provided by UI libraries like jQuery UI—it’s easier to style, and styling is something that clients always wants. Having non-agreement on which pseudo classes and elements to use or not having that possibility at all in browsers is showstopper in majority of cases.

But I’m really looking forward to Shadow DOM, particularly for accessibility reasons and possibility of creating custom reusable components without interfering with the rest of the DOM.

Comment by Constantine

@Charlie my point is “styling of forms ? whatever, forms are obsolete”.
If you need something simple and accessible (and developed fast) – you can still use all the classic stuff: HTML 4 Forms + CSS up to lvl3, but if you want to get anything more advanced – you will need to go with JS. If your user don’t have JS – they are useless. Either they are penny-less trafic-eaters who never buy anything, or they are crappy old bots (fyi: Google and Bing bots can parse JS, at ES5 level).

___
Why i compare css to assembler ?
Because the are no variables, no scoping, no functions,
because in order to position a block – you need to position couple of other blocks so they move the target one,
because nobody uses css without some compiler/preprocessor in any big project for years already,
because working with sprites is royal mess,
because css is unfriendly both to designer (who would like visual tools) and to programmers (who want a real language),
because nobody wants to write css nowadays.

Yet, it’s simple, and good enough for its job. As all the pretty sites we see are made with ugly css.

Comment by David Goss

With the exception of buttons, I don’t try to do very much styling to form elements. IMO they should still resemble the operating system controls fairly closely so that users are immediately familiar with them and don’t how to stop and figure out how to use them.

The problem with wanting to style things like input[type=range] and input[type=date] is that you can’t be sure what kind of control will be rendered – I think the spec contains suggestions about this, rather than instructions.

If you decide, for instance, that you want some input that would require an input[type=range] but you want to do a fancy custom control with JS for it, you can still use the input[type=range] as an accessible default, then use JS to hide it on page load and update it whenever your custom control is updated.

The nice thing about having the new input types and attributes is that they double up as hooks for your JavaScript fallback – the required and pattern attributes in particular are great for this.

Comment by Patrick H. Lauke

I love the implications in David Goss’ comment. All the fancy “built-in, not bolt-on” functionality of baked-in form validation, audio/video element, etc were intended to be the default, and then feature-detect and fall back on JS solutions…but now it seems that in many cases, the opposite is happening: use your more customisable JS thing first, and fall back on the natively supported (but limited) elements instead. Brave new world…

Comment by Barney

I couldn’t submit this form when I entered ‘barneycarroll.com’ as my ‘Website’. The feedback was: ‘Please enter a URL’.

Peter Winnberg hits the crucial nail on the head which is that validation is far too simplistically defined and implemented. While WebForms were an awesome idea at the time, we’re now accustomed to JS to do this work. As you say, it’s `novalidate` or no usability depending on the capricious whims of eager browser devs ATM.

Extensible Shadow DOM is the way forward for widgets, ultimately. We love the idea of universal accessibility but we don’t want to be at the mercy of `::-webkit-scrollbar-top-left-curve-when-overflowed`.

Paul Irish hints [1] a bit at this kind of thing: in many ways the community at large has implemented its own standards that are just far too sophisticated compared to the wishy-washy, obsolete-before-release attempts at advanced native forms UX proposed in HTML5.

[1] https://github.com/h5bp/lazyweb-requests/issues/92

Comment by Chris Lienert

Styling form fields has always been a mine field and the new HTML5 fields and CSS selectors haven’t exactly improved the situation.

I use a “safe” subset of HTML5 fields with minimal styling albeit hooked into my custom JS validation library which does the dirty work.

It’s no surprise third party script libraries are used for such things given the inherent complexities involved. The wild and wandering variety of form stylings seem evidence enough that what’s in place isn’t working very well.