クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

Vue.js で作る GridSystem

Vue.js で作る GridSystem OGP 画像

こんにちは、crowdworks.jp でエンジニアをしている @t0yohei です。最近はデザインシステム構築の一貫でコンポーネントライブラリの実装を行なっています。

今回は Vue.js を使って GridSystem を作るにはどうしたらいいか、どういうことを考える必要があるのかをお伝えしていこうと思います。

※ このブログは、 Vue Fes Japan 2023 のセッション「Vueを使ってGrid Systemを実装した話 」の内容を補足するブログになっています。セッションをご覧になっていない方が読んでも問題ない形式になっておりますのでご安心ください。

目次

そもそも GridSystem って?

GridSystem は 1981 年に刊行された、ヨゼフ・ミューラー゠ブロックマンの主著『Grid systems in graphic design』にて体系化された概念で、具体的には

グリッドシステムとは、画面上に架空の縦横線をガイドラインとして引きブロックごとに文字や図版を配置することでデザインのシンプルな美しさを引き出す手法

とされています。

参考: グリッドシステム グラフィックデザインのために

元々がデザインの手法であるため、実装として扱う GridSystem はこの定義に実装としての制約を加える必要があります。

実装として扱う GridSystem について明確な定義が見つからなかったため、今回は GridSystem 実装の走りと言える Bootstrap での定義を元に実装を進めていこうと思います。

グリッドシステムは、12カラムのシステムと5段階のレスポンシブ、Sassとmixin、いくつかの定義されたクラスですべての図形とサイズのレイアウトを作成可能です。

.

グリッドシステムは、一連のコンテナ、行、列を使用してコンテンツをレイアウトし、整列させます。

参考: グリッドシステム · Bootstrap v5.3

大まかにまとめると Bootstrap 風な GridSystem には以下のような機能が求められると言えそうです。

  • N 個(ex. 12 個)のカラムで画面を分割できる
  • カラム数の指定で、縦・横のコンテンツレイアウトを制御できる
  • M 段階(ex. 5 段階)のレスポンシブな画面にできる

*1

今回は、この要件を実現する Bootstrap 風の GridSystem を作る方法について言及していきます。 また今後 GridSystem と言う際は、この Bootstrap 風の GridSystem のことを指すことにします。

【コラム】GridSystem はなぜ必要?

そもそも GridSystem はなぜ必要なのでしょうか。GridSystem が必要とされる要因は以下のようなものが考えられます。

  • 格子状にデザインされた画面を効率よく作りたい
  • CSS Grid や Flexbox を使えば実現できるけど、画面全体やサービス全体で統一感を持たせたい

逆に以上の要望がない場合は、GridSystem を自ら実装したり GridSystem を使うためだけに UI ライブラリを導入するなどは必要ないかもしれません。

【コラム】GridSystem はいつ作ることになるか

UI ライブラリなどに既に実装されている GridSystem を使うことは数あれど、GridSystem を自ら作る機会はあまりないかもしれません。では一体いつ自身で作ることになるのでしょうか。 主だったタイミングとしては、

  • Web サービスを作る上での開発方針で、UI コンポーネントライブラリを自作しようとなった時
  • OSS などで UI コンポーネントライブラリを作ろうとした時
  • GridSystem を自分で作ってみたいなーと思った時

などが思い浮かびます。 そういった機会の多寡は読み手の皆さんに任せるとして、この記事は実際に GridSystem を作ることになった方に、少しでも自分の知見を共有できればと思い書いてみました。

決める必要があること

さて、若干話が逸れた気がしますが、具体的に GridSystem を作るために必要なことの話に入って行きます。

GridSystem を作るには、まず基本的なこととして以下の内容を決める必要があります。

  • 対応する画面サイズは何パターンにするか
    • Pc(lg), Tablet(md), Sp(sm) など
  • それぞれの画面サイズは、何 px 〜 何 px までを割り当てるか
    • つまり画面サイズの境界値(breakpoint)を何 px にするか
  • 一列の総カラム数は何カラムにするか
    • 画面サイズごとに総カラム数を変えるか、統一するか

また、応用的な内容として以下のようなことも検討する必要があります

  • カラム間に間隔(Gutter)を設けるか
    • 設ける場合は何 px にするか
    • 縦・横でカラム間の間隔を別にするか、統一するか
  • GridSystem を適用するエリア(body)に最大幅を設けるか
    • また、エリア(body)外との Margin は何 px にするか
  • どういったオプションを用意するか
    • Order: カラムの順番を入れ替えるためのオプション
    • Offset(Start): カラムの開始位置を指定できるようにするためのオプション
    • etc...

決めることが多いですが、自分(達)が必要とする GridSystem はどういうものかを調査・議論しながら定義していきます。

参考までに、crowdworks.jp の GridSystem において、実際に決めた内容は以下のようなものになります(まだまだ発展中のため、後から変更になる場合もあります)。

GridSystem の要件まとめテーブル
GridSystem の要件まとめテーブル

GridSystem のイメージ図
GridSystem のイメージ図

また、GridSystem の検討にあたっては実際に運用されている GridSystem を調査してみることも重要になるため、私達が参考にさせてもらった GridSystem いくつかを紹介させて頂きます。

実装パターン

GridSystem の実装には大きく以下の 3 つの実装パターンがあります。

  • float を使う方法
  • Flexbox を使う方法
  • CSS Grid を使う方法

歴史的には float を使う方法が一番古く、次に FlexBox を使う方法、CSS Grid を使う方法と並んできます。

Bootstrap では、3 系までは float を使う方法で、4 系からは Flexbox を使う方法、5 系からは CSS Grid を使う方法が登場して来ます(5 系では Flexbox を使う方法、CSS Grid を使う方法の両方が提供されています)。 Bootstrap の進化はやっぱりすごいですね。

Bootstrap 風の GridSystem を作るのであれば、Flexbox を使う方法で十分なのですが、今回はせっかくなので CSS Grid を使う方法で GridSystem を作っていきます。

実装方法

実装方法については、下記スライドにて画面の表示を交えながら紹介を行ないました。 ここで紹介している GridSystem に肉付けを行なっていくことで、運用可能な GridSystem を作ることができると思います。 speakerdeck.com

実装 Tips

時間の都合上、スライドに記載できなかった実装 Tips をいくつかご紹介します。

GridLayoutFrame コンポーネント

GridSystem を適用するエリア(body)の最大幅と、エリア(body)外との margin を設定するための Layout コンポーネントです。 実装は以下のようなイメージになります。

<template>
  <div class="grid-layout-frame">
    <slot />
  </div>
</template>

<style scoped>
.grid-layout-frame {
  max-width: 1200px;
  margin-right: auto;
  margin-left: auto;
}

@media screen and (width <= 1279px) {
  .grid-layout-frame {
    max-width: 575px;
    margin-right: auto;
    margin-left: auto;
  }
}

@media screen and (width <= 607px) {
  .grid-layout-frame {
    margin-right: 16px;
    margin-left: 16px;
  }
}
</style>

index.ts での import and export

例えば、components/layouts/grid_system にて GridSystem 関連のコンポーネントを実装している場合、 components/layouts/grid_system/index.ts を作成し以下のように実装することで、実際に使う際の import が簡潔になります。

import GridColumn from './GridColumn.vue';
import GridLayout from './GridLayout.vue';
import GridLayoutFrame from './GridLayoutFrame.vue';

export { GridColumn, GridLayout, GridLayoutFrame };

JS のライブラリなどでよく使われているやり方ですね。

最終的な実装イメージ

GridSystem を適用する画面で一般的に行う実装は次のようになります。

<script>
import { GridLayoutFrame, GridLayout, GridColumn } from '@/components/layouts/grid_system';
</script>

<template>
  <GridLayoutFrame>
    <GridLayout>
      <GridColumn :pc="12" :tbl="12" :sp="12">
        グリッド全体にまたがる要素
      </GridColumn>
    </GridLayout>

    <GridLayout>
      <GridColumn :pc="3" :tbl="12" :sp="12">
        サイドバー
      </GridColumn>

      <GridColumn :pc="9" :tbl="12" :sp="12">
        メインコンテンツ
      </GridColumn>
    </GridLayout>
  </GridLayoutFrame>
</template>

簡潔で良い感じですね?

終わりに

GridSystem は CSS Grid の登場や、Subgrid が遂に全メジャーブラウザに実装されたことにより、更なる進化を遂げる予感がしています。 Bootstrap 風の GridSystem は歴史的な経緯により、縦の画面割をベースとした GridSystem になっており、CSS Grid などが提供する縦横に柔軟な画面配置とはまた違ったものになっています。

こういった経緯もあり、どのような GridSystem が主流となっていくか今後も楽しみですね。

それでは、以上でこの記事を締めさせていただければと思います。最後まで読んで頂きありがとうございました。

*1:あくまで Bootstrap 風な GridSystem を実装する際に求められる要件です。元の GridSystem の定義を別の解釈で実装に落とし込む場合は、別の機能要件になります。

© 2016 CrowdWorks, Inc., All rights reserved.