5

I have a vertically long SVG image that I need to scroll to some specific element with a specific id.

const el = document.getElementById(id);
el.scrollIntoView({
  behavior: 'smooth',
  block: 'center'
});

This works fine in chrome but Firefox scrolls into view the top of the SVG file, not the selected element.

I reproduced the bug in a stackblitz:

https://stackblitz.com/edit/react-wkoiwq

https://react-wkoiwq.stackblitz.io

In chrome the #hotplate element is moved to the center while in firefox the top of the SVG is moved to the center.

Try changing center, with start and end to see the effect.

Is there a way to fix / avoid this problem?

gyc
  • 4,300
  • 5
  • 32
  • 54

2 Answers2

3

Perhaps doing it manually is the right solution:

For example:

var el = document.getElementById("hotplate");

// { block: "top" } behavior:
let newScrollY = window.pageYOffset + el.getBoundingClientRect().top;

// adjust to behave like { block: "center" }
newScrollY = newScrollY - document.documentElement.clientHeight/2;

window.scrollTo({top: newScrollY, behavior: 'smooth'});
Nickolay
  • 31,095
  • 13
  • 107
  • 185
3

I think the main issue is that Firefox animates to the original position of the element #hotplate which the boundaries of the parent SVG. Firefox does not account for y attribute.

To overcome this you can wrap your svg code in a container and add a span that has the same position as the svg child element with an absolute position.

You can change your HTML to:

<div class='container'>
   <span id='hotplate-ref"></span>
   <svg>.....</svg>
</div>

and then add to your CSS:


.container
{
  position: relative;
}

#hotplate-ref
{
  position: absolute;
  top: 1703px; /* includes margin top of svg (1400px) + y attribute of svg element (503px) */
  width: 0px;
  height: 0px;
  visibility: hidden;
  pointer-events: none;
}

and finally change "componentDidMount()" to this:

    const el = document.getElementById("hotplate-ref");
    el.scrollIntoView({ 
      behavior: 'smooth', 
      block: 'start' 
    });

I tested the code in both Chrome and FF and it worked fine.

Obviously, you can do this with other svg child elements as well.

Kalimah
  • 11,217
  • 11
  • 43
  • 80