Dynamically add deep links to a page

08 March 2015

As you can see, I have republished my blog with a new design. It's built with Sandra.Snow (a static site generator written in Nancy) from the awesome Phillip Haydon.

All posts are written in markdown and get automatically compiled to HTML by the generator.

A requirement for a good blog post for me is to be able to deep link to specific parts, especially if it get's longer or is part of a documentation.

How deep-linking works

The search-value in location lets us retrieve the current hash from the URL. When a page is loaded the browser searches for an element with the same ID as the given hash and scrolls to it in case it was found.

What to do?

  1. Add an ID (unique, for sure) to every headline or section to your page where you want users to be able to deeplink to. (e.g. <h1 id="code-example">Code Example</h1>)

  2. Give users the ability to discover this deeplink by creating a visual indicator/anchor (do you see the hash next to the headlines in this post?). These anchors have the hash as their href (e.g. <a href="#code-example">#</a>).

Why should I do this on the client?

There are cases where you don't have the ability to modify all your headlines/sections on the server-side, especially when there's no server involved. Or you just want to be cool kid in town.

How to do it with Javascript

For this blog I have created a simple snippet which dynamically inserts the anchors and assigns the IDs to the headlines in a post.

// get all the elements you want a deep-link for
// you can modify this query to your needs
var elements = document.querySelectorAll('.post-article h2, .post-article h3');

Now you can modify each headline:

for (var i = 0; i < elements.length; i++)
{
  // create a slug (URI encoded string) that looks best for your use-case
  var slug = encodeURIComponent(elements[i].textContent.toLowerCase().replace('&', 'and').replace(/\W/g, '-').replace('--', ''));

  // create the visual anchor and assign a content and the href
  // and maybe a class so you can style it ;-)
  var a = document.createElement('a');
  a.href = '#' + slug;
  a.textContent = '#';
  a.classList.add('post-anchor');

  // the slug becomes the id of the headline 
  // and the anchor gets appended (or prepended if you want to)
  post.id = slug;
  post.appendChild(a); 
}

This simple snippet will create all the deeplinks automatically.

You can display them all the time (like I do on frontendplay) or just view them on hover (like github does).

But the browser doesn't scroll to the deep-link on load

True. As they are inserted dynamically the browser doesn't see them on load and therefore not scrolling to it (this is not the case for all browsers).

To fix this, we can alter the location.hash after creating the deep-links and simple trigger this behaviour again:

if (!!location.hash)
{
  var hash = location.hash.replace('#', '');
  location.hash = '';
  location.hash = hash;
}
comments powered by Disqus