本ページはHIGA TSUBASAが属する個人プロジェクト「COFUS」内のBLOGコンテンツです。

JavaScriptでスクロールに合わせて特定の要素にActiveクラスを追加する

JavaScriptでスクロールに合わせて特定の要素にActiveクラスを追加する

HIGA TSUBAS

Frontend Engineer HIGA TSUBAS

1992年生まれ、沖縄県育ち、現在大阪暮らし。フリーなフロントエンドエンジニアとしてコーディング案件をメインに行いながら、Web制作・Webサイト運営・ツール制作などの活動を行っています。

スクロールに合わせて特定の要素にActiveクラスを付与する実装の例です。毎回作っては破棄しているので備忘録としてメモしておきます。

下記例ではスクロールし特定の要素が事前に設定した位置に達した時にActiveクラス(例ではis-visibleクラス)を1回付与する想定です。

// Scrollイベント.
window.addEventListener(
  'scroll',
  throttle(100, () => {
    getClientRect();
  }),
  false
);

// 要素取得(特定の要素はここで指定します).
const scroll_target = {
  '#news'       : document.querySelector('#news'),
  '#about'      : document.querySelector('#about'),
  '#possible'   : document.querySelector('#possible'),
  '#skilllists' : document.querySelector('#skilllists'),
  '#work'       : document.querySelector('#work'),
  '#blog'       : document.querySelector('#blog'),
  '#contact'    : document.querySelector('#contact')
};

/**
 * getClientRect
 * @description 要素の高さとか取得します.
 */
const getClientRect = () => {
  for (let key of Object.keys(scroll_target)) {
    let clientRect = scroll_target[key].getBoundingClientRect();
    let y = clientRect.top;

    let num = getDeviceType() === 'lg' ? 750 : 600;
    if (y <= num) {
      if (!scroll_target[key].classList.contains('is-visible')) {
        scroll_target[key].classList.add('is-visible');
      }
    }
  }
};

最適化するとよりページパフォーマンスが可能だと思いますが、改めて見返すと私はよくこんな感じで実装する事が多いようですね。やはり見え返すのは大事です。

scrollイベントはthrottle処理で間引いてあげる

scrollイベントの所はthrottle処理で間引いて上げるとページパフォーマンスの向上になります。

throttle処理は別途用意して書いてあげてもいいですし、私はよくthrottle-debounceを利用していますのでパッケージを呼んで上げて、後はthrottle(100, () => {})内で処理を書いてあげます。

ちなみに上記プラグインだとdebounceも利用可能になります。(便利!)

PC、SPでタイミングを変える

getClientRect()のActiveクラスを付与するスクロール位置はPC・SPで分けて使うことも多いです。
例ではPCの場合(lg)は750、そうでなければ600という値に設定しています。

let num = getDeviceType() === 'lg' ? 750 : 600;

getDeviceType()は制作時に個人的によく利用するので最初でfunctions.js等に設置する事が多いです。中身はウインドウサイズと比較してPCサイズなのか、SPサイズなのか返しているだけですので案件に合わせて色々変わったりします。

/**
 * get_deviceType
 * @return string 'lg' or 'sm'
 * @description breakpointとウインドウサイズを比較してlgかsmか返します.
 */
const getDeviceType = () => {
  let windowWidth = window.innerWidth;
  let deviceType = windowWidth > define.breakpoint ? 'lg' : 'sm';
  return deviceType;
};

プラグインを利用せずともActiveクラスの付与程度で可能なアニメーションであれば、上記の様な形で簡素に実装してしまう事も割と多いです。自由度も高いので案外複雑な表現も出来たり。
備忘録ではありますがWeb制作者の参考になりましたら幸いです。