Question

JavaScript Links: Should You Use href="#" or javascript:void(0)?

javascripthtmlperformanceoptimizationhref

Question

I want to create a link whose only purpose is to run JavaScript code. Which of these approaches is better in terms of functionality, page behavior, performance, and validity?

<script>
function myJsFunc() {
    alert("myJsFunc");
}
</script>

<a href="#" onclick="myJsFunc();">Run JavaScript Code</a>

Or this version:

<script>
function myJsFunc() {
    alert("myJsFunc");
}
</script>

<a href="javascript:void(0)" onclick="myJsFunc();">Run JavaScript Code</a>

If the element only triggers JavaScript and does not actually navigate anywhere, what is the best practice?

Short Answer

By the end of this page, you will understand why href="#" and href="javascript:void(0)" are both usually poor choices for JavaScript-only actions. You will learn when to use a real link, when to use a <button>, how default browser behavior works, and what patterns are preferred in modern JavaScript codebases.

Concept

The core concept here is choosing the correct HTML element for the job.

An <a> element represents navigation. Its purpose is to move the user to another URL, section, or resource.

A <button> element represents an action. Its purpose is to trigger behavior such as opening a menu, submitting a form, toggling a panel, or running JavaScript.

That distinction matters because browsers, assistive technologies, keyboards, search tools, and other developers all rely on semantic HTML.

Why href="#" is problematic

Using href="#" tells the browser to navigate to the top of the current page, or to the fragment with the empty hash. Even if you attach onclick, the link still has navigation behavior unless you prevent it.

Common side effects:

  • the page may jump to the top
  • the URL may change to include #
  • browser history can be affected
  • users can get confusing behavior if JavaScript fails or loads slowly

Why javascript:void(0) is problematic

Using href="javascript:void(0)" puts JavaScript code directly inside HTML where a URL is expected. This mixes behavior with markup and makes the link depend on JavaScript in a non-semantic way.

Problems with this approach:

  • it is not a real destination
  • it mixes JavaScript into the href attribute
  • it is harder to maintain
  • it is considered outdated in modern codebases
  • some security or style rules discourage javascript: URLs

Best practice

  • If the user should go somewhere, use an <a href="/real-url">.
  • If the user should perform an action, use a <button type="button">.

This improves:

  • accessibility
  • semantics
  • maintainability
  • keyboard behavior
  • code clarity

Unobtrusive JavaScript

A modern pattern is to keep HTML focused on structure and attach behavior with JavaScript:

<button type="button" id="runCodeBtn">Run JavaScript Code</button>
document.getElementById("runCodeBtn").addEventListener("click", myJsFunc);

function myJsFunc() {
  alert("myJsFunc");
}

This separates concerns clearly:

  • HTML describes the element
  • JavaScript adds behavior
  • CSS handles presentation

That separation is easier to test, maintain, and scale.

Mental Model

Think of HTML elements like tools in a toolbox:

  • <a> is a road sign that sends you somewhere.
  • <button> is a doorbell that makes something happen.

If you use a road sign as a doorbell, people may still try to follow it somewhere. That is what happens with href="#" and javascript:void(0).

So the simple rule is:

  • Need navigation? Use a link.
  • Need an action? Use a button.
Take Quiz

Syntax and Examples

Preferred syntax for an action

<button type="button" id="runCodeBtn">Run JavaScript Code</button>

<script>
function myJsFunc() {
    alert("myJsFunc");
}

document.getElementById("runCodeBtn").addEventListener("click", myJsFunc);
</script>

This is the best choice when clicking the element should only run JavaScript.

Why this is better

  • no fake URL
  • no page jump
  • better accessibility semantics
  • cleaner separation between HTML and JavaScript

If it really is navigation, use a real link

<a href="/profile">Go to profile</a>

This should be used when the click leads to another page or location.

If you must use a link with JavaScript

Sometimes a real link also has JavaScript behavior, such as analytics or progressive enhancement:

<a href="/download" id="downloadLink">Download file</a>

<script>
document.getElementById("downloadLink").addEventListener("click", function () {
    console.log("Download clicked");
});
</script>

Here the href still points to a meaningful destination.

Avoid this

<a href="#" onclick="myJsFunc();">Run JavaScript Code</a>

This may navigate to # unless you prevent the default action.

<a href="javascript:void(0)" onclick="myJsFunc();">Run JavaScript Code</a>

This uses JavaScript as a URL, which is generally considered outdated and poor practice.

Step by Step Execution

Consider this example:

<button type="button" id="runCodeBtn">Run JavaScript Code</button>

<script>
function myJsFunc() {
    alert("myJsFunc");
}

document.getElementById("runCodeBtn").addEventListener("click", myJsFunc);
</script>

What happens step by step

  1. The browser reads the HTML and creates a button element.
  2. JavaScript defines the function myJsFunc.
  3. getElementById("runCodeBtn") finds the button.
  4. addEventListener("click", myJsFunc) tells the browser: when this button is clicked, run myJsFunc.
  5. The user clicks the button.
  6. The browser fires a click event.
  7. myJsFunc() runs.
  8. The alert appears.

Compare that to href="#"

<a href="#" onclick="myJsFunc();">Run JavaScript Code</a>

When the user clicks:

  1. The onclick handler runs.
  2. myJsFunc() shows the alert.
  3. The browser then performs the link's default action.
  4. Since the href is #, the page may jump to the top or update the URL.

To stop that behavior, you would need to prevent the default action:

<a href="#" onclick="myJsFunc(); return false;">Run JavaScript Code</a>

That works, but it is still a sign that a button would be a better fit.

Real World Use Cases

When to use a <button>

Use a button for interface actions such as:

  • opening a modal dialog
  • toggling a dropdown menu
  • starting a search with JavaScript
  • adding an item to a cart
  • expanding or collapsing content
  • copying text to the clipboard

Example:

<button type="button" id="copyBtn">Copy invite code</button>

When to use an <a>

Use a link for navigation such as:

  • going to another page
  • downloading a file
  • jumping to a section with #section-id
  • opening an external website

Example:

<a href="/settings">Account settings</a>

In interactive web apps

In React, Vue, Angular, or plain JavaScript apps, developers still follow the same idea:

  • navigation controls should behave like links
  • action controls should behave like buttons

Even if a page feels like a single-page app, semantics still matter for accessibility and maintainability.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid inline onclick and fake link URLs.

Common patterns include:

Event listeners instead of inline handlers

const button = document.querySelector("#saveBtn");
button.addEventListener("click", saveData);

This keeps JavaScript out of the HTML.

Guard clauses in event handlers

function handleDeleteClick(event) {
  if (!confirm("Delete this item?")) {
    return;
  }

  deleteItem();
}

This makes the action flow clearer.

Progressive enhancement

Sometimes a real link is kept so the page still works without JavaScript:

<a href="/products?sort=price" id="sortLink">Sort by price</a>
document.getElementById("sortLink").addEventListener("click", function (event) {
  event.preventDefault();
  sortProductsOnPage();
});

This pattern is useful when:

  • the link has a meaningful fallback
  • JavaScript enhances the user experience
  • navigation still works if scripting is unavailable

Validation and linting

Many codebases use linters and accessibility tools that flag:

  • javascript: URLs
  • anchors used as buttons
  • inline event attributes like onclick

That is why modern teams commonly prefer semantic elements plus JavaScript event listeners.

Common Mistakes

1. Using a link for an action

Broken example:

<a href="#" onclick="openMenu()">Open menu</a>

Why it is a mistake:

  • a menu toggle is an action, not navigation
  • the page may jump
  • accessibility semantics are weaker

Better:

<button type="button" id="menuBtn">Open menu</button>

2. Forgetting to prevent default behavior

Broken example:

<a href="#" onclick="myJsFunc()">Run</a>

The browser may still navigate to #.

If you must keep the link:

<a href="#" onclick="myJsFunc(); return false;">Run</a>

Or better:

<a href="/real-url" id="runLink">Run</a>

<script>
document.getElementById("runLink").addEventListener("click", function (event) {
  event.preventDefault();
  myJsFunc();
});
</script>

3. Using javascript:void(0) because it looks harmless

Broken example:

<a href="javascript:void(0)" onclick="myJsFunc()">Run</a>

Why to avoid it:

  • not a real URL
  • mixes JavaScript into HTML
  • outdated pattern

4. Using inline onclick everywhere

Broken example:

<button onclick="save(); track(); showMessage();">Save</button>

Why it becomes a problem:

  • hard to maintain
  • hard to test
  • logic is scattered inside HTML

Better:

<button type="button" id="saveBtn">Save</button>

<script>
document.getElementById("saveBtn").addEventListener("click", function () {
  save();
  track();
  showMessage();
});
</script>

5. Forgetting button type inside forms

Broken example:

<form>
  <button>Open help</button>
</form>

Inside a form, a button without type often acts like submit.

Better:

<button type="button">Open help</button>

Comparisons

OptionPrimary purposeGood choice for JS-only action?Common issues
<a href="#">Navigation to a fragmentNoJumps to top, changes URL, needs prevention
<a href="javascript:void(0)">Fake link with JS URLNoOutdated, poor semantics, mixes JS into HTML
<button type="button">Triggering an actionYesUsually the best choice
<a href="/real-url"> + JSReal navigation with enhancementYes, if navigation still mattersMust decide whether to prevent default

href="#" vs javascript:void(0)

If you had to choose only between those two, javascript:void(0) avoids the page jump that # can cause. However, neither is the modern best practice for a JavaScript-only action.

Button vs link

QuestionUse <button>Use <a>
Does it perform an action on the current page?YesNo
Does it navigate somewhere meaningful?NoYes
Should it work like a form or UI control?YesNo
Should it appear in navigation or point to a resource?NoYes
Take Quiz

Cheat Sheet

Quick rule

  • Action only? Use <button type="button">
  • Navigation? Use <a href="...">

Avoid

<a href="#">...</a>
<a href="javascript:void(0)">...</a>

Preferred pattern

<button type="button" id="btn">Run</button>

<script>
document.getElementById("btn").addEventListener("click", function () {
  myJsFunc();
});
</script>

If using a real link with JS enhancement

<a href="/page" id="link">Open page</a>
document.getElementById("link").addEventListener("click", function (event) {
  event.preventDefault();
  doSomething();
});

Key points

  • <a> means navigation
  • <button> means action
  • href="#" may change the URL or jump the page
  • javascript:void(0) is generally outdated
  • avoid inline onclick when possible
  • inside forms, use type="button" for non-submit buttons

FAQ

Is href="#" bad practice?

It is usually a poor choice for JavaScript-only actions because it can change the URL or scroll to the top unless you prevent the default behavior.

Is javascript:void(0) better than #?

It avoids the page jump, but it is still not the best practice. A <button> is usually the correct element for JavaScript-only actions.

Should I ever use an anchor without a real URL?

Usually no. If there is no actual navigation target, a button is normally the better semantic choice.

Why is a button more accessible than a fake link?

Buttons are announced and handled by assistive technology as actions. That matches their real purpose better than using a link that goes nowhere.

Can I still style a button to look like a link?

Yes. You can use CSS to make a button look like text or a link while keeping the correct semantics.

What if I need a fallback when JavaScript is disabled?

Use a real link with a meaningful href, then enhance it with JavaScript. That way users still have a destination if scripts do not run.

Are inline onclick handlers wrong?

They are not always invalid, but they are usually less maintainable than attaching events in JavaScript with addEventListener.

Does this choice affect performance?

The performance difference between # and javascript:void(0) is negligible. The more important issue is semantics, maintainability, and browser behavior.

Take Quiz

Mini Project

Description

Build a small interactive panel with two controls: one real navigation link and one JavaScript action button. This project demonstrates the difference between navigation and actions, and shows how to attach behavior using addEventListener instead of fake link URLs.

Goal

Create a page where a button shows a message with JavaScript, while a separate link performs real navigation semantics.

Requirements

  • Add a button that shows an alert when clicked.
  • Add a real link that points to a meaningful URL or page section.
  • Attach the button behavior using addEventListener().
  • Do not use href="#" or javascript:void(0).
  • Make sure the button does not submit a form accidentally.
Take Quiz

Keep learning

Related questions

View more