Reputation:
I have the following code snippet below. When the user scrolls past the header it becomes sticky. Then when they click on either of the tabs in the header One
, Two
, Three
, etc. it scrolls down to the corresponding div.
For some reason when I click on the tabs it scrolls past the div. Like I want to scroll to the top of the One
, Two
, etc. sections and have it appear right underneath the sticky header when scrolled. Right now it scrolls past the sticky header when I click on the nav items on header. Is there a different way to achieve this?
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
font-size: 28px;
}
#navbar {
overflow: hidden;
background-color: #333;
padding: 25px 16px;
}
#navbar a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
text-decoration: none;
font-size: 17px;
margin-right: 15px;
}
.content {
padding: 16px;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
z-index: 100;
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.16);
}
.common {
border: 1px solid black;
padding: 200px 10px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="header">
<p>Scroll down to see the sticky effect.</p>
</div>
<div id="navbar">
<a onclick="headerClick(this); return false;" href="#">This is One</a>
<a onclick="headerClick(this); return false;" href="#">This is Two</a>
<a onclick="headerClick(this); return false;" href="#">This is Three</a>
<a onclick="headerClick(this); return false;" href="#">This is Four</a>
</div>
<div class="content">
<div class="common" id="One">This is the first</div>
<div class="common" id="Two">Two</div>
<div class="common" id="Three">Three</div>
<div class="common" id="Four">Four</div>
<div class="common" id="Five">Five</div>
<div class="common">Filler div to make scrolling longer</div>
<div class="common">Filler div to make scrolling longer</div>
<div class="common">Filler div to make scrolling longer</div>
</div>
<script>
window.onscroll = function() {myFunction()};
var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
navbar.classList.add("sticky")
document.getElementById("navbar").style.padding = "40px 16px";
} else {
navbar.classList.remove("sticky");
document.getElementById("navbar").style.padding = "25px 16px";
}
}
function headerClick(elem) {
if (elem.innerHTML === 'This is One') {
document.getElementById("One").scrollIntoView();
}
if (elem.innerHTML === 'This is Two') {
document.getElementById("Two").scrollIntoView();
}
if (elem.innerHTML === 'This is Three') {
document.getElementById("Three").scrollIntoView();
}
if (elem.innerHTML === 'This is Four') {
document.getElementById("Four").scrollIntoView();
}
}
</script>
</body>
</html>
Upvotes: 2
Views: 1179
Reputation: 130
The problem is that your navbar is covering the top of the div. You can avoid this by using window.scrollBy()
and offsetHeight
to scroll the window up again by the height of the navbar. This solution has the advantage that it does not require you to know what height your navbar will be to start with, so it allows for various different browser configurations.
function headerClick(elem) {
if (elem.innerHTML === 'One') {
document.getElementById("One").scrollIntoView();
window.scrollBy(0, -(elem.offsetHeight)-2)
}
if (elem.innerHTML === 'Two') {
document.getElementById("Two").scrollIntoView();
window.scrollBy(0, -(elem.offsetHeight)-2)
}
if (elem.innerHTML === 'Three') {
document.getElementById("Three").scrollIntoView();
window.scrollBy(0, -(elem.offsetHeight)-2)
}
if (elem.innerHTML === 'Four') {
document.getElementById("Four").scrollIntoView();
window.scrollBy(0, -(elem.offsetHeight)-2)
}
if (elem.innerHTML === 'Five') {
document.getElementById("Five").scrollIntoView();
window.scrollBy(0, -(elem.offsetHeight)-2)
}
}
The extra -2 is to ensure that the div border can be seen, but you can delete that if it's not needed.
Upvotes: 1
Reputation: 152
You can achive this like so: Before each section add sort of anchor and instead scrolling to the section scroll to the unvisible anchor which will have some top offset.
<a id='Two'></a>
<div class="common">Two</div>
#Two {
display: block;
position: relative;
top: -120px; /*Here must be same value as your navbar height is*/
visibility: hidden;
}
I hope it helped you!
Upvotes: 0