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 など用のファイルが並んでいる

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

CSS 改善と並行して、ボタンやタブ、フォーム・ページングなどを Bootstrap のものから、自前のコンポーネントスタイルに置き換えるプロジェクトも動いていました。

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

この作業によって、アプリで使用されていた Bootstrap の CSS コンポーネントはすべて自前のスタイルに置き換えられました。 こちらの取り組みについて、詳しくは以下の記事にあります。

tech.misoca.jp

Bootstrap 撤廃

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

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

tech.misoca.jp

CSS 改善を支える仕組み

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

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

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

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

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

遊軍チームのサポート

デザイナーがリファクタリングを担当する事で、リファクタリングに伴うデザイン変更の細かな判断や今後の変更を前提とした設計がスムーズになる一方、動的な 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系にアップデートされたとのことです。