アバターの画像

@kou_hey3

最終更新日:

ポスト

ブログのデザインリプレイスを通してデザインシステムを学んだ

当ブログの作成時は、デザインについての知見が浅く、なかなかに酷いデザインでした。。
今回ブログのデザインをリプレイスする際に取り組んだこと、考慮したことをまとめておきます。

はじめに

本記事では、サイトのデザインを見直すためにデザインシステムを構築し、その際に考慮した点をメインに記載します。
Web フロントエンドディベロッパーの目線で記載しています。

デザインを学ぶ

まずは最低限デザインについての知識をつけておく必要がありました。
Design Systems ―デジタルプロダクトのためのデザインシステム実践ガイド をベースにデザインシステムについて学びました。

デザインも保守のしやすさが必要。デザイントークンの定義から、デザインシステムを整備しておくことでデザイン及びコードの保守のしやすさ、サイトの拡張のしやすさが得られるのだなと。

一番意識しておくことはデザイントークン・デザインコンポーネントをコードと同期しやすくしておくことが大事そうだなと思いました。

今回は Figma を使い、実際にデザイントークンの定義から、それを React のコードとして実際にサイトに適用するまでの一連を行いました。

デザインシステムを用意する

Figma を使ってデザインシステムを用意します。

デザイントークンを定義する

まずは全てのベースとなるデザイントークンを定義します。
色や余白、フォントやシャドウなど、以降はここで定義したデザイントークンを使用していくことで一貫性を担保します。

デザイントークンは Figma Tokens を使用して定義しました。
今回は使っていないですが、 Figma Tokens で定義したトークンは json としてエクスポートできるため、 git 管理もしやすいです。
git で管理されたデザイントークンを取得し、プロダクトコードのデザイントークン定義に同期を行うなどもできそうです。

今回は以下のトークンを定義しておきました。

  • Sizing
  • Spacing
  • Color
  • Border Radius
  • Border Width
  • Opacity
  • Box Shadow
  • Typography
  • Font Family
  • Font Size
  • Line Height
  • Letter Spacing
  • Z-index
  • Break Point
  • Transition

がっつりですね。

SizingColor には Numerical なインデックスでトークン名を付けておくと良さそうです。
x や small, main や sub などの名前は、保守性の悪さや値の想像のしづらさがあるためです。
逆に、 Z-index などには用途に合わせた命名をしておくと良さそうだと思います。(例: spinner , modal

Color に関しては、ダークテーマ対応も意識して定義しました。
Color はコントラスト比を意識して定義を行います。
コントラスト比に関しては WCAG 規格に沿っておくと良いです。

今回は static color , light color , dark color のカラーパレットを定義しました。
static color はすべてのテーマで一貫した値を持ちます。テーマの背景色とのコントラストに基づかず、色の色相の認識可能性を優先したい場合に使用します。
light color はインデックスが高くなるごとに暗く、 dark color はインデックスが高くなるごとに明るくなります。

デザインコンポーネントを定義する

デザインコンポーネントは、 React コンポーネントと密な関わりがあります。
再利用性や凝集度を意識してデザインコンポーネントを定義しておくと、デザイン及び React コードの保守性がグンと上がります。

Figma に Components ページを作成し、作成したコンポーネントを Create Component してコンポーネント化し命名していきます。
基本的に、このコンポーネント化されたものをそのまま React コンポーネントとして実装します。

レスポンシブを意識する

大体はデスクトップサイズとモバイルサイズを定義しますが、実際には定義されたサイズ以外の view サイズで見られることがあり、実装時にどういう挙動をするようにしておくべきなのか迷うことがあります。
Figma にはコンテンツのサイズを Fixed width , Hug content , Fill container で指定できるので、それらをレスポンシブを意識して設定しておくことで、実装時の迷いがなくなります。

例えば、どこの文字が折り返されるかとか...

インタラクティブな要素はその状態も定義しておく

他にも実装時に迷いが発生する点として、インタラクティブな要素の各状態の見た目はどうなるかがあると思います。
こちらもデザイン側で予め定義しておくことで実装がしやすくなります。

大体はデザイントークンで定義された色のインデックスをいくつずらすとかだと思います。

この辺り、 Figma では定義の面倒臭さがあったのですが、こうすると良いみたいなのがあったら知りたい...

ページ単位のデザインを定義する

定義したデザインコンポーネントをレイアウトに当てはめてページのデザインを定義します。

Figma に Pages ページを作成し、フレームを使ってページデザインを作成していきます。
フレームで作成することによって、 Present でプロトタイプチェックができます。

配置するコンポーネントは、デザインコンポーネントで作成したコンポーネントのインスタンスを使っていきます。
こうすることで、コンポーネント側を修正した場合にインスタンス側も修正が反映されるため、手間が省けます。

ページレイアウトを定義する場合も Figma の Constraints 機能を使うことで、 flex な要素の動きがわかりやすくなり、実装時の迷いを軽減できます。

コードに落とし込む

Figma でデザインの定義が終わったら、実際にコードに落とし込んでいきます。

デザイントークンをコードにも定義する

当ブログでは CSS Modules を使っているため、 global な variables としてデザイントークンを定義していきました。
リプレイス前は CSS in JS を使っていたのですが、なんだかんだ CSS Modules に乗り換えました。なんだかんだ CSS Modules は良いぞ!って話、機会があったら記事にします。

変数名はトークン名と合わせておくとデザインシステムとして機能しやすいです。

/* global.css */

:root {
  --global-static-color-black: #000;
  # ...
}

コンポーネント側で var(--global-static-color-black) のように使っていきます。

テーマ毎の変数はテーマ毎の data 属性を用意するか、 prefers-color-scheme を使うかにもよりますが、どちらの場合でも --theme-hoge みたいな変数名で合わせておきます。

/* global.css */

:root[data-theme='light'] {
  color-scheme: light;

  --global-theme-color-blue-400: #2680eb;
}

:root[data-theme='dark'] {
  color-scheme: dark;

  --global-theme-color-blue-400: #1473e6;
}

こうすることで、 var(--global-theme-color-blue-400) としているスタイルがテーマによって切り替わります。

デザインコンポーネントを React コンポーネントで実装する

Figma 側でかっちり定義しておけば迷うことはほとんど無いと思います。

動的な値を Props として定義し、デザインに合わせてスタイルを適用するのみでした。

デザインコンポーネントに合わせて、 shared なコンポーネントなのか internal なコンポーネントなのかを意識し、ディレクトリ構造を用意します。

その他リファクタリング

デザインリプレイスのタイミングで、コードの保守面も見直しました。

不要な機能を削除する

ブログ作成時、「とりあえず機能つけておけ!」と無意味に機能を実装していました。当時は Next.js を学ぶ意味も持たせてしまっていたので、結果不要な機能を持つことになり、保守もし辛い状態でした。。

用途に合わせて不要な機能を削ることで、無駄にコードの保守をすることもなくなります。
この辺りの判断は Google Analytics などを使って長い目で見ていくと良さそうです。

主に削除した機能は以下です。

  • 記事毎に画像を設定
  • 前の記事、次の記事のリンク

記事毎に画像を設定し、記事一覧及び記事のトップでの画像表示、 OGP での使用をしていたのですが、記事を書くたびに画像を用意する必要があり、記事を書くのが億劫になっていました。これでは本末転倒です。
OGP に関しては記事を基に自動生成する仕組みを用意しました。こちらに関しては章を分けて記載しておきます。

また、前後記事へのリンクを貼っていたのですが、特定の記事を見ていただいてる際に「続けて前の記事読むか」とはならないだろうなと思い、機能を削りました。
ブログ全体でジャンルが統一されている場合や、日記のような内容の場合は機能としてあってもよさそうですが、当ブログは記事毎に内容が全く違うので不要と判断しました。

その他にも、記事本文をメインとして記事一覧はシンプルなものにしたりと、「記事を書きやすい状態」、「目的にあった記事が見れれば良い状態」になるように意識しました。

アクセシビリティに考慮する

Color のコントラスト比もそうですが、マークアップでのアクセシビリティも見直しました。

デザイントークン、デザインコンポーネントをかっちり定義したことにより、 React コンポーネント実装時に ARIA などの考慮に集中することができるようになりました。
これはかなりのメリットかなと思います。

ランドマーク、 sectionarticle などのコンポーネント分割や、 ARIA 属性の指定など意識が漏れやすい部分なのですが、コンポーネントのインターフェースやインタラクティブな状態を脳死で書けるので意識が漏れることもなく、逆にその点に集中して実装を行うことができます。

OGP 画像を自動生成する

記事毎に画像を用意する手間は無くしたのですが、 OGP 画像をどうしようか迷いました。
特にこだわりは無かったので、記事タイトルと投稿日、サイト名がわかる画像を自走生成して設定すれば良いかとなり、その仕組みを導入しました。

画像生成には Playwright を使っています。
React コンポーネントで OGP 画像のベースを作成し、そこに動的データを埋め込んだコンポーネントをレンダリングしてスクリーンショットを撮っています。
この処理を行う関数を Vercel の Serverless functions にデプロイし、その API route を og:image に設定しています。

まとめ

Figma を用いてデザインシステムの構築を行ったことにより、デザイン周りの知見を蓄えることができました。
今回の経験で、デザイナーさんとのやり取りもしやすくなった気がしたので良い経験になりました。
デザインシステムを構築する場合には、開発者側もある程度のデザインの知見、及びデザインツールの知見を付けておくことは大事だなと気付きがありました。

まだまだ直す場所もあるのですが、徐々に直していこうかなと思います。

記事を書く障壁も下がったので、サボっていたアウトプットも今後ちゃんとやっていこうと思います...!

記事一覧に戻る