diff --git a/web_src/js/markup/anchors.js b/web_src/js/markup/anchors.js
index cc2ed5db78..53dfa2980c 100644
--- a/web_src/js/markup/anchors.js
+++ b/web_src/js/markup/anchors.js
@@ -2,10 +2,11 @@ import {svg} from '../svg.js';
 
 const headingSelector = '.markup h1, .markup h2, .markup h3, .markup h4, .markup h5, .markup h6';
 
-function scrollToAnchor() {
-  if (document.querySelector(':target')) return;
-  if (!window.location.hash || window.location.hash.length <= 1) return;
-  const id = decodeURIComponent(window.location.hash.substring(1));
+function scrollToAnchor(hash, initial) {
+  // abort if the browser has already scrolled to another anchor during page load
+  if (initial && document.querySelector(':target')) return;
+  if (hash?.length <= 1) return;
+  const id = decodeURIComponent(hash.substring(1));
   const el = document.getElementById(`user-content-${id}`);
   if (el) {
     el.scrollIntoView();
@@ -24,9 +25,11 @@ export function initMarkupAnchors() {
     a.classList.add('anchor');
     a.setAttribute('href', `#${encodeURIComponent(originalId)}`);
     a.innerHTML = svg('octicon-link');
+    a.addEventListener('click', (e) => {
+      scrollToAnchor(e.currentTarget.getAttribute('href'), false);
+    });
     heading.prepend(a);
   }
 
-  scrollToAnchor();
-  window.addEventListener('hashchange', scrollToAnchor);
+  scrollToAnchor(window.location.hash, true);
 }