When To Use The Button Element

Avatar of Chris Coyier
Chris Coyier on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

You use it when, uhm, you want a button on your page that users can click, right? Well, unfortunately it’s a bit more complicated than that. It’s not too bad though, let’s figure it out.

It looks like this:

<button>
  Do Something
</button>

What’s the most common result of clicking something on a website? Moving to a new URL, like you would clicking a link (an <a href="/example/"></a>) element).

The <button> element, by itself, can’t do that. There have been various conversations about allowing “href anywhere” over the years, but nothing has came of it.

Clicking on a button does do something though, when used in its natural environment…

Button is a Form Element

Web forms have submit buttons. You might think of that like this:

<form action="/" method="post">
  <input type="submit" value="Submit">
</form>

A <button> element in a <form>, by default, behaves identically to that submit input above.

<form action="/" method="post">
  <button>Submit</button>
</form>

However gross the UX, forms can have reset buttons as well. You can duplicate that behavior by changing the default submit type to reset.

<form action="/" method="post">
  <button type="reset">Reset</button>
</form>

Clicking that button will clear all the other inputs (and textareas) with the parent <form>.

Buttons can have content

The primary reason for using a <button> is that it has both an opening and closing (</button>) tag. Which means there can be stuff inside. A common use case would be something like:

<button>
  <img src="tiny_birthday_cake.png" alt="">
  Submit
</button>

While an input can be <input type="image">, this mixed content would be hard to pull off.

You can probably get away with putting just any HTML inside a button, but MDN points out the “permitted content” of a button is limited to “phrasing content”. Phrasing content is a limited subset of HTML elements that “defines the text and the mark-up it contains. Runs of phrasing content make up paragraphs.”

Pseudo elements can be used too.

Let’s leave styling <button>s for another day, but different browsers generally have a special style they apply to buttons. You’ll want to either leave that alone so the default comes through or remove it thoroughly so your new styling can be consistent across browsers.

Let’s consider: “if a button doesn’t have a meaningful href, it’s a <button>”

I said recently that I enjoyed that sentiment. That’s what kicked off this article for me. At the time, I was thinking of how I enjoyed the semantics of it. As in:

<a href="#0">
  I'm kinda sick of doing this for buttons.
</a>

There is no meaningful href there. The 0 is just there so it doesn’t jump the page, because ID’s can’t start with a number.

Chances are, HTML like the above means: I’m going to make clicking that do something with JavaScript. Somehow that feels better than a <div> whatever, because you get the cursor change and whatever else default styles.

If you don’t like those meaningless href’s, a <button> can seem like a nice alternative. But unfortunately outside of the context of a <form>, a <button> is equally meaningless.

<button>
  Outside of a <form>, I'm just as useless.
</button>

But <button> feels better anyway

Even if a <button> doesn’t do anything outside of a form without the help of JavaScript, it still feels better for things you can click that do stuff other than change pages. A bogus href link definitely doesn’t feel right.

Alright. Let’s insert it with JavaScript then.

That’s probably the best solution. If JavaScript is required for the clickable-thing to do anything at all, it might as well not even be there at all unless JavaScript runs. We can do:

// 1. Create the button
var button = document.createElement("button");
button.innerHTML = "Do Something";

// 2. Append somewhere
var body = document.getElementsByTagName("body")[0];
body.appendChild(button);

// 3. Add event handler
button.addEventListener ("click", function() {
  alert("did something");
});

You could easily have “button adding” be a part of your JavaScript workflow.

When links make more sense

If there is any kind of href you could put on that link that makes sense, by all means, use an anchor. Even if you override that behavior with JavaScript. That’s progressive enhancement at it’s finest. For instance:

  • A search button normally triggers a type-ahead ajax-search thingy – but the href could just point to a /search/ page.
  • A publish button triggers the the next stage of publishing something a user built – but the href could just point to a /publish/ page.
  • A thumbnail button opens a lightbox with a larger version – but the href could just point to the URL of that larger version.

If nothing makes sense, insert the button with JavaScript.

Accessibility concerns

Let’s say using an anchor link does make sense. After you give yourself a nice little back-pat for being good at progressive enhancement, there is accessibility to consider as well.

You might be like, I got this!

<a href="#meaningful" class="button" role="button">
  I'm good
</a>

But you aren’t out of the woods yet. MDN covers it well:

Warning: Be careful when marking up links with the button role. Buttons are expected to be triggered using the Space key, while links are expected to be triggered through the Enter key. In other words, when links are used to behave like buttons, adding role=”button” alone is not sufficient. It will also be necessary to add a key event handler that listens for the Space key in order to be consistent with native buttons.

Get that? You activate links and buttons with different keys, so consider that.

Go forth and uhm, make clickable things correctly.