Colm Delaney Web Design & Development

The HTML button element

The HTML <button> tag is unusual in that, when used on its own, it has no default behaviour. This conflicts with progressive enhancement principles.

The problem

When used on its own, outside of a <form> tag, <button> provides interactivity on a web page. Here's a simple example:

Problems arise when users without JavaScript try to use the element. Click on this no-JavaScript button and nothing happens:

Progressive enhancement

This behaviour violates the principle of progressive enhancement, which states that the basic content and functionality of a web page should be available to all users regardless of the capabilities of their browsers. More advanced presentation and interactivity can be layered on top of this for users with more advanced or up to date browsers.

The bedrock of progressive enhancement is semantic HTML, where every tag is selected for its meaning: you use an <h1> to mark up the heading of the page, <p> tags to mark up discrete paragraphs, <ol> and <ul> tags to mark up lists of related items, and so on.

<button> announces itself as an interactive element, and is fully accessible by assistive devices, for instance, you can focus on the button by tabbing through the page with a keyboard, and activate the button by pressing the Enter key, just as you can with <a> tags for links.

In the earliest days of the web, before Cascading Style Sheets provided sophisticated formatting and before JavaScript provided interactivity, web pages were quite crude. Pages had a grey background with black text, and page headings were enormous, with excessive space above and below.

Although authors quickly leapt on every improvement to the specification and developed ingenious tricks and workarounds to address these limitations, a properly marked up web page did its basic task of presenting content in a structured and accessible manner.

If you view such a page on either a current web browser such as Chrome or Safari, or on an ancient web browser such as NCSA Mosaic, you will have no difficulty understanding its message.

Interactive elements

Interactive elements such as <form> and <a> work perfectly well on even the oldest browsers as long as they’re coded correctly. They can be enhanced in various ways, but their fundamental behaviour is baked into their specification.

The problem with <button> is that it is an interactive element with no default behaviour to fall back on. If you view a page with a button element on Mosaic – or on any browser that does not have JavaScript, for any reason – the button will behave like the second example above, leaving the user to wonder what’s wrong with the page.

The solution

By definition, there is no way to endow a standalone <button> with default behaviour. So how do we address this problem?

Stated simply, we should not put such elements in web pages in the first place, rather we should only make them available when the necessary support for interactivity (i.e. JavaScript) is present. We then use JavaScript to manipulate a suitable default element to convert it to a functional <button>.

There are a few ways to do this. Your choice will depend on what you’re trying to accomplish with the button.

Examples

You want to display a short supplementary message

If the message is short, like in the example above, it would be reasonable to simply display it in the body of the page in the same location as the <button>. Instead of a <button>, the message would be wrapped in an appropriate content tag, such as <small>.

When the page loads, JavaScript would convert this element to a <button>, hide the message, and allow the user to reveal the message by clicking. Here’s how that might work:

Without JavaScript:

Your HTML looks like this:

<small>A short message</small>

and renders like this:

A short message

With JavaScript:

With some simple JavaScript, the same code renders like this, and will reveal the message when clicked:

A short message

You want to display a longer message

If your message is longer – for instance, a set of terms and conditions – displaying them in the body of the page might disrupt the reader’s flow. In this case, you would put the entire message in a separate web page and simply link to it.

When the page loads, JavaScript would convert this element to a <button>. When the user clicks on it, the message appears in an overlay on the page, thus allowing the user to peruse the message with minimal disruption to their flow.

Without JavaScript:

A simple link to the document in question:

With JavaScript:

With some slightly more complicated JavaScript, the same link is converted to a button, and will reveal the linked page as an overlay on the current page when clicked:

You want to provide more advanced interactivity

Let's say your button does something fancier, maybe changes the styling of the page, or does some calculation. These actions might not have a more basic fallback. What then?

If this interactivity is supplementary, it will be acceptable to omit both the <button> and the fallback element when the page loads. You can then use JavaScript to load the <button> and its associated functionality. If the interactivity is something a typical user might expect – maybe it's mentioned in the text – then you can place a brief message that gets swapped out, much like in the first example.

Without JavaScript:

Your fallback message might look like this:

The calculator feature requires JavaScript

With JavaScript:

JavaScript converts the message to a button and enables the calculator:

The calculator feature requires JavaScript.

Conclusion

No web page should have a <button> element that, for a subset of users, does nothing. Instead, always build the page with a fallback element that does not require JavaScript, and use JS to replace that with a working <button>, as in the examples above.

More information

Posted in: