How to Get Rid of javascript void: Practical Fixes
Learn safe, modern alternatives to javascript:void(0) to improve accessibility and navigation. This guide explains why the pattern is problematic, how to replace it with semantic actions, and how to audit and test across your codebase.

To get rid of javascript:void(0), replace dummy links with real URLs or semantic controls. Replace anchors with actual hrefs when navigation is intended, or switch to button elements for actions. Add event handling only as needed and ensure accessibility with aria-labels and keyboard focus. Run a code search to refactor all occurrences.
Why getting rid of javascript:void(0) matters and context
If you’ve ever worked on a website or a web app, you’ve probably seen the pattern javascript:void(0) in anchor tags. It’s a way to make a link act like a button or to suppress navigation, but it creates a host of issues for users and search engines. If you’re asking how to get rid of javascript void, you’re not alone. The right answer is to swap in semantic, accessible patterns that preserve intent without confusing the browser.
According to JavaScripting, this approach is increasingly viewed as a maintenance risk rather than a best practice. Many projects accumulate dozens or hundreds of such anchors as quick fixes during quick demos, only to realize later that they hinder keyboard navigation and screen readers.
JavaScript void patterns can interfere with history, break bookmarks, and complicate automated testing. The ultimate goal is to reduce surprises for developers and users alike while keeping behavior predictable. Moving away from javascript:void(0) is a straightforward step toward cleaner, accessible UI.
Practical approaches to replace javascript:void(0) with safe patterns
There are several reliable patterns to replace javascript:void(0) while preserving the interaction. The simplest is to use a real URL in the href and handle the navigation in a script if you need to prevent default behavior. For example:
- Replace <a href="javascript:void(0)"> with <a href="/target-page" > and add an event listener to stop default navigation when needed.
- If the anchor represents an action, use a <button> element instead, with an accessible label and an onClick handler.
Additionally, you can keep anchors visually identical by using data attributes to carry what would be an action, and then handle it in JavaScript. Always call e.preventDefault() only when you truly need to suppress navigation. If the link should trigger a SPA route, rely on your router instead of injecting void statements.
Accessibility matters: ensure focus outlines are visible, add aria-labels if the visible text doesn’t fully describe the action, and avoid disabling keyboard access. This approach improves both usability and maintainability.
How to audit and fix across a codebase
Begin with a systematic audit to find every instance of javascript:void(0) and similar patterns. Use a fast search to locate occurrences: ripgrep -n "javascript:void(0)" or grep -R "javascript:void(0)". Once you’ve identified targets, categorize by context: links that should navigate, anchors used as buttons, and script-driven actions.
Create a plan to replace each case:
- For navigation links, replace the href with an actual URL and adjust any routing logic.
- For action anchors, replace with a button and wire up the action with a click handler.
- If the project uses a framework router, convert to router-links or equivalent.
After changes, run lint rules and tests. You may want to add a codemod script to standardize replacements across a large repo. If possible, run accessibility checks to verify that screen readers read the new controls correctly. Document the migration so future developers understand why the changes were made and how to extend them.
Migration strategy and testing plan
Plan the migration in small, reversible steps. Start in a feature branch and limit scope to a single module or page to minimize risk. Build a small regression test that exercises anchors using javascript:void(0) and verify the expected behavior with actual URLs or button controls.
Test across major browsers and devices, including at least Chrome, Firefox, Safari, and a mobile viewport. Confirm keyboard operability, focus management, and readable labels. Review performance implications if you replace dozens of dynamic anchors with real links or buttons. Finally, monitor production feedback and be prepared to rollback if any critical accessibility or navigation issues appear.
By following a deliberate migration strategy, you reduce the chance of breaking existing flows and improve long-term maintainability. The JavaScripting team emphasizes gradual changes and thorough testing to ensure consistent results across the codebase.
Accessibility considerations and future-proofing
As you refactor, ensure that new controls meet accessibility guidelines. Use semantic HTML (button for actions, anchor for navigation) and provide meaningful text for screen readers. If you must use JavaScript to enhance behavior, document the feature, keep progressive enhancement in mind, and maintain keyboard operability. Finally, create a small guardrail: a linter rule that flags leftover javascript:void usages and a test that fails when such patterns appear in code paths intended for navigation.
Summary of practical patterns you can adopt immediately
- Prefer real hrefs for navigations and actual destinations for links.
- Use <button> for actions; wire up with event handlers.
- If you must suppress navigation, call e.preventDefault() with a clear justification.
- Add ARIA attributes only when necessary, not as a substitute for proper semantics.
- Run a code search and a CI check to catch regressions across the entire repo.
Tools & Materials
- Code editor (e.g., VS Code)(Enable linters and snippets for JavaScript/HTML)
- Local development server(Hot reloading helps verify changes quickly)
- Modern browser with DevTools(Test across Chrome/Firefox/Safari)
- Node.js and npm(Run scripts and tooling for migrations)
- Git and version control(Track migrations and reversions)
- Search/Refactor tools (ripgrep, ESLint)(Speed up scanning and enforcement)
Steps
Estimated time: 60-90 minutes
- 1
Locate all occurrences
Run a project-wide search for javascript:void(0) to catalog every instance and context (anchor navigation, button-like anchors, or placeholders). Use fast search tools to cover many files quickly. Document findings in a migration sheet.
Tip: Pro tip: use ripgrep (rg) with --line-number to map occurrences precisely. - 2
Decide on replacement strategy
For each instance decide whether to replace with a real URL or switch to a button and handle the action. Prioritize semantic HTML and accessible labels to reduce later refactors.
Tip: Pro tip: group similar cases to minimize repetitive changes and apply a uniform pattern. - 3
Implement replacements
Refactor code by replacing void anchors with real hrefs or button elements. Add minimal, clear click handlers where needed and ensure e.preventDefault() is used only when necessary to stop navigation.
Tip: Pro tip: keep interactions predictable by centralizing event handlers in a module. - 4
Refactor routing for SPAs
If your app uses a router, swap to router links (or equivalents) instead of manual JavaScript navigation. Update tests to reflect the new navigation flow.
Tip: Pro tip: run the app’s router tests to catch path misconfigurations early. - 5
Enhance accessibility
Ensure focus outlines are visible, add aria-labels where visible text isn’t descriptive, and verify keyboard access performs the intended action.
Tip: Pro tip: use automated accessibility checks to catch missing labels. - 6
Test and review
Execute unit tests, manual QA, and cross-browser checks. Validate that anchors now behave like intended and that no regressions were introduced.
Tip: Pro tip: create a codemod to apply the same changes across multiple files.
Questions & Answers
What does javascript:void(0) do?
Javascript:void(0) is used to prevent navigation for an anchor while keeping it clickable. It returns undefined, which stops the browser from following the link. This pattern is often fragile and inaccessible, especially for screen readers.
It’s a pattern used to stop navigation, but it often breaks accessibility and should be replaced with real navigation or a proper button.
Why do developers still use it?
Some projects use it as a quick placeholder during demos or to attach a JavaScript action to an anchor. However, it can hinder accessibility, disrupt history, and confuse automated testing.
It’s often a quick hack for demos, but it tends to cause more problems than it solves in real apps.
Are there accessibility issues with this pattern?
Yes. Screen readers may not convey intent accurately, and keyboard users may rely on focus and visible labels that are missing with void anchors.
Yes—it can make it hard for assistive tech to understand what the link does, so replace it with accessible controls.
What are safe alternatives to javascript:void(0)?
Replace with a real href when navigation is intended, or use a <button> for actions and wire up a click handler. For SPA routes, use the router’s link component.
Use real navigation targets or buttons and rely on the app’s router for SPA scenarios.
How can I verify changes across a large project?
Run a code search for remaining patterns, execute automated tests, and perform manual QA across browsers. Add a CI rule to fail on any remaining void patterns.
Run searches and tests across the project to catch any stray instances and confirm behavior.
Watch Video
What to Remember
- Identify all javascript:void occurrences across the codebase.
- Replace with real URLs or semantic buttons for accessibility.
- Test keyboard and screen-reader support after refactors.
- Document migration steps and use tooling to enforce patterns.
- Verify consistency with routing and accessibility standards.
