A common pattern on the web today is that of navigation within a single page. One sees this technique used frequently on marketing landing pages, where a larger amount of content will be contained within one page. Each link in the nav links to a spot on the page, and usually that spot scrolls smoothly into view when the link is clicked.
Recently a new developer asked me how to make a nav like that. While my suggested implementation is certainly not complex, my approach might be instructional as an example of progressive enhancement. People don’t talk much about progressive enhancement anymore but it is still my preferred and recommended methodology.
Progressive enhancement is all about layers. The idea is to break the implementation into its simplest, most bulletproof form and build that first. I call this the “baseline experience.” From there, one layers additional style or behavior on top of that foundation to achieve the desired effect. If any layer above the baseline experience fails, the implementation will still stand.
With something like in-page navigation, there is a very clear starting point. HTML already provides a way to link to a specific region of the page using a fragment identifier. For example, given that the page has a
section element with an ID of “features,” one can link to that
section with the
HREF “#features,” i.e.
<a href="#features">Features</a> will move the viewport to
So the first step is to build a navigation menu using the built-in semantics of a
<nav> element and an
<ol> of links:
That implementation alone will meet the requirements of in-page navigation. Clicking one of the links using a fragment identifier will move the viewport to that section. But although technically correct, this approach leaves something to be desired. The links need an additional behavior added.
Step two is to use data attributes to declare that some of these links have an additional behavior:
scrollTo behavior actually does. My implementation uses jQuery, but obviously that is not a requirement. I add an event listener to the body to detect clicks on links with the
data-behavior="scrollTo" attribute, verify that a fragment identifier is present, scroll to the identified element, and prevent the fragment from being added to the URL:
preventDefault is at the very end.