トップページの記事一覧でアイキャッチ画像に文字を重ねて表示させる、ようなことを作っていました。
これで、試しに低回線の環境でページを表示させたら、画像が読み込むまでテキスト同士が重なってしまいます。
回線が速いと一瞬なので気になりません。
恐らく、画像読み込み時にピクセルサイズなどの情報も読み込んでて、それが完了するのに時間がかかってるではと思います。
画像が読み込み中になると画像サイズの枠が確保されます。テキストは重なりません。
画像の読み込みが完了すると、画像にテキストが重なって表示されます。
imgタグに「width」や「height」を指定すると画像のピクセルサイズの情報を読み込む前に枠が確保されてテキストは重なりません。
一見、解決したように思いますが、レスポンシブに対応しておらず画面の小さいスマートフォンで見ると表示がおかしくなります。
CSSで画像をレスポンシブにしていると、画像を読み込むと縦長に表示される。2列表示してるので「320×240」の画像が「160×240」で表示されるみたいな。
なので、透明の画像を用意して重ねるようにします。透過画像は容量を極力小さくすることで、テキストが重なる時間が少なくなると思います。
JavaScriptで画面幅からimgタグの「width」や「height」の数字を書き換えることも出来そうなんですが、なんせ方法が分かりません。
2枚の画像を使うのでやっつけ感がありますが、今の自分の技量だとこれが手っ取り早いです。
備忘録です。目的の動作になったやり方を書いているだけで、他にもっといいやり方があると思います(方法までは分かりかねますが)。
Chromeのデベロッパーツールで疑似的に低回線の環境にする
サイトが、低回線だとどのように表示されるのかが分からないと対処できません。
回線の遅い環境は、Chromeのデベロッパーツールで疑似的に再現が出来ます。
Network conditionsタブの項目を「Slow 3G」にすると低速回線が再現できます。
これで、遅い回線だとどのように表示されるかが分かります。
解像度の小さい透明な画像を用意
グラフィックソフトで透過PNGを作ります。透過PNG作成できれば何のソフトでもいいです。
作成する透過PNGは重ねる画像のアスペクト比と同じ解像度にします。
「320×240、640×480、1280×960」などは4:3は、「4×3」ピクセルで作成。
「640×360」、「1280×720」、「1920×1080」などの16:9は、「16×9」ピクセルで作成。
PaintShopProXIで4×3ピクセルの透過PNGを作成したら容量は約150バイトになりました。1KBの1/6以下なので無視できる容量かと思います。
透過PNGは必要最低の解像度で作成て、CSSで拡大表示させます。写真やイラストと違い1色(透過)だけなので、引き伸ばしても表示に荒れることはありません。
HTMLとCSS
HTML基本型
<ul class="page_list">
<li class="list">
<a href="/page01.html">
<img src="./page01-eyecatch.jpg" alt="タイトル1" loading="lazy" >
<div class="caption"><p>タイトル1</p></div>
</a>
</li>
<li class="list">
<a href="/page01.html">
<img src="./page02-eyecatch.jpg" alt="タイトル2" loading="lazy" >
<div class="caption"><p>タイトル2</p></div>
</a>
</li>
<li class="list">
<a href="/page01.html">
<img src="./page03-eyecatch.jpg" alt="タイトル3" loading="lazy" >
<div class="caption"><p>タイトル3</p></div>
</a>
</li>
<li class="list">
<a href="/page01.html">
<img src="./page04-eyecatch.jpg" alt="タイトル4" loading="lazy" >
<div class="caption"><p>タイトル4</p></div>
</a>
</li>
</ul>
CSS基本型
ul.page_list{
flex-wrap:wrap;
list-style: none;
display: flex;
padding: 0;
}
li.list{
position: relative;
padding: 0;
width: 48%; /* ボーダーラインの影響で2列表示は50%未満にする */
height: 20%;
border: solid 1px #444; /* 外枠 */
}
li.list .caption{
position: absolute;
width: 100%;
bottom: 0;
color: #fff;
background-color: rgba(0, 0, 0, 0.6);
}
li.list .caption p{
margin:16px;
}
li.list:hover{
opacity: 0.6;
}
li.list img{ /* 画像をレスポンシブで表示 */
width: 100%;
display: block;
margin: 0;
}
メインカラムをレスポンシブにするなどは省いてます。
それぞれの画像にリンクを貼っていて、カーソルを画像に重ねると白く変わります。
ただ、最初に説明した通り回線が遅い環境だと画像の情報を読み込むまではテキストが重なって表示されてしまいます。
なので、透過PNGを重ねます。
HTMLの修正部分
<li class="list">
<a href="/page01.html">
<img src="./eyecatch-space.png" alt="" loading="lazy" class="img0">
<img src="./page01-eyecatch.jpg" alt="タイトル1" loading="lazy" class="img1">
<div class="caption"><p>タイトル1</p></div>
</a>
</li>
透過PNGの画像のタグを追記します。imgタグのクラスに透過PNGに「img0」、アイキャッチ画像に「img1」を追加。クラス名は適当。
<img src="./eyecatch-space.png" alt="" class="img0">
透過だと見えないので、黄色にしています。
CSSは手を加えてないので、透過PNGの下にアイキャッチ画像が表示されます。これに、CSSでアイキャッチ画像を透過PNGに重ねるようにします。
CSSの追加部分
li.list img.img0{ /* なくてもいいかも */
position: relative;
}
li.list img.img1{ /* アイキャッチ画像を重ねる */
position: absolute; /* 親要素の絶対位置にする */
top: 0; /* top=0、left=0で親要素の左上 */
left: 0;
}
ページ読み込むときに一瞬テキスト同士で重なりますが、前より速くなってます。
同じことを透過PNGで表示確認。画像を差し替えただけなので「黄色」の時と動作は同じです。
全体のコード
HTML
<ul class="page_list">
<li class="list">
<a href="/page01.html">
<img src="./eyecatch-space.png" alt="" loading="lazy" class="img0">
<img src="./page01-eyecatch.jpg" alt="タイトル1" loading="lazy" class="img1">
<div class="caption"><p>タイトル1</p></div>
</a>
</li>
<li class="list">
<a href="/page02.html">
<img src="./eyecatch-space.png" alt="" loading="lazy" class="img0">
<img src="./page02-eyecatch.jpg" alt="タイトル2" loading="lazy" class="img1">
<div class="caption"><p>タイトル2</p></div>
</a>
</li>
<li class="list">
<a href="/page03.html">
<img src="./eyecatch-space.png" alt="" loading="lazy" class="img0">
<img src="./page03-eyecatch.jpg" alt="タイトル3" loading="lazy" class="img1">
<div class="caption"><p>タイトル3</p></div>
</a>
</li>
<li class="list">
<a href="/page04.html">
<img src="./eyecatch-space.png" alt="" loading="lazy" class="img0">
<img src="./page04-eyecatch.jpg" alt="タイトル4" loading="lazy" class="img1">
<div class="caption"><p>タイトル4</p></div>
</a>
</li>
</ul>
CSS
ul.page_list{
flex-wrap:wrap;
list-style: none;
display: flex;
padding: 0;
}
li.list{
position: relative;
padding: 0;
width: 48%;
height: 20%;
border: solid 1px #444;
}
li.list .caption{
position: absolute;
width: 100%;
bottom: 0;
color: #fff;
background-color: rgba(0, 0, 0, 0.6);
}
li.list .caption p{
margin:16px;
}
li.list:hover{
opacity: 0.6;
}
li.list img{
width: 100%;
display: block;
margin: 0;
}
li.list img.img0{ /* なくてもいいかも */
position: relative;
}
li.list img.img1{ /* アイキャッチ画像を重ねる */
position: absolute; /* 親要素の絶対位置にする */
top: 0; /* top=0、left=0で親要素の左上 */
left: 0;
}
ページ表示を比較
事前に透過PNG読み込み「なし」と「あり」でページの表示を比較しました。
アイキャッチ画像は240pxx180pxの4枚。通信速度はChromeのデベロッパーツールでSlow 3Gにして、Chromeの更新ボタンでリロード。キャッシュはクリア済み。
事前に透過PNG読み込んでいても、一瞬テキストが重なりますが画像の外枠(border)が表示されるのは速いです。
透過PNGの読み込みは1回。アイキャッチ画像の枚数が増えると効果が表れやすいかなと思います。
透過PNGを実装したサイトの動作がこちらです。
WordPressを利用しないでHTML(主にPHP)だけで作っていた手打ちのサイトです。
ただ、もっといい方法があると思うのでやっつけ感が出てます。(いい方法もありそうな気がするだけで知識が足りず思いつかないですが)