こんにちは!のせっち@nosecchi01です。
サイトスピードアップに欠かせないlazyloadですが、ページ内リンクとは相性が悪く、意図した場所に着地してくれなくなることがあります。
今回はそちらの解消方法を解説します。
なぜlazyloadを使うとページ内リンクがズレるのか?
理由は下記です。
- lazyloadを使うと最初は画像が読み込まれない。
- ページ内リンクボタンを押すと指定idの位置(ターゲット)までスクロールが始まる。
- 画像読み込みが始まる。
- ボタンを押したときと、ページスクロール後のターゲット位置が画像分異なるため位置ずれが起きる
要は、画像がある、ないでY座標が異なるため、その分が位置ずれとなってしまうのです。
解決策① width, heightを指定する
解決策としては、<img>
タグに必ずwidth
、 height
を指定することです。
heightを書いておくことで、画像本来の高さが確保されるので位置ずれを防ぐことができます。
解決策② padding-bottomで高さを出す。
width
、height
を指定するのが正攻法だと思いますが、この方法では対応できないケースがあります。
特にvanilla-lazyloadなど、src
の代わりにdata-src
属性を使うものでは、残念ながら、width
、height
が効きません。
<!-- vanilla-lazyloadを使ったimgタグの記述例 -->
<div class="image-wrapper">
<img class="lazy image" alt="An image" data-src="lazy.jpg" />
</div>
srcの代わりにdata-srcを使っているのがわかります。
data-src
属性を使うケースではheight
の代わりにpadding-bottom
で高さを確保します。
<div class="image-wrapper">
<img class="lazy image" alt="An image" data-src="lazy.jpg" />
</div>
HTMLは変わりません。img
タグをdiv
タグなどで囲っておく必要があります。(cssの取り回しやすさの観点から常に何かしらのタグで囲っている人は多いかと思います。)
.image-wrapper {
width: 100%;
height: 0;
padding-bottom: 150%;
/* 👆 image height / width * 100% */
position: relative;
}
.image {
width: 100%;
height: auto;
position: absolute;
}
続いてcssです。
.image-wrapper
の方でheight: 0とした上で、画像の比率をpadding-bottom
で計算しています。
150%の部分は各画像の比率を計算して置き換えてください。
このやり方は、vanilla-lazyload公式のgithubに記載があります。
.image
の方ですが、reset.cssの方でキチンとresetしていればこの記述は不要です。
下記のような感じ
// reset.css
img {
height: auto;
max-width: 100%;
vertical-align: bottom; // baseline以外を指定
}
// style.css
.image-wrapper {
width: 100%;
height: 0;
padding-bottom: 150%;
/* 👆 image height / width * 100% */
}
.imageの記述はなくなりました。
これで、data-src
を使ったとしても、高さを確保することができます。
画像ごとに全て書かないといけないのか…。
残念ながらそうです。各画像ごとに画像比率は違うでしょうから、共通化できる部分はありつつも、padding-bottom
は各画像ごとに指定が必要です。
ただ、色々試した結果、こちらの方法が一番確実だったので是非試してみてください!