とあるソシャゲのHTML/CSS設計話

Frontendアドベントカレンダー19日目】

Xboxに釣られて転職してから2年半…あっという間だった…。

関与したもの:

  1. スマホ版ピグ(リニューアルして面影無し)
  2. ピグファンタジア(11月末クローズ)
  3. 新規ゲーム ←今ここ

今は新規ゲームでコーディングの人としてjoinしてます。

新しいサービスを立ち上げる時に必要なHTMLとCSSの土台作りを全部やるということが、
「HTML/CSS設計」という言葉で装飾されることを知ったのは割と最近です。

マークアップだけで一人据えるのは珍しいと思うので、今やってることなど含めてつらつら書きます。

ここが変だよソシャゲ開発

依頼を受けてサイトを作る場合は次のようなフローだと思います:

  1. クライアントと打ち合わせ
  2. 仕様が決まる
  3. デザイン決まる
  4. 値切られる
  5. 価格が……決ま…る
  6. コーディング
  7. クライアントチェック
  8. 突然の無理難題に戦慄走る
  9. テスト・修正
  10. リリース

ソシャゲの場合はこうです:

  1. ゲームコンセプト・メインループ・チームメンバー等が決まる
  2. エンジニアが裏側を、ディベロッパーが表側の環境決める
  3. 開発環境作る
  4. ゲーム仕様が決まった所からデザイン製作始まる
  5. デザイナーが嘆く傍らエンジニアは黙々と作業
  6. デザインが出来た所からフロント作業始まる
  7. 出来た所をつなぐ
  8. テスト・修正
  9. メンバーが続々と体調崩す
  10. リリース

モノを作る時って大抵は仕様が決まってから作るけど、ソシャゲは全体の仕様が決まる前に走り出す。
転職前はクライアントの顔色を窺いながら仕様第一で動いていたので、この違いに凄く戸惑いました。

設計ことはじめ

全体の仕様がないというのを普通のサイトに置き換えると
「トップページがあるということだけ確定」してて、「トップページの仮デザインしかない状態」になります。
もうすこし恵まれていれば、会社概要やお問い合わせページが確定してデザインもあるかもしれません。

全体像が見えないし、デザインは二転三転するし、細かい仕様はいつ変わるのか分からない。
かといって何もしないでいるとリリース日が近づいてくるわけで、作れる所から手をつけるしかない…。

この段階でできること:

  1. 命名規則を決める
  2. ページのHTML構造を考える
  3. UIを洗い出す

1. 命名規則を決める

似たものがあれば必要なページやコンテンツは予想できる。

ソシャゲの機能はジャンルが違ってても似通ってて、何が必要なのか予想しやすいです。

あるあるソシャゲ機能:

  • マイページ (mypage)
  • おしらせ (info)
  • あいさつ (greeting)
  • ガチャ (gacha)
  • ショップ (shop)
  • アイテム一覧 (item)
  • クエスト (quest)
  • イベント (event)
  • フレンド (friend)
  • 設定 (setting)
  • ヘルプ (help)

カードゲームあるある機能:

  • カード一覧 (card)
  • 進化 (upgrade)
  • 強化 (evolution)
  • 売却 (sell)
  • 対戦 (battle)
  • クエスト (quest)
  • ギルド (guild)

機能(コンテンツ)はそのまま簡単な英単語にして使います。
カード一覧をcardと命名した場合、画像やCSSディレクトリの名前はどうするのか?
ファイル名はどうするのか?等を決めます。

2.ページのHTML構造を考える

大抵はトップページのデザインをベースにして他ページのデザインも作られます。
トップページを組めば必要なレイアウト要素を抜き出してテンプレート化することが出来ます。

3.UIを洗い出す

デザインがなくても、ページやコンテンツの予想ができれば出てくるUIの予想も出来ます。

まずサイト内で共通のヘッダーとフッターは確定ですね。
グローバルメニュー。
お知らせ表示する時は大抵リストです。
カード、ユーザー、アイテムの表示は左側にサムネイル、右側にステータス。
ガチャはボタンがちょっと派手になることが多い。

……などなど

UIコンポーネント

前で「洗い出す」と書いたけど、必要不可欠なUIというのはほぼ決まってます。
ので、デザイン待ちの間にこれらのUIを先にコンポーネントとして作っておきます。

  • ヘッダー・フッター
  • メニュー
  • ボタン
  • 見出し
  • ダイアログ(アラート含む)
  • フォーム要素
  • サムネイル
  • リスト
  • 飾り枠
  • タブ
  • ナビゲーション(戻るリンク・ページング)
  • ステータス(プレイヤー・カード・アイテム)
  • カルーセル
  • 隙間(margin,padding)

デザインがないうちは仮スタイルをつけるだけ。
UIとしての見た目や機能・お約束は変わらないので、background:blueとかでもそれっぽいUIが作れます。

仮スタイル状態

デザインが出来たら仮スタイルを消して順次差し替えるだけです。

普通のサイトでも、↑こういうUIは出てくるものが割と決まっているし、
レイアウトも「前似たようなの作ったわ」って事が多いです。
そういうのをコンポーネント化します。

UIコンポーネント3分クッキング:

  • 適当なhtmlファイルを用意する
  • ファイル名をUIと同じ名前にする(タブならtab.html)
  • UIのHTMLとCSSをコピペ(タブならタブのソースだけ抜粋)
  • componentフォルダに投入

本当に基本だけのスタイルを当てたものは単なる雛形だけど、
サイト内のCSSを読み込んでる場合はスタイルガイドになります。
最近はHTML作成の所を自動でやってくれるツールが出てきました。

大規模になればなるほどドキュメント作成の手間が増えるので、
最初から自動化しておくと後々楽できます。

コンポーネントができてくると、ページの作成がコピペで済むようになります。
デザイン見る→コンポーネント作る→コンポーネント配置→ユニークな所作成

デザイナーの協力を仰げ!

デザイナーには何かしらUIを作ったら1つのファイルにまとめるよう予め頼んでおきます。
ページをデザインするときはコンポーネントファイルからUIパーツをコピーして作ってもらいます。

ページに使っている部品を1カ所に纏めておくというのは面倒だけどかなり大事です。
同じUIなのに高さや幅がページ毎に違っていたらどれを基準にしたらいいか分からないじゃないですかー。
デザインから狂っていたらどうにもならないので、デザイナーの理解と協力は欠かせません。

先導役の重要性

コーディングルールとか命名規則にはこれといった正解はないです。
どちらかというと、ルールを決めて先導してくれる人がいることの方が重要だと思う今日このごろ…。
特に複数のディベロッパーで作る大規模開発なんかでは、各々が決めたルールで走り出すとモジュール毎にルールが変わってしまって非常に危険です。

もし先導役になったら先ずこれを決めるべし:

  1. HTML5準拠するかどうか
  2. ディレクトリ構造
  3. ファイルの命名規則
  4. IDやClassの命名規則
  5. HTML構造
  6. コーディングルール
  7. CSSプリプロセッサ
  8. HTML・画像・CSSの圧縮方法
  9. スタイルガイドどうするか

(製作環境、対応端末は決まっていると仮定)

よもやま話

これまでに気づいたことなど・試したことなど。

共通スタイルの目印

ゲームのスタイルシートはcommonなものと、各モジュールごとに読み込むユニークなものに分けることが多いです。
普通のサイトでも規模が大きくなると分けるんじゃないでしょうか。

スタイルが増えれば増えるほど何がcommonなのか見失い、それがどこに書いてあるのか分からなくなりました。
それでスマホピグとピグファンタジアでは共通スタイル用ファイルに書いてあるスタイルに目印になる接頭語をつけました。

スマホピグ:spg-
ファンタジア:pf-

結果、共通とそうでないものの見分けがついて修正しやすかった。

モジュールやコンポーネントにも接頭語を付けるようにしてみたら、
クラスがやたら増えても見分けがつきやすかった。

<div class="c-btn c-btn-sm c-btn-bl foo-btn-bar">

JSで操作する為のIDやクラスに対する目印

上のボタンの例で、.foo-btn-bar をJSで握っていたとする。
でもHTMLを見ただけではその判断が出来ません。
クラスを削除したり変更したいとき、JS側の確認をしたり他のディベロッパーに周知する手間が増えます。

JSで操作するためだけに付ける目印がついていれば一目瞭然:

<div class="c-btn c-btn-sm c-btn-bl foo-btn-bar js-foo-btn">

でもIDだと若干気持ち悪い:

<div id="js-foo-btn">

ファイル・ディレクトリ名とモジュール名を一致させる

ガチャの場合:

  • gacha/index.html
  • css/gacha.css
  • img/gacha/
  • js/gacha/

\わかりやすーい/

バリエーションの増やし方

ゲームは普通のサイトと違ってUIのバリエーションがとにかく多い。
コンポーネントのバリエーションをどうやって増やすかは毎度悩みます…。

1. ベースクラス+オプションクラス(OOCSS)

オーソドックス。
クラスの干渉が激しく汚染でカオスになりやすい。
大規模になるほど管理運用の難易度が上がる。

<div class="btn circle blue small"></div>

2. ベースクラス+オプションクラスその2

オプションクラスにベースクラスを接頭語としてつける。
何のオプションなのか分かりやすいが、名前なのかオプションなのかの判断がつきにくくなる。

<div class="btn btn-circle btn-blue btn-small"></div>

3. ベースクラス+オプションクラスその3

オプションクラスにベースクラスの接頭語とオプション名をつける。
冗長過ぎるが、大規模ならこれくらいしつこい方が安全だったりする。

<div class="btn btn-type-circle btn-color-blue btn-size-small"></div>

4. 3をBEM化

オプションをアンダースコアにする。

<div class="btn btn_type_circle btn_color_blue btn_size_small"></div>

これだけだとハイフンとそう変わらないが、ボタンに名前をつけると違いがでてくる。
問題は慣れるまで気持ち悪いこと。

<div class="btn btn-hoge form__btn btn_type_circle btn_color_blue btn_size_small"></div>

5. セマンティックな名前+@extend

表向きはセマンティックageるよ~

<div class="btn primary-btn"></div>

CSSのプリプロセッサにある@extend機能をフル活用してスタイルを作る。

.primary-btn {
 @extend %btn-type-circle;
 @extend %btn-color-bl;
 @extend %btn-size-small;
}

HTMLの方はかなりスッキリするものの、CSSが大変なカオスになりやすい。
プリプロセッサの挙動を理解していないと作れないので学習コストが高め。

6.data属性

ピグファンタジアがデータ属性ベースのコンポーネントだった。
こういうかんじ→http://jsdo.it/Tenderfeel/3cJ5

ボタンだけでもこの有様で:
fantasia-btn

しかもピグフォントなのでボタンのテキストは全部画像。
(ライセンスの事情でWebFontは使えなかった)

製作と仕様決めが同時進行しているので、
またバリエーションが増えている!!
というのを全てのUIで何度も繰り返した結果が上のまとめ画像です。
(ピグファンタジアは全てのUIをカスタムしてたので、コンポーネントの種類もやたら多かった)

JSで値を変更することでスタイルが変わるという操作も結構あったから、
クラスよりdata属性のが便利なんじゃね?と思ってやってみたのでした。

data属性で指定するソースの例:

<div class="btn btn-add" data-color="rd" data-type="circle" data-size="xl">

クラス(BEM)ならこうなる:

<div class="btn btn-add cssbtn-color--rd cssbtn-type--circle cssbtn-size--xl">

メリット

  • JSで値の変更がしやすい(removeしなくていい)
  • (OOCSSよりは)何を指定しているのか分かりやすい
  • クラスが冗長にならない・最小限で済む
  • バリエーションが増えても対応しやすい

デメリット

  • 機能と装飾の分離?なにそれ美味しい??状態
  • HTML/CSSが冗長
  • 描画コストが高い(属性セレクタ的な意味で)

バリエーション増やすのと管理運用はやりやすかった。(と思う)
それは前述の接頭語が全くないOOCSS的増やし方よりは。という感じなので、
フルに接頭語付けたりBEMだったりと比べるとデメリットが多いように思います。

7.連番

ボタンの例だとtypeとかcolorとかオプションに名前が付けられたけど、
名前が付けられないバリエーションは連番が手っ取り早い。

今作ってるゲームでは、type-整数という命名規則にしています:

<div class="box box_type_1"></div>
<div class="box box_type_2"></div>

もっと省略:

<div class="box box1"></div>
<div class="box box2"></div>

IDセレクタを使ったスタイリングは悪か?

XHTMLが出始めの頃、tableタグ使うのが悪という風潮があったのを思い出す。

UIコンポーネント郡はクラスで作ってないと事故率が高まるが、あれ以外のパーツに関してはIDセレクタを使って困ったことがそんなにないです。
コンポーネント作りまくっていると、出来合いのを組み合わせるだけでページを作れるようになるので、結果IDの出番がなくなるという事なのかもしれないですが。

むしろここはIDのがいいんじゃないかと思うところを挙げてみる:

1.グローバルで1つしか存在し得ないUI

メインヘッダー・メインフッター・メインメニュー等。
スタイルも同じものが二つと存在しないからIDでスタイル書いても問題ない。

2.ページで1つしか存在しえない部品

ソシャゲでいうと大きいcanvasが入るところとか。

<div id="playground"></div>

3.メインレイアウトに関わる要素

<div id="wrapper">←これとか
<div id="container">←これとか

parent-childパターンを使ってみた話

ピグファンタジアは接頭語ルールに加えてparent-childパターンの命名規則を使ってました。

共通スタイル:pf-
モジュール依存:モジュール名-
コンポーネント:コンポーネント名-

共通のボタン:pf-btn
マイページのボタン:mypage-btn

メインヘッダー:main-header
パネルヘッダー:main-panel-header
ヘッダーの中のボタンコンテナ:main-header-btn-container
パネルヘッダーの中のボタンコンテナ:main-panel-header-btn-container

fantasia-source

ルート要素の名前を接頭語として子に引き継ぐので冗長になるけど、
汚染されないし何のパーツなのか分かりやすかった。
困った事はタイプ数と文字数が増えることくらいかな。

とりあえずこれくらいでどうかな…
気になる事あればtwitterとかコメントで聞いてください。