[css+js]スクロールしたら要素がフェードインするやつの自作

汎用性求めたらプラグイン作ってる気持ちになってくる。

完成イメージ

今日に至って何も珍しくない、スクロールしたらタイトルとか画像とかがフェードインするやつ。フェードインついでに上下左右どっからかスライドしてくるやつ。ついでに、フェードインするタイミングも調整できるやつ。

個人的なアレで、フェードインは1回あればよくて、ページの途中から表示した際に上にスクロールした場合はフェードインしなくていい。要するに「戻る」動作のときに動かれてもめんどくさいだけだよねっていう。ついでに言えば下にスクロールしたときに合った動作は、上にスクロールしたときに違和感がある。横移動のスライドはいいけど縦のスライドは妙な感じになる。というのと、見出しが後から表示されるのは気持ちが悪い。そういう個人的な好み。

構築イメージ

発火前と発火後それぞれはcssで作る。発火はjsで行う。発火タイミングとかフェードのバリエーションはclassで指定する。

組む

前提として、これが完璧なものではない。後から見返したら修正点はいくらでも出てくるだろうことは踏まえておく。

css

.fade,.fadeUp,.fadeDown,.fadeLeft,.fadeRight{
    position: relative;
    opacity: 0;
    transition: all 1s ease;
}
.fadeUp{ top: 40px;}
.fadeDown{ bottom: 40px;}
.fadeLeft{ left: -100px;}
.fadeRight{ right: -100px;}
.fade.active,.fadeUp.active,.fadeDown.active,.fadeLeft.active,.fadeRight.active{
    opacity: 1;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

class別に動作を仕込む。.activeを付与したら本来の位置に戻るよって感じ。

transitionで表示・移動の時間を制御。
フェードイン時に移動する幅もここで指定。

※「position:relative;」ありきで表示位置を変更してるので、他のpositionを仕込んだ要素に付与するとえらいことになる。

html

<h1 class="fadeUp delay1000">見出し見出し見出し見出し見出し</h1>

フェードインさせたい要素にclassを付ける。

「delay1000」はjsの方で使う。

js(jQuery)

jQuery3系でのみ動作確認済み。

$(function(){
    var windowHeight = $(window).height();
    var delayScroll = 200;
    $(window).resize(function(){
        windowHeight = $(window).height();
    }).on('load scroll',function(){
        var scrollTop = $(window).scrollTop();
        $('.fade,.fadeUp,.fadeDown,.fadeLeft,.fadeRight').each(function(){
            if(!$(this).hasClass('active')){
                var delayCnt = 0;
                var delayCheck = $(this).attr('class').split(' ');
                for(var i=0; i<delayCheck.length; i++){
                    if(delayCheck[i].match(/delay/)){
                        delayCnt = delayCheck[i].replace(/delay/g,'');
                    }
                }
                var fadePos = $(this).offset().top;
                if(scrollTop >= fadePos - windowHeight + delayScroll){
                    $(this).delay(delayCnt).queue(function(){$(this).addClass('active');});
                }
            }
        })
    })
})

jsが読める人だったら何してるのか分かると思う。

  • スクロールしてブラウザ上に要素が現れたら.activeを付与する
  • 出現直後に発火すると急すぎるんで余裕をもたせる(delayScroll)
  • 発火用classと一緒に「delay***」が入っていれば、数値を抽出して発火に遅延を加える(delayCnt)

要素の出現を計測するためにはブラウザの高さを取得しておく必要があるんだけど、pcからの閲覧を踏まえてブラウザの高さは可変する前提で考えるので、読み込み時だけじゃなくリサイズ時にも高さを取得する内容を加えてある。

課題とかメモとか

現状の必須要件をクリアしただけの内容なんで、見直す部分はあると思う。

個別にdelay(遅延)を設定する必要性

横並びの要素を順番にフェードインさせたいって場合はそれぞれにディレイをかけないといけない。ディレイがないと一斉に表示されてしまう。

単純に発火classが同階層に並んでたら遅延を付与するみたいな仕組みも作れるけど、それを組み込んじゃうとディレイの数値をいじれなくなっちゃうというか、いじれる前提を加えたらすごくめんどくさくなるんで、使い勝手を考えたら個別に数値を充てるのがいいのかなって感じ。

data属性の方がいいんだろうか

こんな感じで管理することもできる。

<h1 data-fade="Up" data-delay="1000">見出し見出し見出し見出し見出し</h1>
データ属性の使用 - ウェブ開発を学ぶ | MDN
HTML5 は、特定の要素に関連付ける必要があるが、定義済みの意味を持つ必要のないデータに対する拡張性を念頭に置いて設計されています。 data-* 属性により、標準外の属性、 DOM の追加プロパティ、 Node.setUserData() のような特殊な方法に頼らずに、標準的な意味のある HTML 要素に追加情報を...

data属性はjsでアクセスできるしcssでも指定できるから、今回みたいなケースでも問題なく使えるってことになる。活用シーンとしてはデザイン用途のclass名との重複回避だけど、どうなんですかね。

あー、wpで記事を書いてそれの中に仕込みたいならclassのほうが良いですね。ビジュアルエディタで完結できますね。

汎用性をもたせるべきかどうか

position:absolute;を付与してる要素に対応するとか、topやらleftやらを既に指定してる要素に対応させるとか、jsを作り込めば初期値を取得してpositionの判別からのどうのこうのとか位置設定の数値を調整するとか、できないことはないんだけど、そうすると全ての条件に対応できてないと中途半端になっちゃうし、設定内容が重複すると優先度で負けたらめんどくさいし、とか問題点が結構出てくるんで、そこらへんのフォローを考えたら、「こっちのルールに合わせて調整してね。上手く使ってね」をやった方がお互い幸せになれる気がする。

コメント

タイトルとURLをコピーしました