うちの一部記事では Twenty20 Image Before-After を利用してます。
このプラグインは、以下の記事にあるとおり画像のビフォーアフターを表示させることができます。
😒 不具合
しかし読み込みのタイミングで画像の高さがうまく取得できないケースがあります。
画像2枚分の高さになるケース
どうやらビフォーの画像とアフターの画像が縦に並んで、それを画像全体の高さだと誤認しているのだと思います。
そもそも画像が出ないケース
テキストとテキストの間に本来は表示されるんですけど、なぜか表示されません。これは画像が遅延して読み込まれているため、Twenty20が動いたときに画像が存在しないと誤認しているのだと思います。
原因は?
正常に表示されないときのHTMLと、正常なときのHTMLを見比べてみると前述のとおり、やはり「画像の高さ」を勘違いしてしまってるようです。以下の例だと本来392px
になるべき箇所が0px
となって、表示されなかったようですね。
<div
class="twentytwenty-container twenty20-3"
style="height: 0px;"
>
<img
decoding="async"
src="https://.../PNG.png"
data-src="https://.../PNG.png"
class=" twentytwenty-before lazyloaded"
style="clip: rect(0px, 392px, 0px, 0px);"
>
<div
class="twentytwenty-container twenty20-3"
style="height: 392px;"
>
<img
decoding="async"
src="https://.../PNG.png"
data-src="https://.../PNG.png"
class=" twentytwenty-before lazyloaded"
style="clip: rect(0px, 392px, 392px, 0px);"
>
🥳 解決策は?
一番簡単な方法は、カスタムJSを記事に埋め込んであげる方法です。
Twenty20 はリサイズのイベントが発火する度に動くようです。つまり、画像を読み込んだらリサイズのイベントを発火させれば Twenty20 が正常に表示される、という目論見です。
解決したコード
遅延して読み込まれる画像の一覧を取得し、それらが Twenty20 のclassName
を持っているか確認。持っているならばリサイズのイベントを発火させ Twenty20 を正常化するコードを作れば解決です!
document.querySelectorAll('img[decoding="async"]').forEach(img => {
img.onload = _ => /twentytwenty/.test(img.className) && jQuery(window).trigger('resize')
})
余談
document.querySelectorAll('img[decoding="async"][class*="twentytwenty"]').forEach(img => {
でいけるんじゃない?と思った方。うちもそうです。しかしclassName
は後から付与されるっぽいので取得できなかったんですよね。なので画像が読み込まれた後にclassName
が一致するか確認をしてresize
をしてます。