YANNTASTIC5915
YANNTASTIC5915

Reputation: 50

How to make scroll-snap-type mandatory but also allow smooth scrolling on sections

I'm using mandatory scroll snapping, and that works when the section isn't bigger than the page. It doesn't work when the section needs to be bigger than the page.

I basically need to use scroll snap mandatory for a few sections, around 5, and then I need it to kind of ignore the mandatory, so I get smooth scrolling later.

I would like a no-js approach.

I've tried separating the snapping part into one div, and the non snapping part into another, but I want it to snap to the top of the non-snapping part, then scroll smoothly.

Here's the code:

body {
    padding: 0;
    margin: 0;
    font-family: sans-serif;
    overflow: hidden;
    width: 100%;
    height: 100%;
}

.scroller {
    max-height: 100vh;
    min-height: 100vh;
    overflow-y: hidden;
}

.blue {
    background-color: blue;
}

.red {
    background-color: red;
}

.snapper {
    flex-basis: 100vw;
    min-height: 100%;
    overflow-y: scroll;
    scroll-snap-type: y mandatory;
    max-height: 100vh;
}

.longer {
    min-height: 500vh;
}

.snapper > div {
    min-height: 100vh;
    scroll-snap-align: start;
    display: flex;
    flex-flow: column;
    justify-content: center;
}
<body>
  <div class="scroller">
    <div class="snapper red">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div class="longer blue">8</div>
    </div>
  </div>
</body>

Upvotes: 0

Views: 712

Answers (1)

YANNTASTIC5915
YANNTASTIC5915

Reputation: 50

OK. I found a fix, albeit javascript, but it works really well. What it does is when it gets to the target point, it adds a no-scroll-snapping class, and the scroll snapping targets a :not(.smooth).

var snapper = document.getElementsByClassName("snapper")[0];
all = Array.from(snapper.children);
all.forEach(element => {
    element.addEventListener("wheel", function(e) {
        if (snapper.scrollTop >= window.innerHeight*7 && e.deltaY > 0) {
            snapper.classList.add("smooth");
        } else if (snapper.scrollTop <= window.innerHeight*7) {
            snapper.classList.remove("smooth");
        }

    })
})
body {
    padding: 0;
    margin: 0;
    font-family: sans-serif;
    overflow: hidden;
    width: 100%;
    height: 100%;
}

.scroller {
    max-height: 100vh;
    min-height: 100vh;
    overflow-y: hidden;
}

.blue {
    background-color: blue;
}

.red {
    background-color: red;
}

.snapper {
    flex-basis: 100vw;
    min-height: 100%;
    overflow-y: scroll;
    &:not(.smoothsnap) {
        scroll-snap-type: y mandatory;
    }
    max-height: 100vh;
}

.longer {
    min-height: 500vh;
}

.snapper > div {
    &:not(.longer) {
        min-height: 100vh;
    }
    scroll-snap-align: start;
    display: flex;
    flex-flow: column;
    justify-content: center;
}
<body>
  <div class="scroller">
    <div class="snapper red">
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <div>4</div>
      <div>5</div>
      <div>6</div>
      <div>7</div>
      <div class="longer blue">8</div>
    </div>
  </div>
</body>

Upvotes: 0

Related Questions