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.1;
  transition: opacity 500ms;
}

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

.container {
  display: flex;
  margin: 20px;
  justify-content: space-between;
}
.container .js-ani {
  margin: 0;
}

JavaScript

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