Skip to content

Instantly share code, notes, and snippets.

@patik patik/scrollToHash.user.js
Last active Sep 28, 2015

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

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
You can’t perform that action at this time.