How do I offset the anchor scroll that overlaps elements?

305 Views Asked by At

How to add an offset to elements hash location so my navigation bar on the top of the window will not overlap my content?

<nav id="nav">
  <a href="#home">Home</a>
  <a href="#about">About</a>
  <a href="#contact">Contact</a>
</nav>

<main>
  <section id="home">
    <h2>Welcome to example.com</h2>
  </section>
  <section id="about">
    <h1>About us</h1>
  </section>
  <section id="contact">
    <h2>Contact us</h2>
  </section>
</main>

The simplest solution I've found on the internet is to add some margin-top or padding-top to the targeted element section{ margin-top:100px }, but this will interfere with my design and I don't want to hack using hidden elements to fix this issue.

1

There are 1 best solutions below

0
Damian Toczek On

TL;DR

window.addEventListener("hashchange", function(e){
  e.preventDefault()
  const navHeight = document.getElementById("nav").offsetHeight
  const target = document.getElementById(window.location.hash.substring(1))
  window.scrollTo(0, target.offsetTop - navHeight)
})

I sadly don't know the jQuery solution to this.

Explanation

So how does this work, we add an event listener to the window that is looking for hash changes. We want to prevent the default browser scroll and use our own "adjusted" scroll with an offset.

If you have a sticky navigation on the top of your page that is always showing, we need to know the height of the navigation element. const navHeight = doc.getElementById("nav").offsetHeight

As next we are getting the hash location, for example.com/about.html#team we want to get the hash location without the hash symbol window.location.hash.substring(1), returns "team"

Now we need to get the target element by passing the returned hash location to the document.getElementById(window.location.hash.substring(1))` that will return the target element.

Now we do some simple math to offset the navigation element so it won't overlap your valuable content.
target.offsetTop - navHeight

As the last step, we pass the new calculated offset to the windows scroll function.
window.scrollTo(0, target.offsetTop - navHeight)