Improving the usability of headings with fragment identifiers

Orde Saunders' avatarPublished: by Orde Saunders

Recently I have been discussing the use of fragment identifiers on headings within articles with Craig McPheat and he noticed that A List Apart were using CSS to show the fragment identifier on hover. This article examines that technique and builds upon it.

Fragment identifiers are used within a web page to enable linking to that particular section by using a URL that contains a hash (#) and the fragment identifier. These are particularly useful if you wish to refer to a specific part of an article and don't want the reader to have to find the relevant content within the context of the entire article.

HTML

In order for this technique to work the ID attributes need to be included in the markup. This allows browsers to jump to the relevant section of the page as it loads, if you try and add in the ID attributes with JavaScript the page may have loaded before the fragment identifiers have been added so won't necessarily be picked up by the browser. (There may be ways to achieve this using JavaScript but this will inevitably fall into the category of breaking the web.)

Linking to a section within a page is a core part of how the web works and this has been part of HTML since version 3. Adding ID attributes to the HTML is the foundation of this technique but the downside is that the ID attributes in the markup aren't easily discoverable so, to improve this, we need to add some enhancements.

CSS

(Credit for this technique goes to Tim Murtaugh and Michael Pick.)

The technique used on A List Apart uses CSS to show the fragment identifier as generated content after the heading element. The CSS selectors and rules for this aren't supported in all browsers and it also uses the hover state which, even if the browser supports the CSS, won't be available on all devices. However, as the core functionality is not affected and this is just a visual enhancement, this lack of universal support is not a concern.

In it's simplest form the CSS is as follows:

h1[id]:hover::after {
  content: '#' attr(id) ;
}

(For the sake of clarity the examples in this article only use <h1> - you will need to apply the techniques to all relevant headings on your site.)

The components of this are as follows:

  • ID attribute selector: the [id] in the selector limits this to applying to elements that have an ID defined.
  • Hover pseudo class: the :hover in the selector means this will only apply when the element is hovered over.
  • After pseudo element: the ::after the selector means the rule will apply to a virtual element after the selected element.
  • Content css property: this adds content into the pseudo-element, in this case a hash mark and the heading's ID attribute which is how the fragment identifier is referenced.

JavaScript

Whilst the visual indication of the fragment identifier is useful, and recessing it behind a hover style prevents it adding distracting visual clutter to the page, it doesn't help on devices that don't support hover. It also means that, even on devices that support hover, to get the full link to the fragment you will need to copy and paste the identifier and add it to the page's URL.

To overcome this we use JavaScript to wrap each heading that has a fragment identifier in an anchor that links to the fragment itself. Essentially we turn:

<h1 id="fragment-identifier">Heading text</h1>

into:

<a href="#fragment-identifier">
  <h1 id="fragment-identifier">Heading text</h1>
</a>

This means that if we want to get the URL for that fragment we can activate the link and take the URL from the browser's address bar or use browsers' various built-in link sharing facilities.

Using jQuery the code might look like this:

$(document).ready(function () {
  $('h1').each(function () {
    var id = $(this).attr('id');
    if (typeof id !== 'undefined') {
      $(this).wrap('<a href="#' + id + '"></a>');
    }
  });
});

Admittedly this is still not particularly discoverable but, if you do encounter a site that uses it, then it makes it much easier to link to a fragment within an article. In fact, having implemented this technique on this site before preparing this article I was able to use it to easily get the link I wanted to reference a specific section of another of my articles.

Accessibility

I have a concern that linking to a fragment identifier contained within the link itself might cause a problem for users of assistive technologies. I've done some reading around the link purpose WCAG 2.0 guidelines but haven't been able to see anything conclusive either way. It certainly doesn't adversely affect keyboard navigation so, until I find out otherwise, I'm going to assume that it doesn't create an accessibility issue.

A note about names

A number of solutions out there for linking to fragments use anchors with name attributes to mark the fragment identifiers. Whilst the name attribute might have greater support than id in very old (pre HTML 3) browsers, it has been obsoleted in HTML5 so, whilst the backward compatible choice might to be use name, the id attribute is currently extremely well sported and is the future friendly choice.