I'm learning Javascript and am trying to combine two codes into one to recreate the mobile food menu from grubhub. (example page: https://www.grubhub.com/restaurant/dunkin-807-ny-82-hopewell-junction/3278731)
The goal is to have my menu navigation stick to the top of the page with the current section of the menu highlighted. You can side scroll the navigation to see other sections and click to scroll down. You can also scroll down on the page and the menu will change to highlight the new section you are in and will also scroll to the highlighted section on the menu.
My code does this but it freezes as you start to scroll or when you click a navigation button. I am thinking the issue is caused by the event listener seeing what is currently active vs what I've selected to be active.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Scroll</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html {
scroll-behavior: smooth;
background-color: #fafafa;
}
body {
-moz-osx-font-smoothing: grayscale;
color: #303030;
}
a {
text-decoration: none;
font-family: Arial, Helvetica, sans-serif;
color: rgb(109, 109, 109);
}
h1 {
margin-top: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
}
nav.mynav {
position: relative;
z-index: 2;
height: 2.5rem;
overflow-y: hidden;
scroll-behavior: smooth;
max-width: 1200px;
margin: 0px auto;
}
.mynav ul {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1.5rem;
padding-left: 0;
padding-right: 10px;
margin-block: 0;
overflow-x: auto;
list-style: none;
text-align: center;
white-space: nowrap;
}
a {
display: block;
padding: .5rem .75rem;
}
a:hover {
background-color: #e3e3e3;
}
.active {
color: rgb(25, 25, 25);
font-weight: bold;
}
.row {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100%;
column-gap: 10px;
row-gap: 10px;
}
.navcontainer {
position: sticky;
top: 0;
background-color: #ffffff;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1);
}
.offset {
padding: 4em 10px 0px 10px ;
margin-top: -4em;
max-width: 1200px;
margin: 40px auto;
}
.card {
background-color: rgb(255, 255, 255);
color: rgb(57, 57, 57);
padding: 10px 25px;
height: auto;
border-radius: 10px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1);
transition: 0.3s;
}
.cards {
max-width: 1200px;
margin: 40px auto;
display: grid;
grid-gap: 2rem;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Fira Sans,Helvetica Neue,Arial,sans-serif;
font-size: 16px;
font-style: inherit;
font-weight: 400;
letter-spacing: 0;
line-height: 26px;
text-rendering: optimizeLegibility;
margin: 0;
padding: 0
}
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.1);
}
.menucontainer {
height: 90vh;
}
.main-content-inner-wrapper {
overflow: clip;
}
.title-card-wrapper{
display: none;
}
/* Screen larger than 600px? 2 column */
@media (min-width: 600px) {
.cards { grid-template-columns: repeat(2, 1fr); }
}
/* Screen larger than 900px? 3 columns
@media (min-width: 900px) {
.cards { grid-template-columns: repeat(3, 1fr); }
}*/
</style>
</head>
<body>
<div class="navcontainer">
<nav class="mynav">
<ul>
<li><a href="#raw" class="active">Raw Bar</a></li>
<li><a href="#platter">Shellfish Platters</a></li>
<li><a href="#salads">Cold Appetizers and Salads</a></li>
<li><a href="#apps">Hot Appetizers</a></li>
<li><a href="#beef">USDA Prime Beef</a></li>
<li><a href="#entrees">Entrées</a></li>
<li><a href="#sides">Sides</a></li>
</ul>
</nav>
</div>
<main>
<section id="raw" class="offset">
<h1>Raw Bar</h1>
<div class="cards">
<div class="card"><b>Mini Reuben Sandwiches 2</b>
<p>Description to go in this space underneath</p> </div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="platter" class="offset">
<h1>Shellfish Platters</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="salads" class="offset">
<h1>Cold Appetizers and Salads</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="apps" class="offset">
<h1>Hot Appetizers</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="beef" class="offset">
<h1>USDA Prime Beef</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="entrees" class="offset">
<h1>Entrées</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
<section id="sides" class="offset">
<h1>Sides</h1>
<div class="cards">
<div class="card">ONE</div>
<div class="card">TWO</div>
<div class="card">THREE</div>
<div class="card">FOUR</div>
<div class="card">FIVE</div>
<div class="card">SIX</div>
<div class="card">SEVEN</div>
<div class="card">EIGHT</div>
<div class="card">NINE</div>
<div class="card">TEN</div>
<div class="card">ELEVEN</div>
<div class="card">TWELVE</div>
</div>
</section>
</main>
</div>
<script type="text/javascript">
let mainNavLinks = document.querySelectorAll("nav.mynav ul li a");
let mainSections = document.querySelectorAll("main section");
let lastId;
let cur = [];
window.addEventListener("scroll", event => {
let fromTop = window.scrollY;
mainNavLinks.forEach(link => {
let section = document.querySelector(link.hash);
if (section.offsetTop <= fromTop && section.offsetTop + section.offsetHeight > fromTop) {
link.classList.add("active")
link.scrollIntoView({ behavior: "smooth", inline: "center" })
} else {
link.classList.remove("active");
}
}, {passive: true});
})
let nav = document.querySelectorAll('nav.mynav')
</script>
</body></html>