string(4) "blog"

CONTENTS

2020.10.29

デザインシステムのためのUIコンポーネント実装のコツ

written by 宮崎 聡史

Fixelはデザインシステムを作成・共有するプラットフォームである「UXHub」を用いて様々な業界のお客様の多数のデザインシステムを開発、提供してきました。
その中でデザインシステムに必要なUIコンポーネントの設計方法や実装方法についても試行錯誤を重ねながら研究をすすめてきました。今回はその知見から、WebアプリケーションにおけるUIコンポーネントの設計と実装方法の基本についてまとめてみたいと思います。

1. アトミックデザインを基本としたUIコンポーネント設計

デザインシステムにおけるUIコンポーネントはレゴブロックのようなものだと以前の記事で書きました。では、どのような種類のレゴブロックを作ればいいのかというのが、UIコンポーネント設計になります。

業務システムなどのWebアプリケーションの画面に配置されている、さまざまな部品をどのように分類して取り出し、整理するのか? その方法にはアトミックデザインの考え方がとても役立ちます。

アトミックデザインの詳しい内容については、この記事の最後に参考リンクを載せますが、概要としては以下のような内容になります。

Atoms

これ以上分割するとコンポーネントとしての機能が失われてしまうレベルの、UIコンポーネントの最小単位を指します。

例:ボタン、チェックボックス、ツールチップなど

Molecules

AtomsレベルのUIコンポーネントを複数組み合わせて作られたUIコンポーネントを指します。
Molecules同士の組み合わせも含みます。
ページ上の配置位置による意味を持たないUIコンポーネントです。

例:検索フォーム、モーダルダイアログ、プルダウンメニューなど

Organisms

Moleculesと同じく、Atoms、Moleculesを組み合わせて作られたUIコンポーネントです。
Organismsはページ上の配置位置によるコンテキストを持ちます。

例:ヘッダー、フッター、サイドメニューなど

Template

UIコンポーネントという部品を並べる、レイアウトのパターンです。

例:ログイン画面レイアウト、3カラムレイアウトなど

Page

AtomsからOrganisms、Templateを組み合わせて作られた、実際のアプリケーションのページです。

例:ログイン画面、情報一覧画面など

このような粒度でページを分割して分類していくと、ページ自体がどのような構造でできあがっているのかが整理されますし、同じUIコンポーネントを重複して実装してしまうようなことも防げます。

※ ただし、アトミックデザインの各レベルの名称をそのまま使うことは必須ではないと思います。実はアトミックデザインのレベルの名称はあまり慣れてない表現なので、各デザインシステムで分かりやすい名称に変えて使ったりしています。

2. シンプルなHTML設計

これは言うまでもないですが、デザインシステムにおけるUIコンポーネントに対してもHTMLを簡潔なものに維持するのは大事です。特に業務システムにおいては、複雑なデザインやリッチなアニメーションなどはほとんど必要ありません。ですので、UIコンポーネント実装でのHTMLはデザインやアニメーションのためだけのタグは極力使わず、シンプルなHTMLの構造で実装します。

3. BEMをベースとしたCSS設計

CSS設計には「OOCSS」「SMACCS」「BEM」「PRECSS」など、さまざまな設計手法が提唱されています。それぞれの設計手法に特徴がありますが、デザインシステムのUIコンポーネント実装を行うにあたって、弊社では「BEM」を採用することにしました。アトミックデザインを使って設計したUIコンポーネントの構造とBEMの親和性が高いためです。

BEMでは、「Block」「Element」「Modifire」という単位で分割してスタイルを定義することにあります。ここで、「Block」の単位と、UIコンポーネントの単位を同じレベルで定義することで、CSS設計とUIコンポーネント設計の単位を一致させることができるからです。

Elementの単位は必ずBlock内に閉じるので、クラス名のBlockを見れば、どのUIコンポーネントのCSSクラスなのかが明確にわかります。

<!-- MenuというUIコンポーネントなら「menu」というBlockにする -->
<ul class="menu">
    <!-- Menuの各項目をElementとして「menu__item」とすると、Menuコンポーネントの一部であることがわかります -->
    <li class="menu__item">
        <!-- 「icon」はBlockが異なるので、これはIconという別のUIコンポーネントが組み合わされていることがわかります -->
        <span class="icon icon--doc"></span>
        <!-- このラベルはBlockが「menu」なので、Menuコンポーネントの一部です -->
        <span class="menu__item-label">メニュー1</span>
    </li>
    <!-- 選択状態などをModifireとMixを使って表現します -->
    <li class="menu__item menu__item--active">
        <!-- 同じUIコンポーネントのデザイン違いなどもModifireとMixを使って表現します -->
        <span class="icon icon--pdf"></span>
        <span class="menu__item-label">メニュー2</span>
    </li>
</ul>

この設計により、UIコンポーネント単位でCSSの影響範囲と責任範囲を限定することができます。

さらに、Fixelが作成するデザインシステムでは、このBEMのルールに加えてデザインシステムごとにユニークなプリフィックスをつけるようにしています。例えば、Fixelオリジナルのデザインシステムであれば、fxl- のような3文字程度のプリフィックスをすべてのクラスにつけます。

これは該当するUIコンポーネントがデザインシステムに属するクラスであることを明確にするためです。このプレフィックスによって、デザインシステムのUIコンポーネントを使って実装したページの中で、デザインシステム内で定義されたCSSクラスなのか、そのシステムかページで独自に定義したCSSクラスなのかがすぐ分かります。

それでは、具体的なコードを例にとって実際の実装例を見ていきましょう。

BEMを使ってベースとなるデザインのボタンをスタイリングすると下記のようになります。

<button class="fxl-btn">基本ボタン</button>
.fxl-btn {
    background-color: #e0e0e0;
    border-color: #e0e0e0;
    border-width: 1px;
    border-style: solid;
    color: rgba(0, 0, 0, 0.87);
    font-size: 14px;
    font-weight: bold;
    line-height: 1em;
    padding: 8px;
}

.fxl-btn:hover {
    background-color: #f5f5f5;
    border-color: #f5f5f5;
    box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25);
}

.fxl-btn:active {
    box-shadow: none;
}

.fxl-btn:disabled {
    background-color: #f5f5f5;
    border-color: #f5f5f5;
    color: rgba(0, 0, 0, 0.38);
    box-shadow: none;
}

.fxl-btn:disabled:hover {
    box-shadow: none;
}

ベースのデザインにスタイルを追加して、デザインのバリエーションを増やす場合は、BEMのModifireを使って、fxl-btn-—primary のようなクラスを作成し、プロパティの差分のみ上書きするようにします。
ベースのデザインのクラスとMixして、以下のように使います。

<button class="fxl-btn fxl-btn--primary">プライマリボタン</button>
.fxl-btn--primary {
    background-color: #6187DB;
    border-color: #6187DB;
    color: #ffffff;
}

.fxl-btn--primary:hover {
    background-color: #4A7EE8;
    border-color: #4A7EE8;
}

.fxl-btn--primary:disabled {
    background-color: #DBE5FA;
    border-color: #DBE5FA;
    color: #92B2F1;
}

サイズの違いも同様に、fxl-btn—small のようにサイズ別のクラスを作成して、ベースのクラスとMixで組み合わせて利用します。

<button class="fxl-btn fxl-btn--small">基本ボタン(小)</button>
<button class="fxl-btn">基本ボタン</button>
<button class="fxl-btn fxl-btn--large">基本ボタン(大)</button>

このように、色のバリエーションとサイズのバリエーションをそれぞれ別に定義しておくことで、それらの掛け合わせで多くのデザインをシンプルに実現することができます。

<button class="fxl-btn fxl-btn--primary fxl-btn--small">プライマリボタン(小)</button>
<button class="fxl-btn fxl-btn--primary">プライマリボタン</button>
<button class="fxl-btn fxl-btn--primary fxl-btn--large">プライマリボタン(大)</button>

5. UIコンポーネントを組み合わせて複雑なUIコンポーネントを作る

このように実装されたUIコンポーネントは、UIコンポーネント同士で影響しあいにくいため組み合わせがが容易になります。
例えば、アイコンを表示するUIコンポーネントと、ボタンのUIコンポーネントを別々に実装しておき、それを組み合わせることで、アイコン付きボタンを作成することが簡単にできます。

<button class="fxl-btn">
    <span class="fxl-icon fxl-icon--search"></span>
    検索アイコン付きボタン
</button>

4. まとめ

この記事では、デザインシステムにおけるUIコンポーネントの実装方法を、デザインシステムを構築してきた経験と知見をもとに紹介しました。デザインシステムを作らない場合でも、システムをWebアプリケーションとして実装する場合のUIコンポーネントの設計、実装方法の参考になるかと思います。

Fixelではデザインシステムの構築のご相談や実装を行っております。
デザインシステムを管理するプラットフォームである、UXHubに搭載した形でのご提供も可能ですので、デザインシステムや業務システム開発を検討中でしたら、ぜひご相談ください。

5. 参考記事

アトミックデザインによる設計手法については、こちらの記事に詳しく書かれています。

CSSの設計手法については「CSS設計完全ガイド」という書籍がおすすめです。
書籍を読んだ感想の記事もありますので参考にしてみてください。

一覧に戻る
お問合わせ