Navbar w/ Smooth Scrolling Same Page Links & Accessibility

Not as simple as it sounds…

Photo by Faye Cornish on Unsplash

There’s a few unexpected steps involved which left me scouring the internet for solutions. All the full solutions I found were bloated with ugly and long Javascript or using jQuery, etc which is really unnecessary.

Step 1 — HTML

Here’s a simple example with links to sections on the same page with #id’s.

<nav class='navbar'>
<ul class='navbar__list'>
<li class='navbar__list__item><a href='#intro'>Intro</a></li>
<li class='navbar__list__item><a href='#meatnpotatoes'>Meat 'n' Potatoes</a></li>
<li class='navbar__list__item><a href='#stuff'>Stuff</a></li>
</ul>
</nav>

1.2 — Add Tab Index to html Sections

If you don’t set the tabindex you won’t be able to set focus when writing your Javascript (next step). By default, <section>’s are not focusable.

<section id='intro' tabindex='0'></section>
<section id='meatnpotatoes' tabindex='0'></section>
<section id='stuff' tabindex='0'></section>

Step 2 — Javascript

In your Javascript file create an event listener for clicks on the navbar links.

  • Select your links.
const navbarItems = document.querySelectorAll('.navbar__list__item');
  • Loop over links & add listeners for clicks.
navbarItems.forEach(item => {
item.addEventListener('click', () => {
  • Prevent the default behaviour.
    Without this your links will jump instantly down the page ( :O no smooth, sexy scrolling! ).
event.preventDefault();
  • Select section of page related to the navbar item.
let section = document.querySelector(item.childNodes[1].getAttribute('href'));
  • Set scroll behaviour for section .

behaviour: ‘smooth’ will set it to smoothly scroll to the section.
block: ‘start’ will set it to scroll to the beginning of the section, rather than the center.

section.scrollIntoView({
behaviour: 'smooth',
block: 'start'
});
  • Set webpage focus to the clicked section .

The scrolled-to section will receive focus, essential for accessibility & keyboard navigation.

setTimeout(() => section.focus(), 500);

Full code and if you want to see it in action I implemented it in my portfolionot a shameless plug, I swear it just happens to be where I needed it!

const navbarItems = document.querySelectorAll('.navbar__list__item');navbarItems.forEach(item => {
item.addEventListener('click', () => {
event.preventDefault();
let section = document.querySelector(item.childNodes[1].getAttribute('href'));
section.scrollIntoView({
behaviour: 'smooth',
block: 'start'
});
setTimeout(() => section.focus(), 500);
}
}

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store