JavaScript turned static documents into software. Single-page apps feel instant. No full page reloads, no flickering white screens. But that speed comes with a cost that many teams ignore: the basic machinery of the web starts to rot. Navigation becomes brittle. Search engines struggle to follow paths. Screen readers get lost. And users find themselves trapped in interfaces that look like websites but behave like broken desktop applications.

The culprit is usually a div with an onClick handler.

A div carries no semantic meaning. It is a box. When you strap a click handler onto it and use it to route users to a new view, you are asking the browser to treat a cardboard box like a door. The browser refuses. So does every tool built around the browser.

Screen readers do not announce a div as a link or a button. They skip over it, or they read it as plain text. A user navigating by voice cannot target it. A search engine crawler, scanning your page for discoverable URLs, sees nothing to follow. Your route might as well not exist.

Worse, you lose the behaviors users already know. A real link lets someone right-click to open in a new tab, bookmark the destination, or copy the address to share. Keyboard users expect to hit Tab to reach it and Enter to open it. A div offers none of this. Even if you bolt on tabIndex and role="link" and keyboard listeners, you are rebuilding, poorly, what the browser gives you for free. And you will forget an edge case. You always do.

Use Anchors for Destinations, Buttons for Actions

HTML already solved this. The confusion starts because both elements look clickable, so developers treat them as interchangeable. They are not.

Use an <a> tag when you want to move the user to a new URL. Not a simulated view swap, not a state change, but an actual location. The href attribute should contain a real address:

<a href="/docs">Documentation</a>

That is it. If the user is going somewhere, use a link.

Use a <button> when something happens on the current page. Buttons are for actions such as:

  • Opening a modal
  • Submitting a form
  • Saving settings
  • Toggling a menu

Links are for destinations. Buttons are for actions. Mixing the two muddles your interface and breaks user expectations.

Let the Browser Do Its Job

Modern browsers are the result of decades of evolution and standardization. They handle security, history, prefetching, and accessibility better than your hand-rolled JavaScript ever will.

A genuine anchor tag automatically feeds the browser history stack. It works with the native context menu. It participates in the browser's built-in prefetching algorithms when the user hovers or focuses it, making your app feel faster without you writing a line of code. It respects the user's preferences for opening links. It cooperates with password managers, with translation tools, with reader modes.

When you replace that with a JavaScript navigation function, you opt out of all of it. You are not just losing features; you are forcing users to abandon habits they have built across every other site on the internet. That is not a technical decision. It is a hostile user experience.

Check What Your Framework Actually Renders

React Router, Vue Router, Next.js Link components, SvelteKit. These tools make client-side routing feel effortless. But abstraction breeds mistakes.

Inspect your DOM. Open the browser's developer tools and look at the elements your framework emits. A <Link> component should render as a real <a> tag with a valid href attribute in the final HTML. If it renders as a span, a div, or anything else without a proper href, your abstraction has failed you. Fix the component. Override the default. Use the passHref prop or the framework equivalent. Do not trust the framework to get it right without verification.

This matters for hydration mismatches too. If the server renders a link and the client hydrates it into a non-link, you create accessibility bugs that are hard to trace because the HTML looks correct in your source code but wrong in the live DOM.

Ban Fake Destinations

There is a pattern that refuses to die: href="javascript:void(0)". Developers use it when they want something that looks like a link but acts like a button, usually because they do not want to style a button or because an older codebase demands it.

रुकिए। यह कोई URL नहीं है। यह ब्राउज़र को कोई गंतव्य नहीं देता। यह हिस्ट्री स्टैक को अनुपयोगी स्टेट्स से भर देता है। यह ब्राउज़र हिस्ट्री और एक्सेसिबिलिटी को खराब करता है। यह एक जाल है। यदि आपको बिना नेविगेशन के क्लिक व्यवहार चाहिए, तो आपको एक <button> की आवश्यकता है। इसे अपनी इच्छानुसार स्टाइल करें। CSS को इससे कोई फर्क नहीं पड़ता कि एलिमेंट एक बटन है या लिंक। आपके उपयोगकर्ताओं को फर्क पड़ता है।

ऐसा टेक्स्ट लिखें जो बताए कि उपयोगकर्ता कहाँ जा रहा है

आपके लिंक के अंदर के शब्द मायने रखते हैं। स्क्रीन रीडर उपयोगकर्ता अक्सर जल्दी से स्कैन करने के लिए पेज पर मौजूद हर लिंक की सूची निकालते हैं। यदि आपके सभी लिंक "Read more" या "Click here" कहते हैं, तो वह सूची बेकार का शोर बन जाती है।

विशिष्ट बनें। इनकी तुलना करें:

  • खराब: <a href="/security/api-guide">Read more</a>
  • अच्छा: <a href="/security/api-guide">Read the API security guide</a>

दूसरा विकल्प उपयोगकर्ता को ठीक-ठीक बताता है कि उन्हें क्या मिलेगा। यह सर्च इंजन को गंतव्य पेज के बारे में संदर्भ देता है। यह आपकी लिंक सूची को नेविगेबल बनाता है। वर्णनात्मक लिंक टेक्स्ट एक्सेसिबिलिटी हासिल करने के सबसे आसान और सस्ते तरीकों में से एक है।

गंभीरता से टेस्टिंग करें

यदि आप आर्किटेक्चर को सत्यापित नहीं करते हैं, तो उसका कोई अर्थ नहीं है।

सबसे पहले, अपने कीबोर्ड फ्लो का परीक्षण करें। अपना माउस हटा दें। अपनी साइट के हर इंटरैक्टिव एलिमेंट पर Tab की मदद से जाएँ। हर वास्तविक लिंक को एक दृश्यमान फोकस आउटलाइन दिखानी चाहिए—कोई हल्का सा ग्लो नहीं जो बैकग्राउंड में गायब हो जाए, बल्कि एक स्पष्ट रिंग जिसे थकी हुई आँखें भी देख सकें। Enter दबाएँ। इससे लिंक सक्रिय होना चाहिए। यदि Tab किसी एलिमेंट को छोड़ देता है, या यदि Enter से कुछ नहीं होता है, तो आपके पास एक बग है।

दूसरा, अपने रूट्स का सर्वर स्तर पर परीक्षण करें। क्लाइंट-साइड रूटिंग केवल एक ऊपरी परत है। यदि कोई उपयोगकर्ता /dashboard/reports को बुकमार्क करता है और कल वापस आता है, या रिफ्रेश करता है, तो आपके सर्वर को पता होना चाहिए कि उस पेज को कैसे सर्व करना है। अपने रिवर्स प्रॉक्सी या सर्वर फ्रेमवर्क को इस तरह कॉन्फ़िगर करें कि अज्ञात पथों के लिए वह आपके एप्लिकेशन शेल पर वापस जाए, या सीधे सही HTML सर्व करे। रिफ्रेश करने पर आने वाला 404 एरर कोई मामूली बग नहीं है। यह एक टूटा हुआ वादा है।

JavaScript एक शक्तिशाली लेयर है