[slick.js]読み込み時の画面のズレを抑える方法

ただ非表示にすればいいってもんじゃない。

何でやるのか

slick.jsに限らないんだけど、仕様だとか回線が細いとか、要因がアレするとjsが走る前に画像が読み込まれて一瞬縦並びになる。

それはダサいからjsが動いたタイミングで表示するcssのハックがある。

どっちにせよ高さが変わるんで動くんですよ。

そういうやつはダサいだけでなく、googleのpagespeedinsights判定、行き着くところではSEOに関わってくる。

どうにかしましょう。

ファーストビューとかのでかいスライド

画面幅いっぱいでスライドを設置する場合。PCだと20インチレベルに耐えられる画像はあんまりスライドで出さないだろうから、左右に前後のスライドがはみ出る感じでやっていくことが多い。

そういうのを作った場合、レスポンシブも加味するのはほぼ確定なんで、ブラウザ幅により高さも変わったりする。その辺に対応するにはどうするかという、一つの提案。

サンプルの構成として、以下の通りにやっていくとする。

スライドはブラウザ幅いっぱいに配置する。

幅が広い状態では1200×600の画像を中央配置、余った左右には前後のスライドをちら見せ。狭くなると左右の余白が減っていく。ブラウザ幅が1200pxを割ったら左右のチラ見せはせず、ブラウザ幅=画像幅として縮小。幅640pxで画像を切り替える(640×480)。

<div class="wrap">
    <div class="slider">
        <div class="slide"><a href="">
            <picture>
                <source srcset="https://placehold.jp/640x480.png" media="(max-width:639.98px)" width="640" height="480">
                <img src="https://placehold.jp/1200x600.png" width="1200" height="600" alt="">
            </picture>
        </a></div>
        <div class="slide"><a href="">
            <picture>
                <source srcset="https://placehold.jp/640x480.png" media="(max-width:639.98px)" width="640" height="480">
                <img src="https://placehold.jp/1200x600.png" width="1200" height="600" alt="">
            </picture>
        </a></div>
        <div class="slide"><a href="">
            <picture>
                <source srcset="https://placehold.jp/640x480.png" media="(max-width:639.98px)" width="640" height="480">
                <img src="https://placehold.jp/1200x600.png" width="1200" height="600" alt="">
            </picture>
        </a></div>
        <div class="slide"><a href="">
            <picture>
                <source srcset="https://placehold.jp/640x480.png" media="(max-width:639.98px)" width="640" height="480">
                <img src="https://placehold.jp/1200x600.png" width="1200" height="600" alt="">
            </picture>
        </a></div>
    </div>
</div>
$(function(){
    $('.slider').slick({
        arrows: false,
        dots:true,
        speed: 500,
        autoplaySpeed: 10000,
        cssEase: 'linear',
        autoplay: true,
        slidesToScroll: 1,
        variableWidth: true,
        centerMode: true,
        swipe: true,
        infinite: true,
        pauseOnFocus: false,
        pauseOnHover: false,
        pauseOnDotsHover: false,
        responsive: [{
            breakpoint: 1199.98,
            settings: {
                centerMode: false,
                variableWidth: false,
            }
        }]
    });
})
.wrap{
    height: 600px;
}
.wrap .slider{ display: none;}
.wrap .slider.slick-initialized{ display: block;}
.wrap .slider .slide a img{
    width: 100%;
    height: auto;
    display: block;
}
@media screen and (max-width:1199.98px) {
    .wrap{
        height: 50vw;
    }
}
@media screen and (max-width:639.98px) {
    .wrap{
        height: 75vw;
    }
}

.98pxのやつはおまじないなので気にしないでください。

slick.jsのスライド自体(.slider)は不定形のもんだとして割り切る。その代わり動作自体は把握できてるんで、スライダーの親要素のサイズをcssで指定することができる。

ポイントはvwの活用で、画像の縦横比を出して親要素に放り込む。スライドはjs読み込みまで表示されないようにしてあるけど、それに関係なくスペースを確保してるんで問題ないという話。

とはいえvwはスクロールバーを無視するんで、実際のサイズよりはちょっとデカくなる

より厳密にやっていく

jsに以下を追加。

const setVw = function() {
    const vw = document.documentElement.clientWidth / 100;
    document.documentElement.style.setProperty('--vw', `${vw}px`);
}
window.addEventListener('DOMContentLoaded', setVw);
window.addEventListener('resize', setVw);

cssに追加と差し替え。

/* 追加 */
:root{
    --vw: 1vw;
}

/* 差し替え */
@media screen and (max-width:1199.98px) {
    .wrap{
        height: calc( var(--vw) * 50);
    }
}
@media screen and (max-width:639.98px) {
    .wrap{
        height: calc( var(--vw) * 75);
    }
}

スクロールバーの幅分を引いたブラウザ幅を100で割って、本当に欲しいvwを割り出す。:rootに入れることで変数的に使えるので、var()をアレしてやっていくことになる。

こうすれば画像の縦横比に合った、きっちりとした領域を確保できる。それはそれでいいんだけど結局js依存なんで、壊れないようにcssで:rootで本来のvwは指定するし、jsが読まれるまでは本来のvwが使われるしという、結局微妙に動く。振れ幅が抑えられただけですね。

全く動かない、大体のエリアを作るか多少動いてでもぴったりのエリアを作るか。デザイン次第のところもあるし制作の方針もあるだろうし、好きな方を取ればいいと思います。

プレーンな状態でガッツリ動いてたのと比べたらどっちもマシ。

端までぶち抜かないタイプ

考え方は前述とほぼ同じ。アプローチが変わる。

可変にしないのであれば実数で縦横を決めちゃって、はみ出したら削る感じにすればいい。

<div class="slider">
    <div class="slide">***</div>
    ︙
</div>
.slider{
    width: 360px;
    height: 240px;
    overflow: hidden;
}

可変だと例えばこんなのとか。

<div class="wrap">
    <div class="slider">
        <div class="slide">***</div>
        ︙
    </div>
</div>
.wrap{
    width: 100%;
    height: 0;
    padding-top: 75%; /* 4:3 */
    position: relative;
}
.slider{
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
}

youtube埋め込みのレスポンシブ化と同じ組み立て。

これらで注意なのがドットとか矢印。overflow:hidden;を使うと、標準で枠外に設置されるこれらは表示されない。使わない、内側に入れるとか調整するならOK。外側に配置したければラッピングは必須で、その分を追加した寸法でやっていくことになる。デザインとかし始めたらサイズが変わるんで、めんどくさいんで割愛。矢印はともかくドットはbuttonで作られてる手前、「何枚あってどこを表示してる」が分かるのはいいけどhtmlタグの存在意義とか動作的にいって、あんな小さいのはスマホ表示時の評価としてはネガティブな存在なんで、うん。どうですかね。

コメント

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