画面に表示されるタイミングでアクションを起こしたい時に便利な、inviewというjQueryプラグインがあります。
その要素の位置までスクロールしたらフェードインで表示する、といったエフェクトを簡単に実装出来るので大変便利に使っているのですが、横並び+複数行の要素を順に表示させるのに手こずったので、その時に処理をメモしておきます。
やりたいこと
以下のイメージのように、画面内に表示されたタイミングで、横並び要素が順に表示(フェードイン)する。
コード
HTML
jQueryとinview.jsを読み込みます。
<script src ="js/jquery.js"></script>
<script src ="js/jquery.inview.min.js"></script>
順に表示させる要素.item
は、包括要素.column
で囲います。
<div class="column"><!-- 全体を囲う包括要素 -->
<div class="item"></div><!-- 順に表示したい要素 -->
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div><!-- /.column -->
CSS
/* 包括要素 */
.column {
padding-bottom: 50px;
}
/* 順に表示したい要素 */
.item {
display: none; /* デフォルトは非表示にしておく */
float: left; /* 今回はfloat指定 ※理由は後述 */
margin-top: 50px; /* 上下にmarginを入れるならjsにも要設定 */
width: 25%; /* 100% ÷ 一行に並べる要素数 */
height: 8em; /* 任意の値。要設定 */
/* 以下二行は本サンプル用のスタイル */
line-height: 1;
counter-increment: item;
}
/* 以降は本サンプル用のスタイル */
.item::before {
content: counter(item);
display: block;
margin-top: 1.5em;
text-align: center;
font-size: 2em;
}
.item:nth-of-type(odd) {
background-color: #dddddd;
}
.item:nth-of-type(even) {
background-color: #efefef;
}
.bottom {
padding: 10%;
background-color: #A4CDFF;
text-align: center;
}
.scroll p {
padding-top: 20%;
text-align: center;
font-size: 3em;
}
jQuery
$(function() {
var getHeight = 0;
$('.item').each(function(){
// 要素の高さを合算
// ただし、margin-top:50px;なので、.itemの高さ+50px の計算にする)
getHeight = getHeight + ($(this).outerHeight() + 50);
});
getHeight = (getHeight / 4); // 一行あたりの要素の数
// 包括要素の高さを予め指定する
$('.column').css('height',getHeight);
// ここから inview.js の設定
// 包括要素のclass名(.column)を指定
$('.column').on('inview', function(event, isInView) {
if (isInView) {
$(item); // 表示されたら実行するアクション(関数)名
}
});
// 実行するアクション(関数)の設定
function item() {
// 一つ目の非表示要素をフェードインし、その後同じ処理を繰り返す
// 次の非表示要素をフェードインし、また次の...と順にフェードインする
// 250はスピード(0.25秒)
$('.item:hidden').first().fadeIn(250, function () {
item(); // 繰り返し
});
}
});
- 全体を囲っている
.column
が画面に表示されたタイミングでアクション実行 - 「最初の非表示
.item
を表示する」を繰り返すので、一つめを表示したら2つめが「最初の非表示.item
」になり表示される、以降繰り返し
という仕様です。
失敗例
今どきfloatレイアウトはないっしょ!と思われたかもしれませんが、FlexboxやCSS Grid Layoutで.item
を並べようとしましたが、思ったような動きになりませんでした…。
▼参考:flexboxでレイアウトしたサンプル
.column
の高さをjavascriptで指定しているから.item
が縦に均等割付されてしまい、二行目以降このようになるのだと思います。
ちなみに、.column
の縦幅を指定しないと後の要素がスムーズに表示されないため、今回のケースでは縦幅を指定することにしました。
▼参考:包括要素(.column)の縦幅を指定しないサンプル
青い要素がガタガタしてしまい、あまりスマートではないですね…。
結果、floatレイアウトで落ち着きました。
flexboxやCSS Grid Layoutでも出来るよ!もっとスマートに出来るよ!という方がいらっしゃったら是非ご教示ください。
下記のページを参考にさせていただきました。ありがとうございます。
▼順番に画像をフェードイン表示する
http://jobtech.jp/js/224/