Preserve an element's position in the viewport after a layout shift
My app includes content areas that expand and collapse. A lot like accordions, except they take up the whole page and can be huge.
When you open one, whatever's open gets closed, and that makes whatever you just clicked on jump around as the previous content area stops taking up space on the page.
Here's a code snippet I put together that keeps whatever you just clicked at the same spot in the viewport after the layout shift:
/**
* This ensures that the element is at the same position within the viewport
* after a layout shift.
*
* MUST be called BEFORE triggering the layout shift.
*
* IT can only do so much - if the layout shift cuts off enough content, the
* element will still wind up positioned higher in the viewport than before.
*/
export const retainScrollPosition = (el: Element) => {
const targetViewportPosition = el.getBoundingClientRect().top;
requestAnimationFrame(() => {
const newPagePositon = el.getBoundingClientRect().top + window.scrollY;
window.scrollTo({ top: newPagePositon - targetViewportPosition });
});
};