株式会社クイックのWebサービス開発blog

HAPPYなサービスプランナー・エンジニア・デザイナーのブログです。

サイズを固定できないVueコンポーネントのCLS対策はslotを使うとなんかいい感じ

こんにちは!
来月でクイックに入社して2年になりますソフトウェアエンジニアのponです!
昨年から話題だったCore Web Vitalsがついに先日のコア アップデートで追加されましたね。
クイックでもUX向上とSEO改善のためコアウェブバイタルの指標は注視しており、特にCLS(Cumulative Layout Shift)は私の担当しているサイトでスコア100点をキープしています(どやぁ)
今日はCLS対策で実施したことを書いていこうかなと思います!

CLS(Cumulative Layout Shift)とは?

ページがどのくらい安定しているように感じられるかを表します。視覚的な安定性を測定し、表示されるページ コンテンツにおける予期しないレイアウトのずれの量を定量化します。
https://developers-jp.googleblog.com/2020/05/web-vitals.html

直訳すると「累積レイアウトシフト」になりますが、ユーザーが予期しないレイアウトのずれを定量化したものになります。
レイアウトシフトについてはweb.devの記事にあるムービーが大変わかりやすいです。 web.dev

レイアウトシフトが起こる主な要因として、

  • 画像
  • 広告
  • webフォント
  • 動的コンテンツ

などが挙げられます。

基本的には事前にコンテンツ分のサイズを設定しておくだけで対応できますが、文字数などによってコンテンツの高さが変動したり、事前にサイズを指定できないことって結構ありますよね。
私の所属しているプロジェクトではVueを採用しており、部分的にVueコンポーネントを使用するとどうしても通信速度やCPUが低い端末だとレンダリング遅延によりCLS(Cumulative Layout Shift)が発生してしまいがちです。

そこでサイズを固定できないVueコンポーネントでCLS対応する方法を1つ紹介したいと思います!

完成形はこちら

ファーストビューにVueコンポーネントで作成したリンクリストを挿入しています。

See the Pen cls-with-vue by kaaaaeeee (@kaaaaeeee) on CodePen.

 

CodePen上だとわかりづらいですが通信速度が低い回線等で表示させると以下のようになります。
必要分だけ高さが保持されるようになっていて、DOMが生成されるまでローディングアニメーションを表示させています。

f:id:aimstogeek:20210806084125g:plain

実装方法

名前付きスロットを使用して、表示するコンテンツを渡します。
スロット名のないものはコンポーネントのDOM生成後破棄されるため、コンポーネントレンダリングが完了するまで表示させたいもの(ローディングなど)を追加することができます。

スロット — Vue.js

<link-list data-cls="link-list">
    <div slot="link1">テキスト</div>
    <div slot="link2">長文のテキスト長文のテキスト長文のテキスト長文のテキスト</div>
    <!-- 以下はslot名を記載していないためDOM生成後破棄される -->
    <div class="loading"><svg class="loader" viewBox="0 0 32 32" width="32" height="32"><circle id="spinner" cx="16" cy="16" r="14" fill="none"></circle></svg></div>
</link-list>
<template>
  <div class="link-list">
    <ul>
      <li><a href="dummy1"><slot name="link1" /></a></li>
      <li><a href="dummy2"><slot name="link2" /></a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'LinkList',
};
</script>

スロットを使用することでコンポーネントレンダリング前は以下のようにテキストとローディングアニメーションが表示されている状態になります。

f:id:aimstogeek:20210805230457p:plain

コンポーネントのDOMが生成される前に当てたいスタイルを指定します。
slot="link1"やslot="link2"はDOM生成後消えるため、レンダリング前に当てたいスタイルは属性に対して指定します。

[data-cls="link-list"] {
  position: relative;
  display: block;
  
  /* この属性名はDOM生成後消えるため、レンダリング前に当てたいスタイルを指定できる */
  [slot="link1"],
  [slot="link2"] {
    padding: 1rem 2rem 1rem 1rem;
    border: 1px solid var(--color-border);
    font-size: 1.4rem;
    
    &:not(:first-child) {
      margin-top: -1px;
    }
  }
}

以上でCLS対応は完了です ٩( ᐛ )( ᐖ )۶

まとめ

VueコンポーネントでのCLS対応をご紹介しました。

普段自分でwebサービスを利用していてもレイアウトシフトが起きたり、読み込みが遅いとストレスに感じるので
対応する側としては大変ですが、コアウェブバイタルめちゃくちゃ大事だなと思っています。 今後もユーザーにストレスのスの字もを感じさせない、より高いユーザー体験を提供できるよう頑張ります٩(๑❛ᴗ❛๑)۶


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp