scrollIntoView() doesn't scroll anywhere
Asked Answered
P

2

11

I can't get Element.scrollIntoView() to work. I have the code below. There are two locations that it should scroll to, depending on some variable. However, it doesn't scroll to either of them. What am I doing wrong?

class Page extends Component {
    scrollToMyRef = (id) => {
        var ref = document.getElementById(id);
        console.log("Ref1: " + ref);            // returns [object HTMLElement]
        console.log("Ref2: " + document.ref);   // returns undefined
        console.log("Id: " + id);               // returns myRef
        ref.scrollIntoView({
            behavior: "smooth",
            block: "start",
        });
    };

    componentDidMount() {
        if (this.props.location.state) {
            if (this.props.location.state.origine) {
                this.scrollToMyRef("myRef");
            } else {
                this.scrollToMyRef("myTopRef");
                });
            }
        }
    }

    render() {
        return (
            <div
                id="myTopRef"
                key="pricing"
                className="pricing"
            >
                ...
            </div>
            <section id=myRef className="section">
                ...
            </section>
            ...
        )
    }
Particularism answered 18/2, 2022 at 23:35 Comment(5)
You probably need to show your CSS and markup: is the element #myRef in an overflowing parent? scrollIntoView only works if the element itself is outside the viewport + its parent is scrollable.Axilla
In the block property, try specifying nearest instead of start, but there's no guarantee. I used it in a table a while ago and it works as stated by Terry: only if the element is outside the viewport.Rakia
Unfortunately, that doesn't seem to make a difference. It's still not scrolling.Particularism
Interestingly, if I remove behavior: "smooth", or set it to auto, my original code works. Any idea why this is? I would like to use the smooth behavior...Particularism
I've got it working now. I needed to set a time delay: ` scrollToMyRef = (id) => { var ref = document.getElementById(id); setTimeout(function () { ref.scrollIntoView({ behavior: "smooth", block: "start", }); }, 100); };`Particularism
P
35

After setting a time delay it worked:

scrollToMyRef = (id) => {
      var ref = document.getElementById(id);
      setTimeout(function () {
           ref.scrollIntoView({
               behavior: "smooth",
               block: "start",
           });
      }, 100);
};
Particularism answered 19/2, 2022 at 3:16 Comment(4)
This fixed my issue, made me soooooo happy!!! No idea why it works, though.Restful
Same problem as OP, but this time delay didn't solve it for me. Mine still doesn't scroll at all until I remove the behavior: smooth.Hospitalet
It will depend at what point you are invoking scrollToMyRef, but if it's after a change of state, without actually waiting for the change of state to render, then that might be the reason setTimeout solves your problem. If that's the case, you can use setTimeout(..., 0) that is, there's no need to wait at all, just run the function on the next iteration of the event loop.Comfrey
That solution did not make me happy. But it did workNawrocki
G
3

I was facing the same issue. scrollIntoView was working only if behavior was auto. Setting a delay fixed some cases but not all of them. In addition, Safari doesn't support smooth scrolling at all. I used this polyfill which works for all browsers and all cases.

You can use it in the following way:

import { scrollIntoView } from "seamless-scroll-polyfill";

scrollIntoView(element, {
    behavior: "smooth",
    block: "start",
  },
  {
    duration: 250 // aprox. the duration that chrome uses,
  }
);

Gathard answered 9/11, 2022 at 19:22 Comment(1)
According to caniuse, safari should offer full support as of 16+. It's a shame this polyfill is necessary. caniuse.com/?search=scrollIntoViewReturnee

© 2022 - 2024 — McMap. All rights reserved.