CSSについて本気出して考えてみた 〜CSS × Atomic Design〜

こんにちは、WEBエンジニアの神山です。

最近シェルをZshからFishに変えました。Fishについて書きたいのですが本題とそれるので一言でまとめます。
「うお!」

さて今回はAtomic Designという考え方を知りまして、それを踏まえてCSSに対する考えを書きました。
今まではBEMやSMACSSを使っていたのですが、そこに感じている悩みやAtomic DesignをもとにしたCSS設計の利点などを自分なりにまとめてみました。

正直CSSについて詳しい人ではないので正確な考察が出来ているかはわかりません。。
もし違っていたり、より良い考え方などありましたらコメントを頂けると非常に助かります。。

そもそもAtomic Designとは

Atomic Designとは、ボタンやフォームなど小さいパーツを組み合わせて、一枚のページを作っていく考え方です。
たとえば検索ページを作る際に、まず入力フォームを作り、その横に「検索」ボタンを作り、フォームの上に「〜〜を検索する」という見出しを作り、検索ページにヘッダーやフッターを配置し、、、みたいに考えていきます。

Atomic Designは、原子や分子など化学から発想を得ております。化学を勉強したことがある人は理解しやすいかもしれません。 まずボタンや入力フォームという原子があり、それらが組み合わさって検索フォームという分子になり、そういう分子がたくさん集まってページという物質が出来上がるというイメージです。

こちらがAtomic Designの考案者が解説したサイトになります。英語ですがわかりやすい図を用いて解説してあり、直感的に理解しやすいです。

bradfrost.com

Atomic Designは具体的に以下の手順でデザインを考えていきます。

  1. Atoms(原子)
    原子は、ボタンや入力フォームにあたります。
  2. Molecules(分子)
    分子は、検索フォームにあたります。
  3. Organisms(有機体)
    有機体は、ヘッダーやメインコンテンツ、サイドバー、フッターにあたります。
  4. Templates
    テンプレートはページのワイヤーフレームにあたります。
  5. Pages
    ページはワイヤーフレームにコンテンツを入れて、文字通りページとして完成したものにあたります。

こちらにそれぞれの具体例がたくさん載っているので、導入の際に参考にしてみてください。

http://demo.patternlab.io/demo.patternlab.io

CSS設計のポイント

CSS設計のポイントは以下の4つで考えております。
当たり前のことなのですが、これらをきちんと守らないと管理しづらいCSSになってしまいます。

  • 予測しやすい
  • 再利用しやすい
  • 保守しやすい
  • 拡張しやすい

これらは下のサイトを参考にさせて頂きました。

article.enja.io

現状のCSS

さて、上にあげたCSSの設計のポイントを実用的にするために、様々な設計手法が存在します。

有名なものだとSMACSSなどOOCSSをもとにしたものが広く使用されていると思います。またBEMのように少し違う側面での設計手法も存在しており、他の設計手法と組み合わせて使うことも多いと思います。

私はBEMとSMACSSをかけ合わせて使っております。どちらも好きな設計手法です。

BEMは命名をBlock、Element、Modifierで分けるというルールがシンプルでわかりやすく、このルールをきちんと守っていれば、管理しやすいCSSができあがると思います。

<div class=”article>
  <div class=”article__heading”>hoge</div>
  <img class=”article__image” />
</div><div class=”article>
  <div class=”article__heading--small”>fuga</div>
  <img class=”article__image--small” />
</div>
.article {
  &__heading {
    ...

    &--small {
      ...
    }
  }
  
  &__image {
    ...

    &--small {
      ...
    }
  }
}

またSMACSSはCSSをカテゴライズして管理する手法です。

  • Layout
    ヘッダー、メインコンテンツ、サイドバーやフッターの配置を整える
  • Module
    リストやボタンなど再利用そうなもののデザインを定義する
  • State
    クリックされたものなど状態により変化したもののデザインを定義する
  • Theme
    ページ単位のデザインを整える
  • Base
    CSSの基幹部分やタグのデフォルト値などを決める

また私はボタンやテキストのデザインを決めるとき、マルチクラスを使用しております。

/modules/button.scss

.button {
  display: inline-block;
  padding: 12px 20px;
  border-radius: 2px;
  background-color: transparent;
  color: #fff;
  font-size: 80%;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;

  &-default {
    border: 1px solid whiten($base-color, 90%);
    background-color: #fff;
    color: whiten($base-color, 20%);
  }

  &-small {
    padding: 8px 12px;
    font-size: 70%;
  }

  &-full {
    width: 100%;
  }
}

これをHTMLでは以下のように使っております。

<div class=”article>
  <div class=”button button-default button-small”>small</div>
  <div class=”button button-default button-full”>full</div>
  ...
</div>

これでボタンのデフォルトのデザインを統一させることができ、いろいろなパターンのボタンを用意することが容易になります。

現状のCSSの悩み

たとえば警告用のボタンを作りたいときに、2通りの方法が考えられます。

一つは、ボタンクラスに要素を増やす方法。
警告用のボタンであれば、button button-warningというCSSを用意します。

もう一つは、Moduleの一部として考える方法。
ログインボタンのデザインであれば、login_form-buttonというCSSを用意します。

どちらも正解ですしチームで方針をしっかり決めれば良いことだと思います。
しかし2通りの方法があると、CSSを設計する上で管理しづらさ、わかりづらさが出てしまうと考えております。
そしてこれを強く問題視している理由は、デザインを考える視点が真逆だからです。

ボタンやテキストなどのパーツを組み合わせて使うという考え方は、小さいものから考えて大きいものを作っていくという考え方です。 ボタンやテキストを予め定めておき、何かのModuleを作るときはそれらを組み合わせてModule全体をデザインしていくイメージです。

一方、フォームの中のボタンやテキストのデザインを変えるという考え方は、大きいものから考えて小さいものを作っていくという考え方です。 何かのModuleを作るときはModule全体のデザインを考えて、それを細かく落とし込んだときにボタンやテキストが作られるイメージです。

多くの設計手法は大きいものから考えていくやり方です。しかしボタンやテキストなどのデザインを統一したいとなると、小さいものから考えていくやり方も必要になります。
つまり両方の考え方が混在してしまいます。

Atomic DesignをもとにCSSを設計

これを解決するために、Atomic Designの考えをもとにCSSを設計すべきではと考えました。上で紹介したように、Atomic Designは全てのデザインを小さいものから作っていくという考え方をしているからです。

考え方を統一すれば、ボタンの変更ならボタンを管理しているCSSを変えれば良いと明確になります。ボタンやテキストのデザインがぶれることもなくなります。 さらに何かのModuleを作るときもデザインの雰囲気が似てきて、組み合わせても違和感のないものが作られるようになると考えております。

またAtomic Designはコンポーネントを組み合わせていくというシンプルな考え方なので、CSSもシンプルになります。

まずAtomsというカテゴリーを作り、そこでボタンやテキストなどのCSSを管理します。
次ぎにMoleculesというカテゴリーを作り、ボタンやテキストなどを組み合わせて作ったコンポーネントを管理します。ここでのCSSはボタンやテキストの間隔を調整するものになります。ボタンを変更したいときはAtomsを変更するようにします。

というようにOrganismsやTemplatesというカテゴリーも作っていきます。PagesはCSSとは関係ないので必要なさそうです。

またSMACSSと比較すると、視点こそは違うものの区分けは似ているので、SMACSSからの移行も難しくはなさそうに思えます。
LayoutはOrganisms、ThemeはTemplatesに相当すると思います。Baseは相当するものがありませんが、Baseというカテゴリーは作ったほうがいいと思います。

結果的にこのようなディレクトリ構成になると思います。

stylesheets/
  |- atoms/
    |- button.scss
    |- heading.scss
    |- text.scss
  |- molecules/
    |- form.scss
    |- navigation.scss
  |- organisms/
    |- header.scss
    |- sidemenu.scss
  |- templates
    |- template.scss
  |- base/
    |- base.scss
    |- mixin.scss
  |- application.scss

APBCSS

Atomic Designを用いたCSSの設計手法にAPBCSSというのがありました。Atomic Designを用いたCSSを考える上でとても参考になりました。

ただディレクトリ構成をAtomic Designのように/atoms/moleculesとしたかったので、導入は見送りました。 ディレクトリ構成はわかりやすさが肝心だと考えております。

まとめ

私としては、Atomic Designを使用するとCSSにおいて、管理が的確になると思います。いわば関心の分離です。

ただこれが全のアプリケーションにおいて最高のCSSの設計になるとは思っておりません。アプリケーションによっては使いづらいこともあると思いますし、SMACSSやBEMでも十分に使いやすいCSSは組めると思います。あくまで一例として捉えていただければと考えております。

また一番大事なのは、アプリケーション全体でデザインが統一されるようにすることであり、それを管理しやすくするためにCSSの設計を考えるということなのかなと思います。

とりとめのない結論になってしまいましたが、CSSが幸せになればいいなと願うばかりです。

We’re Hiring

弊社ではWeb / ネイティブアプリエンジニアを募集しております。
ご興味がありましたらお気軽にご連絡下さいませ!
エンジニアの方、ぜひ情報交換しましょう!

www.wantedly.com

www.wantedly.com