Question
JavaScript Links: Should You Use href="#" or javascript:void(0)?
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
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.
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:
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
- The browser reads the HTML and creates a button element.
- JavaScript defines the function
myJsFunc. getElementById("runCodeBtn")finds the button.addEventListener("click", myJsFunc)tells the browser: when this button is clicked, runmyJsFunc.- The user clicks the button.
- The browser fires a
clickevent. myJsFunc()runs.- The alert appears.
Compare that to
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
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>
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:
< = =>Run
Comparisons
| Option | Primary purpose | Good choice for JS-only action? | Common issues |
|---|---|---|---|
<a href="#"> | Navigation to a fragment | No | Jumps to top, changes URL, needs prevention |
<a href="javascript:void(0)"> | Fake link with JS URL | No | Outdated, poor semantics, mixes JS into HTML |
<button type="button"> | Triggering an action | Yes | Usually the best choice |
<a href="/real-url"> + JS | Real navigation with enhancement | Yes, if navigation still matters | Must decide whether to prevent default |
href="#" vs
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
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 is negligible. The more important issue is semantics, maintainability, and browser behavior.
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="#"orjavascript:void(0). - Make sure the button does not submit a form accidentally.
Keep learning
Related questions
Deep Cloning Objects in JavaScript: Methods, Trade-offs, and Best Practices
Learn how to deep clone objects in JavaScript, compare structuredClone, JSON methods, and recursive approaches with examples.
Get Screen, Page, and Browser Window Size in JavaScript
Learn how to get screen size, viewport size, page size, and scroll position in JavaScript across major browsers with clear examples.
How JavaScript Closures Work: A Beginner-Friendly Guide
Learn how JavaScript closures work with simple explanations, examples, common mistakes, and practical use cases for real code.