一般社団法人 全国個人事業主支援協会

COLUMN コラム

作ったよ。

というお話。

 

position: sticky;なstyleを持つコンポーネントを用意すればいいだけ。

と思っていたのですが、
position: sticky;はコンテナ(親要素?)の中でのみfloatするようで、

<div>
 <div style="position: sticky; ..." >
  aaa
 </div>
</div>

のようなHTMLではstickyしてくれないようで、
汎用コンポーネントとしては非常に使い勝手が悪い。

 

そのため、stickyしたいところではposition: fixed;

 

元の位置に来たらposition: static(|relative);になるコンポーネントを作ることとした。

 

このコンポーネントを作成する上でポイントとなるのは、Intersection Observerだ。

 

Observerが交差を判定したら、styleを切り替えれば良い。

 

しかしその前に確認が必要だった。

floatしている要素にObserverは判定するのか?

結論はNO。

 

仕方がないのでダミーのElementを置くことで判定することとした。

 

JSXはこう。

 <div>
  <div
   className={classNames({
    isStatic: isIntersecting,
   })}
  >
   {children}
  </div>
  <div ref={dummyRef} />
 </div>

あとはIntersection Observerでdummyを監視してあげれば良い。

useEffect(() => {
 (async () => {
  if (typeof window.IntersectionObserver === 'undefined') {
   await import('intersection-observer');
  }

  if (!dummyRef.current) return;

  observer = new IntersectionObserver(
   entries => {
    const dummyEntry = entries[0];
    setIsIntersecting(dummyEntry.isIntersecting);
   },
   { threshold: 1 }
  );
  observer.observe(dummyRef.current);
 })();
}, []);

実物は、ダミーに高さを持たせて、元の位置に戻るときのカクツキをなくしたり、

イベントハンドラを用意していたりしますが、

その辺は必須ではないため、省略しています。

The following two tabs change content below.

江尻 翔

フリーでSEをしています。 バックエンドから逃げて、 現在はフロントエンドメインでお仕事中。

最新記事 by 江尻 翔 (全て見る)

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア