","programmingLanguage":"html","@type":"SoftwareSourceCode"},{"text":"Open","@type":"SoftwareSourceCode","@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-3","programmingLanguage":"html"},{"@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-4","text":"// attachments: lightweight, centralized behavior\ndocument.addEventListener('DOMContentLoaded', () => {\n document.querySelectorAll('a.action-link').forEach(a => {\n a.addEventListener('click', (ev) => {\n ev.preventDefault();\n const action = a.dataset.action;\n if (action === 'openModal') {\n openModal();\n }\n });\n });\n});","programmingLanguage":"javascript","@type":"SoftwareSourceCode"},{"@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-5","text":"# example: find files containing javascript: href patterns\nrg -n --glob 'src/**' 'href=\"javascript:'","@type":"SoftwareSourceCode","runtimePlatform":"Command Line","programmingLanguage":"bash"},{"@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-6","text":"// targeted refactor example\nconst links = document.querySelectorAll('a[href^=\"javascript:\"]');\nlinks.forEach(l => {\n l.removeAttribute('href'); // safe default, or set to a real URL\n l.addEventListener('click', (e) => {\n e.preventDefault();\n // migrate to function call\n doThing();\n });\n});","programmingLanguage":"javascript","@type":"SoftwareSourceCode"},{"programmingLanguage":"html","@type":"SoftwareSourceCode","text":"Open dialog","@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-7"},{"@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-8","@type":"SoftwareSourceCode","programmingLanguage":"javascript","text":"document.querySelectorAll('a[data-action=\"openDialog\"]').forEach(el => {\n el.addEventListener('click', (e) => {\n e.preventDefault();\n openDialog();\n });\n});"},{"@id":"https://javacripting.com/javascript-dom/javascript-in-href#code-9","programmingLanguage":"javascript","@type":"SoftwareSourceCode","text":"// React example - unobtrusive click handler\nfunction MyLink() {\n return { /* logic */ e.preventDefault(); openModal(); }}>Open;\n}"}]},{"@type":"BreadcrumbList","itemListElement":[{"position":1,"item":"https://javacripting.com","@type":"ListItem","name":"Home"},{"position":2,"name":"JavaScript DOM","@type":"ListItem","item":"https://javacripting.com/javascript-dom"},{"name":"javascript in href: Safe Inline JS for Accessible Anchors","@type":"ListItem","item":"https://javacripting.com/javascript-dom/javascript-in-href","position":3}],"@id":"https://javacripting.com/javascript-dom/javascript-in-href#breadcrumb"},{"@type":"FAQPage","mainEntity":[{"name":"What is javascript in href and why is it discouraged?","acceptedAnswer":{"text":"javascript in href embeds JS code in an anchor tag, triggering code on click. This pattern is discouraged due to accessibility, security, and maintainability concerns. Prefer real URLs and unobtrusive JavaScript attachments.","@type":"Answer"},"@type":"Question"},{"name":"What are safe alternatives to javascript in href?","acceptedAnswer":{"text":"Use real URLs for navigation and attach behavior with addEventListener in a separate script. For non-navigational actions, consider buttons or anchors with data attributes and a centralized JS handler.","@type":"Answer"},"@type":"Question"},{"acceptedAnswer":{"text":"Inline JavaScript in href can be ignored by screen readers or misrepresented by assistive technologies. Refactoring to unobtrusive JS improves compatibility and predictability across devices.","@type":"Answer"},"@type":"Question","name":"Is javascript in href accessible with assistive technologies?"},{"name":"How do I convert existing code to unobtrusive JS?","acceptedAnswer":{"text":"Search for href=\"javascript:\" patterns, replace with a real URL or href=\"#\", and attach the behavior via a script using addEventListener. Start with the most-used links and test thoroughly.","@type":"Answer"},"@type":"Question"},{"name":"Are there cases where javascript in href is acceptable?","@type":"Question","acceptedAnswer":{"@type":"Answer","text":"In rare cases where the anchor is purely a UI trigger not intended to navigate, it may be used with proper ARIA roles and fallback navigation. However, this is discouraged and should be avoided when possible."}}]}]}

javascript in href: Best practices for anchors and inline JS

A comprehensive guide to understanding and safely handling javascript in href. Learn why inline JS is discouraged, explore accessible alternatives, and implement unobtrusive event handling with progressive enhancement across modern browsers in 2026.

JavaScripting
JavaScripting Team
·5 min read
JS in href - JavaScripting
Photo by StockSnapvia Pixabay
Quick AnswerDefinition

javascript in href embeds JavaScript code directly in an anchor's href attribute to trigger actions. This pattern is widely discouraged due to accessibility, security, and maintainability concerns. Prefer real URLs for navigation and attach behavior with addEventListener in separate JavaScript files. If navigation must be prevented, use href="#" with a defensive preventDefault in your script.

What 'javascript in href' means and why it matters

The pattern 'javascript in href' uses an inline JavaScript URL inside the href attribute of an anchor tag to run code when the link is activated. While it might seem convenient, it bypasses a link's semantic purpose and can degrade accessibility for screen readers, block navigation for keyboard users, and complicate content security and testing. In practice, prefer real URLs or progressive enhancement with event listeners.

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

Why this matters: inline JavaScript ties behavior to markup, making behavior harder to reason about and harder to test in isolation. It also makes automated accessibility checks fail and can expose attackers to XSS vectors if dynamic code is not carefully sanitized. A modern approach keeps markup semantic and behavior in JavaScript, not in HTML.

Accessibility and security risks of javascript in href

Anchors should represent navigable destinations. When href contains JavaScript, keyboard focus, screen readers, and search engines can misinterpret the element, leading to poor UX and inconsistent results. Additionally, inline scripts are a common vector for cross-site scripting (XSS) if user input is interpolated or not sanitized. The safe practice is to remove inline JS and rely on event listeners attached after the DOM is loaded.

HTML
<a href="#" id="safeLink">Click me</a> <script> const el = document.getElementById('safeLink'); el.addEventListener('click', (e) => { e.preventDefault(); doSomething(); }); </script>

This pattern preserves semantics: the link can still navigate (if you choose a real URL) or can be a button, while the behavior is defined in JavaScript code separate from the HTML.

Modern alternatives: unobtrusive JavaScript and progressive enhancement

A robust approach replaces javascript: URLs with a real href and unobtrusive event handlers. This improves accessibility, SEO, and security while making maintenance easier. Use data attributes to store identifiers and attach handlers in a single script that runs on DOMContentLoaded.

HTML
<a href="/target-page" class="action-link" data-action="openModal">Open</a>
JavaScript
// attachments: lightweight, centralized behavior document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('a.action-link').forEach(a => { a.addEventListener('click', (ev) => { ev.preventDefault(); const action = a.dataset.action; if (action === 'openModal') { openModal(); } }); }); });

If no JavaScript is available, the link will navigate to the real URL (as defined by href), preserving accessibility. This is the essence of progressive enhancement.

Scanning and refactoring existing codebases

If you inherit a project with many javascript: href usages, start with a targeted audit. Use static analysis or search tools to locate occurrences, then refactor in batches. A typical pattern is to replace href="javascript:..." with href="#" or with a valid URL and move the logic into a script file.

Bash
# example: find files containing javascript: href patterns rg -n --glob 'src/**' 'href="javascript:'
JavaScript
// targeted refactor example const links = document.querySelectorAll('a[href^="javascript:"]'); links.forEach(l => { l.removeAttribute('href'); // safe default, or set to a real URL l.addEventListener('click', (e) => { e.preventDefault(); // migrate to function call doThing(); }); });

Patterns, pitfalls, and best practices

Best practice: avoid inline JS entirely; prefer real URLs and a small, centralized script that handles interactions. When you must use anchors for actions, ensure that keyboard users can activate the action and that screen readers announce the intent. Consider using role="button" only when the anchor is not a navigable link and provide a real URL otherwise.

HTML
<a href="#" class="cta" aria-label="Open dialog" data-action="openDialog">Open dialog</a>
JavaScript
document.querySelectorAll('a[data-action="openDialog"]').forEach(el => { el.addEventListener('click', (e) => { e.preventDefault(); openDialog(); }); });

Frameworks and real-world patterns

Modern frameworks discourage javascript: href in favor of declarative bindings. In React/Vue, attach handlers in the component lifecycle and never put executable code in href attributes. For server-side rendering, maintain semantic anchors and enhance them with client-side scripts for behavior. This keeps code maintainable and secure across devices and browsers in 2026.

JavaScript
// React example - unobtrusive click handler function MyLink() { return <a href={targetUrl} onClick={(e) => { /* logic */ e.preventDefault(); openModal(); }}>Open</a>; }

Steps

Estimated time: 60-120 minutes

  1. 1

    Audit current usage

    Scan the codebase for any href attributes containing javascript: and note where they occur most frequently. Prepare a plan to refactor in logical batches.

    Tip: Use a code search tool to quickly locate all instances.
  2. 2

    Decide on semantics

    Determine if the anchor navigates or triggers an action. If it navigates, keep a real href; if not, consider using a button or real URL with progressive enhancement.

    Tip: Aim for semantic anchors with progressive enhancement.
  3. 3

    Refactor anchor tags

    Replace javascript: hrefs with real URLs or href="#" and move logic into a separate script file.

    Tip: Keep markup clean and logic centralized.
  4. 4

    Implement centralized handler

    Attach event listeners in a single module, using data-action or data attributes to dispatch actions.

    Tip: Avoid inline handlers and keep tests focused.
  5. 5

    Test accessibility and SEO

    Test with JavaScript disabled, verify keyboard navigation and screen reader labels, and ensure link semantics remain intact.

    Tip: Use a11y testing tools and manual checks.
  6. 6

    Roll out and monitor

    Add lint rules or code-review checks to prevent future inline JS usage and monitor for regressions.

    Tip: Automate checks in CI to catch new occurrences.
Pro Tip: Prefer addEventListener over inline handlers for maintainability.
Warning: Avoid javascript: in href due to XSS and accessibility concerns.
Note: Use data- attributes to store action identifiers for clean JS bindings.
Pro Tip: Ensure focus visibility and keyboard operability even when JS is disabled.

Keyboard Shortcuts

ActionShortcut
Open DevToolsIn Chromium-based browsersCtrl++I
Open ConsoleDevTools Console tabCtrl++J
Copy code snippetText selection in code blocksCtrl+C
Format code in editorCode editor formattingCtrl++F

Questions & Answers

What is javascript in href and why is it discouraged?

javascript in href embeds JS code in an anchor tag, triggering code on click. This pattern is discouraged due to accessibility, security, and maintainability concerns. Prefer real URLs and unobtrusive JavaScript attachments.

JavaScript in href is when a link runs code instead of navigating. It hurts accessibility and security, so avoid it and use unobtrusive event handlers.

What are safe alternatives to javascript in href?

Use real URLs for navigation and attach behavior with addEventListener in a separate script. For non-navigational actions, consider buttons or anchors with data attributes and a centralized JS handler.

The safe approach is to keep navigation real and handle actions with separate JavaScript.

Is javascript in href accessible with assistive technologies?

Inline JavaScript in href can be ignored by screen readers or misrepresented by assistive technologies. Refactoring to unobtrusive JS improves compatibility and predictability across devices.

Accessibility is compromised with inline JS in href; refactor to separate JS for better support.

How do I convert existing code to unobtrusive JS?

Search for href="javascript:" patterns, replace with a real URL or href="#", and attach the behavior via a script using addEventListener. Start with the most-used links and test thoroughly.

You refactor by moving logic into JavaScript files and keeping the HTML clean.

Are there cases where javascript in href is acceptable?

In rare cases where the anchor is purely a UI trigger not intended to navigate, it may be used with proper ARIA roles and fallback navigation. However, this is discouraged and should be avoided when possible.

There are few acceptable cases; usually you should avoid it and use progressive enhancement instead.

What to Remember

  • Avoid javascript in href; use real URLs where possible
  • Attach behavior with addEventListener instead of inline handlers
  • Use progressive enhancement to support users with JS disabled
  • Keep HTML semantic and separate from JavaScript logic
  • Audit and refactor codebases to migrate away from inline JS in href

Related Articles