Links and buttons and JavaScript, oh my!
The software teams I have worked with over the last 10 years have primarily developed single-page applications (SPA). Last year, I published the article Warning signs of front-end complexity as a way to reflect on the problems encountered with this approach and to provide a way forward. Since then, I directed two software teams on migrating their single-page architecture to a multi-page architecture.
When relying on client-side routing for so long, it can be easy to forget how else to do it. As such, developers have asked me during these architecture migrations:
Should this be a link or a button?
My most effective response is simply:
How would you build this if you could not use JavaScript?
A JavaScript-less web relies on links and form submissions to handle all interactions with the server, resulting in a page redirect to the same or a different page. There are also ways to use links and buttons that do not involve the server. Let’s review some examples:
Links
Use links when user input is not needed, such as for a website’s navigation.
If a page links to itself, it may include extra data in its query string to support dynamic server-side rendering. For example, page
and sort
keys could provide basic pagination functionality.
Links can also be used to apply settings for a page. Like pagination, changing the sort order uses the page
and sort
keys.
The server inspects the current sort
value in the URL and dynamically applies it to all the pagination links.
In-page links
Use in-page links with #
in the href
value to navigate to specific content on the same page. This is commonly used for:
- table of contents for pages with many distinct sections
- skip links at the top of the page for keyboard users
- back-to-top link (
#
or#top
) at the bottom of a long page
Submit buttons
Use submit buttons with forms when user input is needed. The name
and value
attributes on form fields are sent to the server on submit.
Use a form’s get
method to change the view of a page based on user input, such as displaying a list of items sorted in a user-specified way. In this particular case, the result is effectively identical to the previously described link-based solution.
Use a form’s post
method to create, update, or delete resources. Hidden input fields can indicate the particular action to take on the given resource (Option 1). Alternatively, the hidden input fields could be replaced by a convention that includes the action and resource identifier in the form’s action
URL (Option 2).
Non-submit buttons
Buttons do not submit a form when they are:
- outside a form
- within a form with the
type="button"
attribute
The only way to make these types of buttons functional is to use JavaScript. Prefer to use these for non-critical functionality, that enhances the user experience. For example, a “Clear” button could be a one-click convenience for clearing a text field. If the button fails to work for whatever reason, the user can still manually clear the text field with the keyboard.
Conclusion
How links or buttons should be used primarily depends on the need for user input and the intended default browser behavior.
User input | Default behavior | Use |
---|---|---|
None | Redirect | <a href="/…"> |
None | Skip | <a href="#…"> |
Optional | Redirect | <button type="submit"> |
None | None (use JavaScript) | <button type="button"> |
Only override defaults with JavaScript if it will enhance the user experience. For example:
- Prevent a form from submitting in order to provide custom client-side validation.
- Use a button instead of making another element (like a
div
) behave as a button.
Overall, it is more reliable and maintainable to align as much as possible with default browser behavior. Use native HTML elements in the way they were intended. This saves development time and circumvents incidental usability and accessibility issues.