Reputation: 4789
I have an entirely horizontally spread page that one can scroll by pressing, for example, Space Bar, Page Down, Right Arrow, Home, End, and etc, to navigate.
I currently have two problems that I would like to solve:
When pressing Right Arrow or Left Arrow keys, the page is moved slightly more than 100vw, but the goal for it is to have perfectly aligned page edges with the window.
If for instance, you press the Page Down key multiple times when you reach the end of the page, it will take you the same number of Page Up presses to scroll back.
I would greatly appreciate any help in solving this.
Here is my code:
let scrollAmount = 0
const container = document.documentElement
window.onload = () => {
document.body.onkeyup = event => {
switch (event.code) {
case "Space":
case "PageDown":
case "ArrowRight": {
scrollAmount += window.innerWidth
break
}
case "PageUp":
case "ArrowLeft": {
scrollAmount -= window.innerWidth
break
}
case "Home":
case "ArrowUp": {
scrollAmount = 0
break
}
case "End":
case "ArrowDown": {
scrollAmount = container.scrollWidth
break
}
}
container.scrollTo({
top: 0,
left: scrollAmount,
behavior: "smooth"
})
}
}
// Reset the scrollAmount if the user scrolls back manually.
window.onscroll = event => {
scrollAmount = container.scrollLeft
}
* {
margin: 0;
padding: 0
}
html { height: 100% }
html, body, section {
display: flex;
flex-grow: 1
}
body {
scroll-snap-type: x mandatory;
scroll-snap-points-x: repeat(100%);
overflow-x: auto
}
section {
display: grid;
place-items: center;
flex: 1 0 100%;
scroll-snap-align: center
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 { color: white }
<section><h2>1</h2></section>
<section><h2>2</h2></section>
<section><h2>3</h2></section>
Upvotes: 1
Views: 1492
Reputation: 1041
Adding event.preventDefault()
and changing the listener to keydown
instead of keyup
will prevent the default continuous scrolling for the arrow keys. This works because the arrow key scrolling is triggered while it's held down (which we've now prevented), while the event listener was only being triggered when the arrow key is lifted.
You could do the same (add event.preventDefault()
, that is) for Home and End to prevent all horizontal scrolling.
let scrollAmount = 0
const container = document.documentElement
window.onload = () => {
document.body.onkeydown = event => { // <-----------
switch (event.code) {
case "Space":
case "PageDown":
case "ArrowRight": {
event.preventDefault(); // <-----------
scrollAmount += window.innerWidth
break
}
case "PageUp":
case "ArrowLeft": {
event.preventDefault(); // <-----------
scrollAmount -= window.innerWidth
break
}
case "Home":
case "ArrowUp": {
scrollAmount = 0
break
}
case "End":
case "ArrowDown": {
scrollAmount = container.scrollWidth
break
}
}
container.scrollTo({
top: 0,
left: scrollAmount,
})
}
}
// Reset the scrollAmount if the user scrolls back manually.
window.onscroll = event => {
scrollAmount = container.scrollLeft
}
* {
margin: 0;
padding: 0
}
html { height: 100% }
html, body, section {
display: flex;
flex-grow: 1
}
body {
scroll-snap-type: x mandatory;
scroll-snap-points-x: repeat(100%);
overflow-x: auto
}
section {
display: grid;
place-items: center;
flex: 1 0 100%;
scroll-snap-align: center
}
section:nth-of-type(1) { background: orange }
section:nth-of-type(2) { background: limeGreen }
section:nth-of-type(3) { background: royalBlue }
h2 { color: white }
<section><h2>1</h2></section>
<section><h2>2</h2></section>
<section><h2>3</h2></section>
Upvotes: 1