Info Placeholder href value ("#" or javascript:)
Why href="#" and javascript: links are discouraged for JavaScript-driven controls, and what to use instead.
The validator flags <a href="#"> and <a href="javascript:..."> — links whose destination is a placeholder rather than a real URL.
Example
<!-- Discouraged -->
<a href="#" onclick="openMenu()">Menu</a>
<a href="javascript:void(0)" onclick="openMenu()">Menu</a>
<!-- Preferred, if it doesn't navigate anywhere -->
<button type="button" onclick="openMenu()">Menu</button>Why it matters
Both patterns exist to make an element look and behave like a link while actually being driven entirely by JavaScript — but a real <a> tag with either value still announces itself as a link to search engines and screen readers, promising a destination that doesn't exist. href="#" also has a visible side effect if the click handler doesn't call preventDefault(): the page jumps to the top. A <button> is the semantically correct element for a control that triggers behavior without navigating — it's keyboard-operable and screen-reader-friendly by default, with none of the placeholder-href side effects.
Frequently asked questions
Is href="#section-id" also flagged?
No — a fragment that names a real id is a legitimate same-page link and isn't touched by this check (see the separate broken-anchor-link check for when that id doesn't actually exist). Only the bare # placeholder and javascript: URLs are flagged here.
Why not just use preventDefault() and keep the <a> tag?
You can, and it avoids the page-jump side effect, but the element is still semantically a link with no real destination — a <button> better communicates its actual behavior to assistive technology and doesn't need the extra defensive code.