Skip to content

Instantly share code, notes, and snippets.

@patik
Last active September 28, 2015 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patik/1498874 to your computer and use it in GitHub Desktop.
Save patik/1498874 to your computer and use it in GitHub Desktop.
Scroll to the heading that matches the URL hash
// ==UserScript==
// @name Scroll To Heading From Hash
// @author Craig Patik
// @namespace http://github.com/cpatik
// @version 1.0
// @description Enable jumping to any heading without adding IDs to the heading elements
// @include http://*
// ==/UserScript==
// Site owners can drop the code below into their pages,
// or end-users can install it by clicking `raw` in the top right of this gist
// Looks for a heading element that contains the text in the URL hash
(function _scrollToHash () {
function scrollToHash () {
if (!window.location.hash) { return; }
var stripNonWordChars = /\W/g, // Ignore punctuation
stripHTML = /<\/?[^>]+>/g, // Ignore HTML tags
hash = new RegExp(window.location.hash.replace(stripNonWordChars, ""), "i"),
headers = document.querySelectorAll('h1,h2,h3,h4,h5,h6'),
i = 0;
while (i < headers.length) { // for now, while is much faster than forEach :(
// Quick and dirty comparison of the header's alphanumeric content to the hash's
if (hash.test(headers[i].innerHTML.replace(stripHTML, "").replace(stripNonWordChars, ""))) {
headers[i].scrollIntoView();
break;
}
i++;
}
}
window.addEventListener("load", scrollToHash, false);
window.addEventListener("hashchange", scrollToHash, false);
}());
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ScrollToHash Demo</title>
<style>
nav a { display: block; }
section { margin-bottom: 10em; }
section p { margin: 2em 1em 20em 1em; }
</style>
</head>
<body>
<aside>
<h1>Handy jump links</h1>
<p>Use these to update the URL hash</p>
<nav>
<a href="#alpha">#alpha</a>
<a href="#bravo-charlie">#bravo-charlie</a>
<a href="#bravocharlie">#bravocharlie</a> (jumps to the same place as the previous link)</a>
<a href="#deltaecho">#deltaecho</a>
<a href="#delta">#delta</a>
<a href="#really-long-heading">#really-long-heading</a>
<a href="#TingThatNoon">#TingThatNoon</a>
</nav>
<p>Now tons of space to make sure your browser has to scroll</p>
</aside>
<section>
<h1>Alpha</h1>
<p>Just taking up a bit of space here.<br><a href="#handy">top</a></p>
<h2>Bravo, Charlie!</h2>
<p>Just taking up a bit of space here.<br><a href="#handy">top</a></p>
</section>
<section>
<h1>DeltaEcho</h1>
<p>Just taking up a bit of space here.<br><a href="#handy">top</a></p>
<a href="#handy">top</a>
</section>
<section>
<h3>Really Long Heading &mdash; with <strong>formatting</strong> &dash; That No One In Their Right Mind Would Include In Their URL In Its Entirety, Right?</h3>
<p>Just taking up a bit of space here.<br><a href="#handy">top</a></p>
</section>
<script src="https://gist.github.com/cpatik/1498874/raw/013a1353515076d99564ee31d65f047a2a75db20/scrollToHash.user.js"></script>
</body>
</html>
@patik
Copy link
Author

patik commented Dec 19, 2011

A tweet from @leaverou got me thinking that there must be a better way to enable the jump-directly-to-this-section functionality in browsers. Ideally browsers would implement this by either providing the same DOM navigation shortcuts that screen readers have or by looking for some token in the URL.

But in the mean time, if your site is not already using hashes for something else, you can drop in this function and automatically enable linking to specific headings without adding extra IDs. Also, the hash only needs to be a substring of the heading, and punctuation and HTML formatting is ignored, so you can link to "Hey guys, look at this!" with simply #hey-guys or #lookatthis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment