Horizontal scrollable menu
Horizontal scrollable menu
by pj_js15
HTML
<div class="pn-ProductNav_Wrapper">
<nav id="pnProductNav" class="pn-ProductNav">
<div id="pnProductNavContents" class="pn-ProductNav_Contents">
<a href="#" class="pn-ProductNav_Link" aria-selected="true">Chairs</a>
<a href="#" class="pn-ProductNav_Link">Tables</a>
<a href="#" class="pn-ProductNav_Link">Cookware</a>
<a href="#" class="pn-ProductNav_Link">Beds</a>
<a href="#" class="pn-ProductNav_Link">Desks</a>
<a href="#" class="pn-ProductNav_Link">Flooring</a>
<a href="#" class="pn-ProductNav_Link">Lighting</a>
<a href="#" class="pn-ProductNav_Link">Mattresses</a>
<a href="#" class="pn-ProductNav_Link">Solar Panels</a>
<a href="#" class="pn-ProductNav_Link">Bookcases</a>
<a href="#" class="pn-ProductNav_Link">Mirrors</a>
<a href="#" class="pn-ProductNav_Link">Rugs</a>
<a href="#" class="pn-ProductNav_Link">Curtains & Blinds</a>
<a href="#" class="pn-ProductNav_Link">Frames & Pictures</a>
<a href="#" class="pn-ProductNav_Link">Wardrobes</a>
<a href="#" class="pn-ProductNav_Link">Storage</a>
<a href="#" class="pn-ProductNav_Link">Decoration</a>
<a href="#" class="pn-ProductNav_Link">Appliances</a>
<a href="#" class="pn-ProductNav_Link">Racks</a>
<a href="#" class="pn-ProductNav_Link">Worktops</a>
<span id="pnIndicator" class="pn-ProductNav_Indicator"></span>
</div>
</nav>
<button id="pnAdvancerLeft" class="pn-Advancer pn-Advancer_Left" type="button">
<svg class="pn-Advancer_Icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 551 1024"><path d="M445.44 38.183L-2.53 512l447.97 473.817 85.857-81.173-409.6-433.23v81.172l409.6-433.23L445.44 38.18z"/></svg>
</button>
<button id="pnAdvancerRight" class="pn-Advancer pn-Advancer_Right" type="button">
<svg class="pn-Advancer_Icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 551 1024"><path d="M105.56 985.817L553.53 512 105.56...
CSS
* {
box-sizing: inherit;
}
.pn-ProductNav_Wrapper {
position: relative;
padding: 0 11px;
box-sizing: border-box;
}
.pn-ProductNav {
/* Make this scrollable when needed */
overflow-x: auto;
/* We don't want vertical scrolling */
overflow-y: hidden;
/* For WebKit implementations, provide inertia scrolling */
-webkit-overflow-scrolling: touch;
/* We don't want internal inline elements to wrap */
white-space: nowrap;
/* If JS present, let's hide the default scrollbar */
/* positioning context for advancers */
position: relative;
font-size: 0;
}
.js .pn-ProductNav {
/* Make an auto-hiding scroller for the 3 people using a IE */
-ms-overflow-style: -ms-autohiding-scrollbar;
/* Remove the default scrollbar for WebKit implementations */
}
.js .pn-ProductNav::-webkit-scrollbar {
display: none;
}
.pn-ProductNav_Contents {
float: left;
transition: -webkit-transform .2s ease-in-out;
transition: transform .2s ease-in-out;
transition: transform .2s ease-in-out, -webkit-transform .2s ease-in-out;
position: relative;
}
.pn-ProductNav_Contents-no-transition {
transition: none;
}
.pn-ProductNav_Link {
text-decoration: none;
color: #888;
font-size: 1.2rem;
font-family: -apple-system, sans-serif;
display: inline-flex;
align-items: center;
min-height: 44px;
border: 1px solid transparent;
padding: 0 11px;
}
.pn-ProductNav_Link + .pn-ProductNav_Link {
border-left-color: #eee;
}
.pn-ProductNav_Link[aria-selected="true"] {
color: #111;
}
.pn-Advancer {
/* Reset the button */
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: transparent;
padding: 0;
border: 0;
/* Now style it as needed */
position: absolute;
top: 0;
bottom: 0;
/* Set the buttons invisible by default */
opacity: 0;
transition: opacity .3s;
}
.pn-Advancer:focus {
outline: 0;
}
.pn-Advancer:hover {
cursor: pointer;
}
.pn-Advancer_Left {
left: 0;
}
[data-overflowing="both"]...
JavaScript
var SETTINGS = {
navBarTravelling: false,
navBarTravelDirection: "",
navBarTravelDistance: 150
}
var colours = {
0: "#867100",
1: "#7F4200",
2: "#99813D",
3: "#40FEFF",
4: "#14CC99",
5: "#00BAFF",
6: "#0082B2",
7: "#B25D7A",
8: "#00FF17",
9: "#006B49",
10: "#00B27A",
11: "#996B3D",
12: "#CC7014",
13: "#40FF8C",
14: "#FF3400",
15: "#ECBB5E",
16: "#ECBB0C",
17: "#B9D912",
18: "#253A93",
19: "#125FB9",
}
document.documentElement.classList.remove("no-js");
document.documentElement.classList.add("js");
// Out advancer buttons
var pnAdvancerLeft = document.getElementById("pnAdvancerLeft");
var pnAdvancerRight = document.getElementById("pnAdvancerRight");
// the indicator
var pnIndicator = document.getElementById("pnIndicator");
var pnProductNav = document.getElementById("pnProductNav");
var pnProductNavContents = document.getElementById("pnProductNavContents");
pnProductNav.setAttribute("data-overflowing", determineOverflow(pnProductNavContents, pnProductNav));
// Set the indicator
moveIndicator(pnProductNav.querySelector("[aria-selected=\"true\"]"), colours[0]);
// Handle the scroll of the horizontal container
var last_known_scroll_position = 0;
var ticking = false;
function doSomething(scroll_pos) {
pnProductNav.setAttribute("data-overflowing", determineOverflow(pnProductNavContents, pnProductNav));
}
pnProductNav.addEventListener("scroll", function() {
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function() {
doSomething(last_known_scroll_position);
ticking = false;
});
}
ticking = true;
});
pnAdvancerLeft.addEventListener("click", function() {
// If in the middle of a move return
if (SETTINGS.navBarTravelling === true) {
return;
}
// If we have content overflowing both sides or on the left
if (determineOverflow(pnProductNavContents,...