CSSのcontent-visibilityプロパティでコンテンツの遅延読み込み


遅延読み込みについては、Lazy loadingはよく聞くかと思います。
img要素やiframe要素では「loading=”lazy”」と、loading属性を付けることで対応できます。

Google Chromeのバージョン85以降からは、content-visibilityプロパティが実装できるようになり、表示(レンダリング)を遅延させることができます。

loading属性はimg要素やiframe要素に対応、Lazy loadingはJavaScriptを併用する流れですが、content-visibilityは手軽に、コンテンツに適応させることができます。

content-visibilityプロパティの値

visible
既定値。要素のコンテンツは通常どおりにレンダリングされる。

hidden
要素の内容の描画をスキップする(display:none;をコンテンツに与えるのと似ている)

auto
要素のレイアウト・スタイル・塗りの封じ込めをオンにする。要素がユーザーに関連していない場合はスキップする(ビューポート外などの可視範囲意外の領域)



content-visibilityに「auto」を指定することで、ユーザーに関連していない場合(ビューポート外)は描画をスキップします。
また、一緒にcontain-intrinsic-sizeプロパティを使って、描画する予定の高さを指定します。

気になるWebブラウザの対応状況です。

Can I use(content-visibility)
https://caniuse.com/?search=content-visibility

2021年1月現在、主要ブラウザではChromeとEdgeが対応しています。

では、実際の使い方をいくつかのサンプルでご紹介します。


content-visibilityの使い方


Webページのコンテンツで、一つ一つのセクションを可視範囲の領域に入ったら描画するよう、簡単なHTML構造を用意しました。

以下、サンプルになります。

HTML

<h1>content-visibility</h1>
<div id="sample-block">
  <h2>Section01</h2>
  <section class="sample-section">
    <div>
      <h3>Headline</h3>
      <img width="1000" height="667" src="images/sample-01.jpg" alt="">
    </p>
  </section>

  <h2>Section02</h2>
  <section class="sample-section">
    <div>
      <h3>Headline</h3>
      <img width="1000" height="667" src="images/sample-02.jpg" alt="">
    </div>
  </section>
</div>


CSS

h1 {
  text-align: center;
  padding: 1em 0;
  background: #bec9ff;
}

#sample-block {
  width: 92%;
  max-width: 1000px;
  margin: 2em auto;
}

.sample-section {
  width: 100%;
  max-width: 1000px;
  margin: 1em auto;
  background-color: #d6d6d6;
  content-visibility: auto;
  contain-intrinsic-size: 400px;
}

h2 {
  padding: 40px 0 0;
}

.sample-section > div {
  padding: 2em;
}

h3 {
  padding: 0 0 0.5em;
}

.sample-section img {
  padding: 0.5em 0 0;
}



「.sample-section」のコンテンツをごっそり、遅延読み込みさせています。
その対象の要素に対して、「content-visibility: auto;」と「contain-intrinsic-size: 400px;」を適応させています。
contain-intrinsic-sizeプロパティは、コンテンツ量に変化が出てきて高さが多少かわりますので、おおよその高さを指定すればOKです。

ちなみに「hidden」を指定するとどのようになるかというと、
コンテンツは非表示となります。
要素の高さは保持しておきたいのであれば、contain-intrinsic-sizeプロパティを指定します。

CSS

.sample-section {
  width: 100%;
  max-width: 1000px;
  margin: 1em auto;
  background-color: #d6d6d6;
  content-visibility: hidden;
  contain-intrinsic-size: 400px;
}
contain-intrinsic-sizeプロパティで描画する予定の高さを確保



contain-intrinsic-sizeの「400px」分の高さが保持されているのが確認できます。
レンダリングされれば、コンテンツが400px以上でも以下でも、コンテンツの高さで表示されます。

ですのでcontain-intrinsic-sizeは、アバウトな数値(表示されていない時に保持しておきたい高さ)を指定すればOKです。


デバイス幅でコンテンツを切り替える時にも


レスポンシブWebデザインでは、デバイス幅で表示するコンテンツを切り替えたり、別のコンテンツを表示させるといったことはよくあります。
いろんな方法がありますが、一番簡単なのが「display: none;」をうまく利用した方法でしょう。

コンテンツの切り替えも、今回ご紹介するcontent-visibilityが使えます。
「display: none;」の場合は、一度コンテンツを読み込んでから非表示にするのに対して、content-visibilityプロパティでは、「hidden」とすることで描画がスキップされますので、読み込まれない分、表示速度が上がります。

以下、サンプルになります。

HTML

<section class="sample-section">
  <div>
    <h3>Headline</h3>
    <p class="pc">PC :<br>Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. </p>
    <p class="sp">SP :<br>Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. </p>
    <img width="1000" height="667" src="images/sample-01.jpg" alt="">
  </p>
</section>


CSS

h1 {
  text-align: center;
  padding: 1em 0;
  background: #bec9ff;
}

#sample-block {
  width: 92%;
  max-width: 1000px;
  margin: 2em auto;
}

.sample-section {
  width: 100%;
  max-width: 1000px;
  margin: 1em auto;
  background-color: #d6d6d6;
  content-visibility: auto;
  contain-intrinsic-size: 400px;
}

h2 {
  padding: 40px 0 0;
}

.sample-section > div {
  padding: 2em;
}

h3 {
  padding: 0 0 0.5em;
}

.sample-section p {
  content-visibility: hidden;
}

.sample-section .sp {
  content-visibility: auto;
}

.sample-section img {
  padding: 0.5em 0 0;
}


/*------------------------------------------------------
 PC
------------------------------------------------------*/
@media screen and (min-width:920px) {

  .sample-section .pc {
    content-visibility: auto;
  }

  .sample-section .sp {
    content-visibility: hidden;
  }

}



CSSはモバイルファーストで書いています。
P要素は「content-visibility: hidden;」としておき、スマートフォンのコンテンツ「.sp」は遅延読み込みするように、そしてメディアクエリで、PCの幅の時は「.pc」を表示するように、「.sp」は非表示になるようにすれば、デバイス幅で表示したいコンテンツを切り替えることができます。

content-visibilityプロパティで表示を切り替える



ちなみに、コンテンツの切り替えでは、非表示にしている要素の高さを確保していると、その分の余白ができてしまいますので、contain-intrinsic-sizeプロパティは使わなくていいでしょう。
「display: none;」より「content-visibility: hidden;」の方が、表示速度を上げることができます。
早く多くのWebブラウザに対応してもらいたい。

少し注意点ですが、
display: none;もそうですが、常にコンテンツを非表示にして、検索エンジンにだけ見せるような悪質なコンテンツは、Googleのペナルティを受けることもあるので気をつけましょう。
デバイスのどちらかで非表示にするコンテンツがあるようなデザインも、これからはなるべく表示していくデザインを作っていくことを心がけましょう。


画像のみに対応する


画像を遅延読み込みする場合は、ファーストビューの表示領域はコンテンツが表示されない時間ができるのは好ましくないので、可視範囲意外の領域の要素に対応するようにしましょう。

画像のみにを遅延させる場合には、img要素の幅や高さの指定が影響してきます。
例えば、「loading=”lazy”」で遅延読み込みをする際には、画像の配置場所の確保の関係で、img要素の幅や高さの指定が必要になります(ファーストビューの表示領域は必ず)が、contain-intrinsic-sizeで高さを確保してもimg要素の属性の指定が優先されます。
幅と高さを指定しているとコントロールしずらいです。

HTML

<div class="photo">
  <img src="images/sample-01.jpg" alt="">
  <p>Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text..</p>
</div>
<div class="photo">
  <img src="images/sample-01.jpg" alt="">
  <p>Example text.. Example text.. Example text.. Example text.. Example text.. Example text.. Example text..</p>
</div>


CSS

.photo {
  width: 92%;
  max-width: 1000px;
  margin: 2em auto;
}

.photo img {
  content-visibility: auto;
  contain-intrinsic-size: 400px;
}



画像をギャラリーのように、複数載せているコンテンツで利用できるかと思います。


まとめ


img要素では、はじめにお話したように「loading=”lazy”」を指定して遅延読み込みができますが、「loading=”lazy”」と「content-visibility: auto;」を併用すると、「loading=”lazy”」が優先されます。

loading属性を使った方法は、以下の記事でご紹介しています。

↓ ↓ ↓

imgやiframeのlazy loading設定で画像や動画、SNSの埋め込みを遅延ロード

content-visibilityは「loading=”lazy”」のコンテンツ版という感じなので、img要素についてはloading属性で良いかと。
長いコンテンツのWebページでは、content-visibilityプロパティはとても効果的でしょう。

今後利用できそうなCSSプロパティとして、ぜひ覚えておいてください。