title: Conflict when simultaneously using keyboard events for scrolling and CSS scroll snapping
body: <p>You can horizontally scroll my demo page by pressing <kbd>Space Bar</kbd>, <kbd>Page Up / Page Down</kbd> and <kbd>Left Arrow / Right Arrow</kbd> keys. You can also snap scroll with a mouse or trackpad.</p>
  
  <p><em>But only one or the other works.</em></p>
  
  <p>Is there a way that keyboard events and CSS scroll snapping can coexist? What am I missing? Any help would be really appreciated, since I’ve been struggling with this problem for over a week.</p>
  
  <hr>
  
  <blockquote>
    <p><a href="https://codepen.io/boletrone/full/bGGZGmz" rel="noreferrer">Check out my demo on CodePen</a></p>
  </blockquote>
  
  <p><em>(Please uncomment the relevant piece of CSS code to enable the scroll snapping effect in order to see that keyboard shortcuts stop working.)</em></p>
  
  <hr>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
  
  const sections = Array.from(document.querySelectorAll("section")).sort(
    (s1, s2) =&gt; {
      return s1.getBoundingClientRect().left - s2.getBoundingClientRect().left
    }
  )
  
  const getSectionInView = () =&gt; {
    const halfWidth = window.innerWidth / 2
    const index = sections.findIndex(
      section =&gt;
        section.getBoundingClientRect().left &lt;= halfWidth &amp;&amp;
        section.getBoundingClientRect().right &gt; halfWidth
    )
    return index
  }
  
  const getNextSection = dir =&gt; {
    const sectionInViewIndex = getSectionInView()
    const nextIndex = sectionInViewIndex + dir
    const numSections = sections.length
    const nextSectionIndex =
      nextIndex &lt; 0 || nextIndex &gt;= numSections ? sectionInViewIndex : nextIndex
    return sections[nextSectionIndex]
  }
  
  const container = document.scrollingElement
  
  const animateScroll = dir =&gt; {
    const from = container.scrollLeft
    const { left } = getNextSection(dir).getBoundingClientRect()
    return progress =&gt; (container.scrollLeft = from + progress * left)
  }
  
  window.onload = () =&gt; {
    document.body.onkeydown = event =&gt; {
      switch (event.key) {
        case " ": // Space Bar
        case "PageDown":
        case "ArrowRight": {      
          animate({
            easing: "out-quintic",
            change: animateScroll(1)
          })
          break
        }
        case "PageUp":
        case "ArrowLeft":  {      
          animate({
            easing: "out-quintic",
            change: animateScroll(-1)
          })
          break
        }
      }
    }
  }</code></pre>
  </div>
  </div>
  </p>
  
  <hr>
  
  <p>Note: I’m using a small and elegant module called <a href="https://github.com/bendc/animateplus" rel="noreferrer">Animate Plus</a> for achieving the smooth scrolling animation.</p>
  
  <hr>
  
  <p>Update: @Kostja’s solution works in Chrome, but not in Safari for Mac or iOS, and it’s crucial to me that it works in Safari.</p>