I'm kubosho_

思想の固まり

神獄のヴァルハラゲートのCSS設計

CSS Architecture Advent Calendar 2014 9日目の記事になります。

神獄のヴァルハラゲートのCSS設計方法について振り返りつつ、こうしているということや、上手くいったところ、改善したいところを書いていこうと思います。

アプリの規模

ASP.NET MVCを使っていて、View側はRazorテンプレートを使っているのですが、Razorのファイルを検索してみると以下の量となります。

find ./ -name "*.cshtml" | wc -l
    1674

実際には、これにフィーチャーフォン向けのファイルや、部分的なViewファイルも含まれています。

なので、実際CSSを適用しているファイルの量は、この検索結果よりは格段に減りますが、それでも、約600ファイルはあると思います。

ちなみに、今年のはじめに同僚の@mayukiが、ソーシャルゲームのフロントエンドとASP.NET MVC (Lite)というタイトルで、めとべや東京#3 (Room metro Tokyo #3)にて発表したのですが、そこには「View数は400超」と書いてあるので、1年間の運用で約200ファイル増えたことになります。

対応端末、ブラウザー

スマートフォンでは、以下の環境でアクセスされることを想定して対応しています。

OS

  • iOS 6 or later
  • Android 2.3.x
    • 重要な機能だったら、Android 2.2.xにも対応することも…
  • Android 4.0 or later

ブラウザー

  • iOS
    • Safari
    • WebView
  • Android

iOS 6やAndroid 2系はそろそろ対応端末から外したいなと思っています。来年の今頃は対応しなくて良くなってたらいいですね。

命名規則

BEMを採用しています。ただし、セレクタの命名規則は以下のように変えています。

[prefix]-[block]_[element]-[[Modifier-Key]-[Modifiler-Value]] {
  // property: value;
}

今年のネーミングルール #CSS設計 - < /gecko >とだいたい同じですが、以下の点が異なります。

  • BlockとElementの区切り文字は「_(アンダースコア)」
  • 複数の単語を連結する場合は「-(ハイフン)」を使う
  • ModifierはCamelCaseを使う。例は以下の通り
    • foo-Bar-Baz ([block]-[Modifier-Key]-[Modifier-Value])
    • foo_bar-Baz ([block]_[element]-[Modifier-Value])
  • prefixは、共通で使うルールセットはプロジェクトのコードネーム、各機能のみで使うルールセットはその機能名を使う
    • ガチャならprefixはgachaという感じ

あとは、hiloki/flocssのMindBEMdingの章にあるように、JavaScriptで操作されるような「状態」を表すようなModifierについては、SMACSSのStateパターンの命名のように、is-*プレフィックスを付けて.is-activeという感じにしています。

.is-activeには直接スタイル指定をすることを禁止しています。

// これはOK
.block_element.is-active {
  display: block;
}

// これはNG
.is-active {
  display: block;
}

良いところ

  • --__という区切り文字より、セレクタ名が醜くならない(個人の主観です)

あとは構造が分かりやすいだったり、class名が衝突するということが少ないという、BEMやMindBEMdingを採用した人ならだいたい感じることでしょうか。

改善したいところ

  • prefixのところで世代管理をしなかったのは間違いだった
  • Modifierを使っているclass名で、Modifier-Keyがないclass名というのは、分かりにくいのではと思った
    • この章を書いて気づいた…

ディレクトリ構成

hiloki/flocss に基本は準拠しています。「基本は」と書いたのは以下のディレクトリ名を自分の好みで変えているからです。

  • foundation -> base
  • object/project -> object/page

使っているCSSプリプロセッサーやライブラリー

  • LESS
  • Normalize.css

LESSな理由ですが、ソーシャルゲームのフロントエンドとASP.NET MVC (Lite)の7ページにも書いてあるように、Visual Studioとの相性が良かった(新規ファイル作成時に*.less形式でのみファイルが作れた)ことが要因です。

とはいえ、MSDN BlogsのAnnouncing new Web Features in Visual Studio 2013 Update 2 CTP2にも書かれているように、Visual Studio 2013 Update 2(ちなみに今はUpdate 4が最新)から公式にSass(*.scss形式)のファイルも新規作成できるようになったので、Visual Studioユーザーでも好みでLESSかSassかを選べるようになったと言えます。

ライブラリーはNormalize.cssくらいしか使っていないです。これはやはり同僚の@mayukiが入社したての頃に、汎用classをゴリッと書いてくれたので、ライブラリーを使う理由があまり無くなったという感じです。

CSSプリプロセッサーの機能について

extend

CSSプリプロセッサのExtend - hiloki/flocssに書かれているように、モジュールで完結するextendは許容し、それ以外は禁止しています。むやみにextendを多用すると、どこにそのルールセットが書かれているか分からなくなり破綻する、というのが大きな理由です。

ルールセットの入れ子

CSSプリプロセッサーのほとんど(全て?)はルールセットの入れ子がおこなえますが、入れ子の深さは二段階までと定めています。具体例としては以下のコードです。

.foo {
    border: 1px solid #003760;
    color: #000;
    background: rgba(0, 0, 0, 0.5);

    .nest-01 {
        font-weight: bold;

        .nest-02 {
            color: #f00;
        }
    }
}

なぜ、二段階までに抑えているのかというと、制限がなかった場合、出力後のCSSのセレクタ部分がとても長くなってしまう可能性があるということが挙げられます。

具体例を書くと、以下のようなLESSのコードがあったとします。

// Uuuugly!
.foo {
    .nest-01 {
        .nest-02 {
            .nest-03 {
                .nest-04 {
                    .nest-05 {
                        color: #333;
                    }
                }
            }
        }
    }
}

上記のコードをCSSにコンパイルした場合、以下のようになるでしょう。非常に長くて醜いです。

.foo .nest-01 .nest-02 .nest-03 .nest-04 .nest-05 {
    color: #333;
}

また、実際に挙動を確かめられていないですが、多くのサイトで「ブラウザーのセレクターの解釈として、右から左に解釈される」と書かれています。

とすると、上記のCSSは「.nest-05 -> .nest-04 -> .nest-03 -> .nest-02 -> .nest-01 -> .foo」と解釈されることになります。「.nest-01 -> .foo」という構造よりも解釈に時間がかかりそうです。

ちなみに、古い記事(2011年)ですが、CSSセレクタによる高速化、実際のところ « LINE Engineers' Blogに実際の計測結果が掲載されており、そこには以下のように書かれています。

・スタイルを当てる要素にはできるだけclass又はIDを指定する

・子孫セレクタは重いのできるだけ減らす

という施策に一定の効果はあるようですが、その効果が如実に現れるのはHTML、CSSのコードが非常に大きいページに限られるようです。

そのなかでも、子孫セレクタを減らす施策よりも、スタイルを当てる要素にはできるだけclass名を指定する施策のほうが、効果があるようです。

ということで、MindBEMdingの考え方を適用し、あるBlockの中でスタイルを当てたい要素には、.block_elementだったり、.block_element-Key-Valueという感じでclass名を指定し、スタイルを適用しています。

まとめ

ソーシャルゲームというのは、最初から機能が数十種類あったり、Viewのファイル数が数百ファイルを超えるということは珍しくないと思います。

そんな中で、CSSを書く上での指針がないと、時間が経つにつれ運用が苦痛になってきます。

例えば新しい人が入ってきたり、自分に何かあって他の人が一時的にプロジェクトに入ってきた場合、CSSを書く上での指針が無いと、どのようにCSSを書いていけばいいのか、理解に時間がかかることになります。

なので、CSSを書く上での指針を定め、かつ、それをGitHubのWikiなど、プロジェクトのメンバーが目に入る場所に残しておくのが重要と、自分は考えています。

明日は、越智さんです。

記事内で紹介したGitHubのリポジトリや記事