codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Follow publication

A complete <dev> guide for better buttons

Krishna Damaraju
codeburst
Published in
7 min readOct 16, 2019

--

Buttons are one of the most simple, yet deeply fundamental and foundational building blocks of the web. Click a button, and you submit a form or change the context within the same page. But there is a lot to know from the HTML implementation and attributes, styling best practices, things to avoid, and the even-more-nuance implementations of the buttons — links and button-like inputs.

This article covers, building —

  • Links,
  • Buttons,
  • and Button-like Inputs

We’re going to deep-dive into all three of them, and for each, dig into the 🏗️ HTML implementations, 🖌 CSS and ⚙️ JS considerations, ❤️ Accessibility information, and ‼️ Pitfalls/Bad practices. By covering all that, we’ll have a better UX implementation of each.

Quick rules of thumb on when to use each…

  • Are you moving to another page or a different part of the same page? — Use a Link.
  • Are you building a JavaScript-only powered clickable element? — Use a button.
  • Are you submitting a form? — Use a submit input.

Links

Thumb-ruleif it navigates to other pages on or off a site or different parts of the same page, that’s a link.

🏗️ HTML Implementation

A link can be Absolute (navigates to the different domain) or Relative (to a different page in the same domain)

<!-- Absolute link -->
<a href="https://developer.mozilla.org">Check MDN</a>
<!-- Relative link -->
<a href="/about">About Codeburst</a>

And links can also be hash based or jump links

<!-- Jump link -->
<a href="#some_part_of_my_page">Scroll to Some Part</a>
<!-- will jump to... -->
<section id="some_part_of_my_page"></section>

Clicking that link will “jump” (scroll) to the first element in the DOM with an ID that matches.

Absolute and Relative can also have hash in them.

Considerations

  • Don’t use target=”_blank” on relative links. Read more on when to use target
  • Anchor link without href is called a placeholder link and is a valid syntax.
  • Anchor links don’t have disabled or aria-disabled attributes.
  • Don’t use href="#0" as a button. Use button instead.
  • Can use href="#" or href=”#” to scroll to the top section of the page.

🖌 Styling considerations

  • ‼️ Don’t remove focus styles.
  • Handle the following states of link :link (default state), :visited , :hover , :focus and:active
  • You can style a link to look as a button, but need more code to make it work as a button. So, don't !!
  • While converting webpages to PDF,
@media print {
a[href*='//']:after {
content:" (" attr(href) ") ";
color: $primary;
}
}
// read more here -> https://flaviocopes.com/css-printing/#links
  • Nesting <div></div> inside <a ...></a> is valid.

⚙️ JS considerations

  • It’s possible to intercept a click on a link and do something with JavaScript instead — Why? Single Page Apps, or doing fancy things before the redirect with window.location then use return false or preventDefault()
  • Using onClick() or href="#0" use Button instead.

❤️ Accessibility

We covered some accessibility in the sections above (it’s all related!), but here’s some more to think about.

  • Have understandable text (“documentation” instead of “click here”)
  • Don’t use the URL itself as the text
  • Images-as-links — use alt on <img .../>
  • Making a link recognized as a button? role=”button”. But is it necessary ?
  • Add accessKey for keyboard shortcuts

‼️ Pitfalls/Bad practices

  • Don’t use target="_blank" without rel="noreferrer" and rel="noopener" . Read this
  • Dont override cursor properties.

Buttons

If anything, the <button> element is underused. A good rule of thumb is that if a link has “no meaningful href”, it should be a button. Here’s another: if clicking it doesn’t do anything without JavaScript, it should be a button.

Let’s understand a button —

  • Any clickable element which can be used in forms or any part of the website to submit data or to change the context of the current view.
  • Which has focus, active, hover(optional) and disable states.
  • And importantly, which can be triggered by space and enter.

🔭 Observation

Clicking button by default focuses it in all of the Windows OS related browsers, but in Mac OS — it only happens in chrome and opera.

🏗️ HTML Implementation

General and more frequent ways implementing button-

<!--1-->
<button> Checkout </button>
<!--2-->
<button type="reset"> Reset </button>
<!--3-->
<button type="submit"> Submit </button>

🔭 Observation

A general <button></button> submits the form by default. Specify type='button' to override it.

🖌 Styling considerations

Also applies for input-like buttons

Browsers have a unique way of styling elements and tightly depends on the browser-engine of the browser and has led to the concept of Vendor Prefixes. The default style of every browser is called user-agent style of the browser. And buttons are no exception — every browser renders button differently, unless they share the same engine.

  • Make a button look uniform using Normalizer, Reboot, Sanitise or using shorthand all
  • Don’t remove the outline for a button.
  • Don’t remove :focus :disabled states.

⚙️ JS considerations

Also applies for input-like buttons

  • Handle EventBubbling and RageClicks in the buttons.
  • Handle Async state while the button operation is pending.

❤️ Accessibility

TLDR; — Focus on the clicked button must be present/return to it unless it leads to the context change.

As defined by ARIA

  • If activating the button opens a dialog, the focus moves inside the dialog.
  • If activating the button closes a dialog, focus typically returns to the button that opened the dialog unless the function performed in the dialog context logically leads to a different element.eg., Click on the cancel dialog must return the focus to the model triggering button. If the dialog has the submit button which changes the context, then the focus must set to the appropriate element in the new context.
  • If activating the button does not dismiss the current context, then focus typically remains on the button after activation. Eg., Like an Apply or Recalculate button. But not the reset button.
  • If the button action indicates a context change, such as a move to the next step in a wizard or adds another search criteria, then it is often appropriate to move focus to the starting point for that action.
  • If the button is activated with a shortcut key, the focus usually remains in the context from which the shortcut key was activated. A button in a focused card has a shortcut key assigned and is triggered, the focus should still be on the card rather than a button unless it changes the context.
  • Minimum button size required in 44x44 px
  • if using ICON only Buttons mention label or aria-label on the button.

🔭 Observation

autocomplete works only on firefox and persists the dynamic state of the button.

‼️ Pitfalls/Bad practices

  • Avoid usage of div or span as buttons because that might disable the accessibility features that the browser has to offer. You may have to mimic the button behavior with tabindex, CSS, and JS. And that’s a lot of code for a simple button 😠

Using HTML semantics and letting the browser do most of the work is more future-friendly.

🔭 Observation

autofocusing a button is considered as a security threat and gets blocked by-default in case of iframe with sandbox enabled.

Button like Inputs

You might think of inputs as places where you type things (<input type=”text”/>) or click to choose things (<input type=”radio”/>), but there are a variety of inputs that are essentially submit (or reset) buttons for forms.

🏗️ HTML Implementation

Input button cannot contain children elements, hence there are limitations here. <button></button> can contain children.

<!--1--
<input type="button" value="A button"/>
<!--2-->
<input type="submit"/>
<!--3-->
<input type="reset"/>

🔭 Observation

label is not required for input-buttons as suggested for other input elements.

TIP

If no disabled attribute is specified on a button. It inherits the disabled state from the parent element.

⚙️ JS considerations

  • Validations are to be handled and required is handled by form

❤️ Accessibility

🔭 Observation

“Firefox will, unlike other browsers, by default, persist the dynamic disabled state of a <button> across page loads. Use the autocomplete attribute to control this feature” — as quoted on MDN

Thank you Chris Coyier for helping me on this 🙌

Have something to add? I’d be happy to do it. Post in the comments or tweet me

Cheers, KD 🤘

--

--

Published in codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Written by Krishna Damaraju

JS Developer working with EmberJs and ReactJs. Find me at https://krishnasarath.xyz

No responses yet

Write a response