Links used to activate JavaScript functions

By

Prefer a button and addEventListener when you need a click to run JavaScript. The old href="#" and javascript:void(0) patterns are code smells.

~~~

When you are creating an app using plain JavaScript, sometimes you’ll have the necessity of triggering a function when the user clicks something.

Suppose the function you want to execute is called handleClick():

function handleClick() {
  alert('clicked')
}

What people used to do

For years, people used an <a> tag with either href="#" or href="javascript:void(0)", plus an onclick attribute:

<a href="#" onclick="handleClick()">Click here</a>
<a href="javascript:void(0)" onclick="handleClick()">Click here</a>

With href="#", the browser follows the link and scrolls to the top of the page. To stop that, the onclick attribute itself must return false, like onclick="handleClick(); return false". Returning false from inside handleClick() is not enough, because the attribute discards that value. With javascript:void(0), the scroll does not happen, so many tutorials preferred it.

Both are code smells now. Inline onclick attributes fight Content Security Policy. javascript: URLs are a bad habit. And a link that does not go anywhere is the wrong element for a click action.

Prefer a button and addEventListener

If the click runs a script and does not navigate, use a button:

<button type="button" id="action">Click here</button>
document.querySelector('#action').addEventListener('click', handleClick)

That keeps the handler in your DOM script, not in the markup. It is easier to reuse, and it does not pretend to be a link.

If the element really is a link to another page, keep a real URL in href. Then call event.preventDefault() only when JavaScript takes over:

<a href="/fallback/" id="action">Click here</a>
document.querySelector('#action').addEventListener('click', (event) => {
  event.preventDefault()
  handleClick()
})

If JavaScript fails to load, the user still gets the fallback page. That is the progressive enhancement path, and it beats javascript:void(0) every time.

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about js: