Modern browsers may have changed (thought I'd sorted this out years ago, but technique from an older project no longer works) but this is what I am using now, not having users or personal gripe serious enough to explore JavaScript scroll-event-foo:
<style>
html, body {
overscroll-behavior: none;
/* nothing special */
margin: 0; padding: 0;
background-color: #000000; /* anything on-theme */
}
.scrollBody {
display: block;
height: 100vh; /* 100% does not do it */
overflow: scroll;
overscroll-behavior: contain;
}
</style>
<body>
<div class='scrollBody'>
<!-- everything else -->
</div>
</body>
Basically, assign and constrain scrolling to the element immediately within the body. You may still get rubber-banding if users starts the gesture on a fixed or absolute element like a header or footer area, so at least set the <body>
colour on-theme to minimize how noticeable it is.
Tests well in Chrome, Safari and Edge at this time (on macOS with touchpad, possibly a factor) and might be a starter clue/approach if you're working it out in other environments.