JSFiddle - React, Tailwind, and code Playground

by jyoze

HTML

<div id="dummy-scroller">
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
  <div class="js-ani"></div>
</div>

CSS

body {
  margin: 0;
}

#dummy-scroller {
  height: 5000px;
}

.js-ani {
  width: 100px;
  height: 100px;
  padding: 10px;
  background: red;
  margin: 100px auto;
  opacity: 0.3;
  transition: opacity 500ms;
}

.js-ani.js-ani-on {
  opacity: 1
}

JavaScript

$(function () {
	// 繰り返し使うものは、毎回計算せずに変数に保存しておきます
	var $window = $(window);
	var $targets = $('.js-ani'); 
  // あとでクラスを変えたい時、ここだけ編集すればいいようにしておきます
  var onClass = 'js-ani-on';
  
  // ページ更新などで、画面の途中から表示される場合のテスト
  // $window.scrollTop(500);
  
  var options = {
  	offset: function ($target) {
    	return $target.outerHeight()
    }
  }
  
  // 初期表示で各要素の座標を判定して処理する
  toggleClassOnScreenEdges(options);
  
  // スクロールするたびに各要素の座標を判定して処理する
	$window.on('scroll', function () {
    toggleClassOnScreenEdges(options);
  });
  
	function toggleClassOnScreenEdges (options) {
  	if (!options) {
    	options = {
      	offset: 0
      }
    }
  
    var scrollTop = $window.scrollTop();
    var scrollBottom = scrollTop + $window.outerHeight();
    
  	$targets.each(function () {
    	var $target = $(this);
      var targetTop = $target.offset().top;
      var targetBottom = targetTop + $target.outerHeight();
      var offset = typeof options.offset === 'function'
      	? options.offset($target)
        : options.offset
      
      // 要素の上辺(+offset)が画面の下辺よりも上にあり、
      // 要素の下辺(-offset)が画面の上辺よりも下にあるとき、
      // 要素のすべてが画面の中にあると判定する
      if ((targetTop + offset) < scrollBottom && (targetBottom - offset) > scrollTop) {
        $target.addClass(onClass);
      } else {
        $target.removeClass(onClass);         	
      }
    });
  }
});