React 対象の要素までScrollさせる

2022-04-30
2022-04-30

Intro

targetステートを変更した時の副作用として、target.idを持つ要素までスクロールする機能を作る。 useRefを使用せず、idを使用した方が単純だったので、idを使用している。 (特に調査はしていない。)

scrollTo

tsx
// ⚠️ target と item は同じデータ構造 useEffect(() => { if (!target) { return } const targetEl = document.getElementById(target?._id) const containerEl = document.getElementById('container') const targetTop = targetEl?.getBoundingClientRect().top || 0 const containerTop = containerEl?.getBoundingClientRect().top || 0 const containerScrollTop = containerEl?.scrollTop || 0 const marginTop = 36 // 👈 スクロールの位置36px下に調整する const scrollSize = targetTop - containerTop + containerScrollTop - marginTop containerEl?.scrollTo({ top: scrollSize, behavior: 'smooth' }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [target])
tsx
<div className="container overflow-y-auto"> {items.map((item, index) => ( <div id={item.id}> {item.name} </div> ))} </div>

改良する scrollIntoView

scroll-paddingをという便利なcssプロパティがあったので使用したら、スッキリした。

scroll-padding - CSS: カスケーディングスタイルシート | MDN

また、スクロールさせるコンテナのidも消すことができた。

tsx
useEffect(() => { if (!target) { return } const targetEl = document.getElementById(target?._id) targetEl?.scrollIntoView({ behavior: 'smooth' }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [target])
tsx
// ⚠️ overflow-y-autoは必須 <div className="scroll-py-[36px] overflow-y-auto"> {items.map((item, index) => ( <div id={item.id}> {item.name} </div> ))} </div>