9年モノのRailsアプリで、古のBootstrapを剥がしてFLOCSS化した話

9年モノのRailsアプリで、古のBootstrapを剥がしてFLOCSS化した話

こんにちは、弥生Misocaチームのデザイナー@kanizmbです。

今回、約1年をかけて古のBootstrapの撤去およびCSS設計手法の導入(FLOCSS化)をやり遂げました。
この記事では、これらの変更をどのように進めていったかについてお話しします。

どういった状況だったか

Misocaのローンチは2011年、当時最新であったBootstrap 2.3.2を用いて構築が始まりました。(*1)
当初は請求書の郵送に特化した非常にシンプルなサービスだったため、少しの上書きでスムーズに開発が進められ、Bootstrapの利点を存分に享受できていたのだと思います。

Bootstrap2.3.2をapp.cssで上書きしている図

しかし時は流れ、取引先管理、品目管理、外部サービスとの連携など、機能が増え続けてどんどん綻びが出始めます。 設計方針もないままに野放図に差し込まれたCSSたちは、いつしか激しい詳細度バトルを繰り広げるようになりました。

たとえば、コードで示すとこのような内容です。(コードはイメージです)

/* Bootstrap */
h2  { 
  font-size: 20px;
  margin: 20px 0;
 }

/* アプリ汎用スタイルを上書き */
.page-A,
.page-B,
.page-C,
.page-D {
    #main {
        h2 { 
          padding-bottom: 10px;
          border-bottom: 1px solid #eee;
        }
    }
}

/* 特定のページの一部を上書き */
.page-A {
    .team-member {
        h2 { 
          margin-top: 30px;
          padding-bottom: 0 !important;
          border: none !important;
        }
    }
}

/* 特定のコンポーネント用に上書き */
.modal {
    h2 {
      margin: 0 !important;
      padding-bottom: 20px !important;
    }
}

スコープが広いBootstrapのスタイルを、全体用のスタイルで上書き、さらにそれらをページごとのスタイル・コンポーネントのスタイルで上書きしているため、 !important や冗長な指定が山盛りになっていました。

Bootstrap 2.3.2 を app.css, page.css, component.css の順で上書きしている図

新しくスタイルを追加したり変更したりするには都度既存のスタイルに打ち勝つ調整が必要で、要素間にガイドの一文を差し込むことすら手こずる場合もありました。
これはデザイン上の改善サイクルを回す上でも到底良い状況とは言えません。

これら負債解消のために、デザイナーが中心となってCSSの改善プロジェクトを始動しました。

まずは相手を知る

嘆いていてもなにも始まらないので、まずは現存するファイル・スタイルの用途や影響範囲を調べていきます。

現状のディレクトリごとにスプレッドシートを作成し、既存の各ファイルがどこでどのように使われているか大まかに記入します。

各CSSファイルごとに何が書かれていて、どのファイル(テンプレート)で使われているかを記入しているスプレッドシート

各CSSファイルごとに何が書かれていて、どのファイル(テンプレート)で使われているかを記入しているスプレッドシート

調査の過程で過去の担当者からの叫び(FIXMEコメント)が多数発掘され、取り組みに対する意識が一層高まります。

FIXMEコメントのキャプチャ「アプリケーション全体的に使うメインのコンテンツを内包するコンポーネント/FIXME: 作りが非常に悪いので main というクラスとともに早急に見直すこと。/FIXME: header下のスタイルはコンポーネントとして切り出せるはずなので、うまく切り出したい。」

FIXMEコメントのキャプチャ「FIXME: 本来であれば各一覧でのアクション等の見た目は一貫性をもたせるべきだが、取引先だけ古いままなので特別に専用のコンポーネントとなっている」

FIXMEコメントのキャプチャ「各文書の明細のコンポーネント/FIXME: 各スタイルで table等を使っているため詳細度を上げて優先的にスタイルが当たるようにするためにエレメントを直で指定していたりするが、好ましくないので、全体的に見直し修正すること」

FLOCSS 化

改変後のCSS設計手法は、FLOCSSを採用しました。
後発の手法で導入事例も多く、日本語のドキュメントもあり、今後のチーム開発でルールや作法の共有がスムーズに行えると判断したためです。

(FLOCSSの具体的な設計手法の解説は公式ドキュメントやそれ以外にたくさん記事があるため、ここでは省略します)

github.com

作業に入る前にCSS改善担当者間でFLOCSS提唱者である谷 拓樹さんの「柴犬でもわかるFLOCSS」を読み合わせて認識の統一をしたのち、以下の手順で進めました。

booth.pm

STEP1. FLOCSSルールに沿ってディレクトリ分類

先のファイルごと用途調査を元に、既存のファイルをFLOCSSのルールに沿ったディレクトリに分類していきます。1つのファイルで分類がまたがるスタイルが混在するものもありましたが、ここでは細かな点は一旦無視しています。

この段階ではまだ微妙なバランスの上に成り立っているスタイルが多いため、ファイルの移動により読み込み順が変わって表示崩れが起こらないか、慎重に確認しながら少しづつ移動しました。

なお、1ファイルで用途が多岐に渡る巨大な汎用ファイルについては保留にして触らずに置いておきます。

STEP2. FLOCSSルールに沿った命名変更とスタイルの整理

大まかな分類が終わったら、各ファイル内に記述されている個別のスタイルがどこでどのように使われているかをスプレッドシートに書き出し、新しい命名や分類を検討しました。

新しい命名・分類では以下の点に配慮しています。

  • HTMLの構造に依存しすぎない
  • スコープが絞り込まれていない状態で要素セレクタを使用しない(foundationは除く)
  • BEM (MindBEMding)を使用し、名前から影響範囲や役割が想像できるようにする
  • 今後のHTML構造の変更や機能の追加に耐えられるよう、詳細度をなるべく低く抑える

たとえば以下のような変更です。

/* before */
body.team  {
    .member-list {
        ul { ... }
    }
}

/* after */
.p-team-member__list { ... }

命名変更とあわせて他と共通化できる部分は統合し、重複するもの、似ているけど微妙に異なるもの、不要になっていたスタイルもバッサリと整理・削除しました。

この時、見た目が似ているからといって何も考えずに統合すると後から困る可能性があるため、その要素の性質や今後のデザイン方針を踏まえた変更でなければなりません。
このあたりはデザイナーが直接担当していることで、シームレスに判断しながら作業を進められました。

ユーティリティスタイルの併用

変更前のスタイルは要素セレクタが多用されるなどでスコープが広いスタイルが多く、整理の際にこちらを立てるとあちらが立たずといった場面がとても多くありました。

このような谷を埋めるためにマージンやフォントサイズ、色や配置指定のためのユーティリティスタイルを用意しました。
わずかな差はこのユーティリティスタイルで吸収しながら、コツコツ整理していきます。

ユーティリティーディレクトリのファイル一覧のキャプチャ、clearfix, margin, cursor, flex, float, display, text など用のファイルが並んでいる

自前のUIコンポーネントへの置き換え

今回のCSS改善と並行して、ボタンやタブ、フォーム・ページングなどをBootstrapのものから、自前のUIに置き換えるプロジェクトも進んでいました。

この対応でアプリ内で使用されていたBootstrapのUIは、すべて別のスタイルに置き換えられています。

Bootstrapのコンポーネントと自前のUIコンポーネント一覧 ビフォーアフター

こちらの取り組みについて、詳しくは以下の記事にあります。

tech.misoca.jp

Bootstrap 撤廃

FLOCSS化と自前のUIコンポーネントへの置き換えが終わった後、Bootstrap用のCSSはほとんど用済みになっていました。
不要なものは削除し、どうしても必要なものはFLOCSSで分類したディレクトリに移し変えてすべての関連ファイルを削除します。

なお、JS部分は別途フロントエンドチームが全て削除してくれています!

tech.misoca.jp

CSS改善を支える仕組み

CSS改善プロジェクトは非エンジニア2名によるプロジェクトだったため、リソース不足や技術的な壁にぶつかる懸念もありましたが、実際のところほとんど支障なく進行出来ました。

主な理由は以下の3点です。

高速・高品質コードレビュー

CSSのレビューはなかなか手をつけづらく滞りがちなものですが、Misocaではレビュー待ち数を増やさないよう所属プロジェクトを問わず協力し合ってレビューし合う体制があるため、CSS改善のPRも例外なくスムーズにレビューが通っていました。
この際、単純な見た目の違いはもちろん特別な操作を行った時にだけ表示される部分や、他の箇所との整合性までしっかり見てもらえます。

レビューや巻き戻しをしやすくするためにPRを小さくに分けていた都合で、後続の作業に影響が出やすい状況でしたが、全く困ることがありませんでした。

遊軍チームのサポート

デザイナーがCSSのリファクタリングを担当すると、リファクタリングに伴うデザイン変更可否の判断をスムーズに進められる一方、動的なUIの変更や複雑なspec修正が絡む部分など対応しきれないケースがどうしても出て来ます。

こんな時、気軽に声をかけられるのがこぼれタスクを専門に扱う「遊軍」チームです。
「テスト通らない助けて〜」「やります!」と、気負わず相談できる環境にはとても助けられました。

tech.misoca.jp

最後の砦、ビジュアルリグレッションテスト

影響範囲の広いスタイルの移動や削除・命名変更では思わぬ画面差分が発生する場合があります。
リリース前にこれらの差分をとらえてくれるのが、ビジュアルリグレッションテストです。
変更前後のスクリーンショットを比較して、前後で差分が出ていないかを検証してくれます

tech.misoca.jp

アプリ全体で微妙なズレまで拾ってくれるので、きちんと意図通りに変更されているかしっかり確かめて安全にリリースができました。

ビジュアルリグレッションテスト、reg-suit のキャプチャ。表示差分が赤く表示されている。

ビジュアルリグレッションテスト、reg suit のキャプチャ。前後のスクリーンショットを並べて、表示が変わっていることが判断できる。

Bootstrap撤廃 & FLOCSS化 を終えて

FLOCSS化を終えたディレクトリのツリー。余計なファイルやディレクトリがなくなっている。

よかったこと

  • !important 地獄からの脱却
  • 設計・命名ルールが定まり、どこにどう書くかを判断する基準が出来た
  • 適用範囲が明確になり、変更や削除をあまり気を使わずに出来るようになった
  • componentの再利用性が高まって、新しくスタイルを書く量が減った
  • HTML側に書かれたclass名からスタイルがどのファイルに書かれているかすぐにわかり、grepして探さなくて良くなった
  • 令和になってもBoostrap 2.3.2を使っている負い目から解放された

気になること

  • まだ判断に迷う部分がある
    • projectに置くか、componentに置くか
    • Modiferとして扱うか、 .is-xxx のような補助的な名前にするか
  • BEMのBlock粒度のばらつき(特にproject内)
    • 大きいものだとページ(RailsのController)単位だけど、コレジャナイ感
  • BEMで命名が長大になってしまう場合の対処
    • Blockの中でElementが入れ子になる場合、みんなどうしているんだろう…?

今後やってみたいこと

  • 現在部分的に導入しているScoped CSSを利用したVueコンポーネント化範囲の拡張


まだまだ改善の余地はあると感じますが、ひとまず各スタイルがHTMLの構造や他のスタイルと疎結合になり、今後新たな方針で進めるにしても舵を切りやすくなったと思います。

約1年をかけてコツコツ進めてきたCSS改善がやっと形になって、感慨もひとしおです。(膨大すぎる作業を支えてくれたパートナースタッフの @riszw に大感謝!)

宣伝

MisocaではつらくないCSS環境で開発を進めたいエンジニア・デザイナーを募集しています。

www.wantedly.com


  1. 正確に言うと2系が出たのは2012年1月なので、ローンチ初期の段階は適宜アップデートしていて、ある時期に固定されたものと思われます。(追記)Misoca創業者の証言によるとローンチ時は1系で、1〜2年後に2系にアップデートされたとのことです。