Question

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

htmljavascriptperformanceoptimizationhref

Question

I want to create a link whose only purpose is to run JavaScript code. Which of these approaches is better in terms of behavior, performance, and HTML 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 a link exists only to trigger JavaScript, which option should be used, and is there a better semantic alternative?

Short Answer

By the end of this page, you will understand why href="#" and href="javascript:void(0)" are usually not the best choices for triggering JavaScript actions. You will learn the semantic difference between links and buttons, how browsers handle each option, and the recommended modern approach: use a <button> for actions and an <a> only for real navigation.

Concept

In HTML, links and buttons have different jobs:

  • An <a> element is for navigation.
  • A <button> element is for actions such as opening a menu, submitting data, toggling UI, or running JavaScript.

That distinction matters because browsers, assistive technologies, search engines, and other developers all expect these elements to behave according to their meaning.

Why href="#" is problematic

When you use:

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

# is a URL fragment. Clicking it usually means “navigate to the top of the page” or “navigate to the element with the matching fragment id.” Even if your onclick handler runs, the browser may still perform navigation unless you prevent the default behavior.

Common side effects:

  • The page may jump to the top.
  • The URL may change to include #.
  • Browser history may be affected.
  • The element is pretending to be a link even though it is not really navigating.

Why javascript:void(0) is also not ideal

When you use:

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

The javascript: URL scheme tells the browser to execute JavaScript from the href itself. void(0) makes the expression return undefined, so the browser does not try to replace the page with a result.

Although this avoids the jump-to-top behavior of #, it still has issues:

  • It mixes behavior into HTML markup.
  • It is harder to maintain.
  • It is considered poor practice in modern development.
  • Some security tools and content policies discourage inline JavaScript.
  • It still uses a link for something that is not navigation.

What should you use instead?

If the element performs an action, use a button:

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

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

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

This is better because:

  • It is semantic: buttons are for actions.
  • It is more accessible by default.
  • It separates HTML structure from JavaScript behavior.
  • It avoids fake navigation.
  • It is easier to test and maintain.

Why this matters in real programming

In real projects, clean semantics lead to better:

  • accessibility n- maintainability
  • keyboard support
  • browser behavior
  • team readability

A developer reading your code should immediately know whether clicking something should navigate somewhere or perform an action. Using the right element makes that obvious.

Mental Model

Think of HTML elements like tools in a toolbox:

  • A link is like a road sign: it sends you to another place.
  • A button is like a doorbell: pressing it causes an action.

If you install a doorbell that secretly acts like a road sign, people will be confused. Browsers and screen readers feel the same way.

So the rule of thumb is simple:

  • Going somewhere? Use a link.
  • Doing something? Use a button.
Take Quiz

Syntax and Examples

1. Using a link for real navigation

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

Use this when the user should move to another page or location.

2. Using a button for JavaScript actions

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

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

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

This is the recommended modern approach.

3. If you must use a link, use a real URL

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

Then JavaScript can enhance behavior if needed:

<script>
document.getElementById("downloadLink").addEventListener("click", function (event) {
    console.log("Tracking download before navigation");
});
</script>

The link still works as a normal link.

4. Avoid these patterns for actions

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

These work in many cases, but they are not the best semantic or maintainable choice.

5. If href="#" is already in old code

You often need to stop default navigation:

<a href="#" id="oldLink">Run</a>

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

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

This is safer than relying on inline onclick, but a button is still better if there is no navigation.

Step by Step Execution

Consider this recommended example:

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

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

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

What happens step by step

  1. The browser reads the HTML and creates a button on the page.
  2. The JavaScript defines the myJsFunc function.
  3. document.getElementById("runAction") finds the button.
  4. addEventListener("click", myJsFunc) tells the browser:
    • when this button is clicked,
    • call myJsFunc.
  5. The user clicks the button.
  6. The browser fires a click event.
  7. myJsFunc() runs.
  8. alert("myJsFunc") displays the message.

Compare that with href="#"

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

When clicked:

  1. The browser sees a link.
  2. The onclick code runs.
  3. The browser may then follow href="#".
  4. The page may jump to the top or update the URL fragment.

That extra navigation behavior is usually unwanted when the element is only meant to trigger code.

Real World Use Cases

Use a <button> for actions like:

  • Opening a modal dialog
  • Toggling a dropdown menu
  • Showing or hiding password text
  • Starting a file upload
  • Applying a filter in a dashboard
  • Adding an item to a cart with JavaScript
  • Expanding an accordion section

Example:

<button type="button" id="toggleMenu">Toggle Menu</button>

Use an <a> for navigation like:

  • Going to a product page
  • Moving to another route in a single-page app
  • Jumping to a section of the same page
  • Downloading a file from a URL
  • Opening documentation

Example:

<a href="/products/42">View Product</a>

In APIs and web apps

Developers often attach JavaScript actions to buttons for:

  • submitting AJAX requests
  • refreshing data tables
  • retrying failed operations
  • opening side panels
  • triggering export actions

Using a button makes intent clear and avoids fake URLs.

Take Quiz

Real Codebase Usage

In real codebases, developers usually avoid inline handlers like onclick="..." and instead attach behavior in JavaScript.

Common pattern: separate structure and behavior

<button type="button" id="saveBtn">Save</button>
document.getElementById("saveBtn").addEventListener("click", function () {
    console.log("Saving...");
});

This keeps HTML cleaner and JavaScript easier to organize.

Guard clauses in event handlers

document.getElementById("saveBtn").addEventListener("click", function () {
    if (!formIsValid()) {
        return;
    }

    saveData();
});

Developers often return early when validation fails.

Progressive enhancement

If navigation is real, developers keep a valid href so the page still works without JavaScript:

<a href="/reports/export" id="exportLink">Export</a>
document.getElementById("exportLink").addEventListener("click", function () {
    console.log("Track export click");
});

Error handling with action buttons

document.getElementById("retryBtn").addEventListener("click", async function () {
    try {
        await fetchData();
    } catch (error) {
        console.error("Retry failed", error);
    }
});

Why teams prefer this approach

  • better accessibility
  • easier testing
  • clearer intent
  • less inline JavaScript
  • fewer accidental navigation bugs

Common Mistakes

1. Using a link when a button is needed

Broken example:

<a href="#" id="openModal">Open Modal</a>

Problem:

  • This is not navigation.
  • It may jump to the top of the page.

Better:

<button type="button" id="openModal">Open Modal</button>

2. Forgetting to prevent default on href="#"

Broken example:

<a href="#" id="runLink">Run</a>

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

Problem:

  • The function runs, but the browser still follows #.

Fix:

<a href="#" id="runLink">Run</a>

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

3. Using javascript: URLs

Broken style:

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

Problem:

  • Behavior is embedded in markup.
  • It is outdated and harder to maintain.

Better:

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

4. Relying on inline onclick

Less maintainable:

<button type="button" onclick="myJsFunc()">Run</button>

Better:

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

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

5. Forgetting button type inside forms

Broken example:

<form>
  <button id="runBtn">Run</button>
</form>

Problem:

  • A button inside a form defaults to type="submit" in many cases.

Fix:

<form>
  <button type="button" id="runBtn">Run</button>
</form>

6. Assuming performance differences matter here

Between # and javascript:void(0), performance differences are not the real issue. The important concerns are:

  • semantics
  • accessibility
  • maintainability
  • unwanted browser behavior

Comparisons

ApproachMain purposeGood choice for JavaScript-only action?Notes
<a href="#">Fragment navigationNoMay jump to top or change URL unless prevented
<a href="javascript:void(0)">Execute JS from URLNoOutdated style, mixes behavior into markup
<button type="button">Trigger actionYesBest semantic choice for actions
<a href="/real-url">Real navigationYes, if navigatingBest when the element should go somewhere

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

Feature#javascript:void(0)
Changes URL fragmentUsually yesNo
Can jump page positionYesNo
Semantic for action-only UIPoorPoor
Modern best practiceNoNo
Requires workaroundOften preventDefault()Still not recommended

Button vs Link

ElementUse whenKeyboard/accessibility meaning
<button>The user triggers an actionAnnounced and behaved as a control
<a>The user navigates to another locationAnnounced and behaved as a link
Take Quiz

Cheat Sheet

Quick rule

  • Use <a> for navigation
  • Use <button> for actions

Avoid for JS-only actions

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

Recommended pattern

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

<script>
document.getElementById("runBtn").addEventListener("click", function () {
    alert("Hello");
});
</script>

If you are stuck with href="#"

event.preventDefault();

Why avoid inline handlers

Avoid:

<button onclick="doSomething()">Run</button>

Prefer:

element.addEventListener("click", doSomething);

Important edge case

Inside a form, specify button type:

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

Otherwise it may submit the form.

Best practice summary

  • Real destination -> use <a href="/somewhere">
  • UI action -> use <button type="button">
  • Do not use javascript: URLs in modern code
  • Do not use # as a fake link unless maintaining legacy code

FAQ

Is href="#" bad practice?

It is usually a poor choice when the element does not actually navigate anywhere. It can cause page jumping and confusing semantics.

Is javascript:void(0) better than #?

It avoids the jump-to-top behavior, but it is still not the recommended modern approach. A button is usually better.

What should I use instead of href="javascript:void(0)"?

Use a <button type="button"> and attach a click handler with JavaScript.

Can I still use an anchor tag with JavaScript?

Yes, if it has a real destination. JavaScript can enhance the link, but the link should still represent navigation.

Why does clicking href="#" scroll to the top?

Because # refers to the top of the current document when no specific fragment target is given.

Does javascript:void(0) affect page load speed?

In practice, performance is not the important issue here. Semantics, maintainability, and accessibility matter much more.

Are inline onclick handlers allowed?

They work, but they are generally less maintainable than adding event listeners in JavaScript.

What is the most accessible choice for a JavaScript action?

A native <button> is usually the best choice for actions because browsers and assistive technologies already understand how it should behave.

Take Quiz

Mini Project

Description

Build a small interface with two controls: one real navigation link and one JavaScript action button. This project demonstrates the core rule behind the original question: links should navigate, while buttons should trigger actions. It also shows how to attach events without inline onclick code.

Goal

Create a page where one element navigates to a section on the page and another element runs JavaScript to show a message counter.

Requirements

  1. Add a real anchor link that navigates to a section on the same page.
  2. Add a button that runs JavaScript when clicked.
  3. Keep JavaScript out of the HTML attributes.
  4. Show how many times the button has been clicked.
  5. Make sure the action control does not change the URL or scroll the page.
Take Quiz

Keep learning

Related questions

View more