デザイナーのいないチームでのCSSの書き方

スタートアップや少人数のチームでは、デザイナー(最終的なデザインの決定権を持つ人)がいないことも少なくないと思う。 また、エンジニアだけで何かサービスを作ることも多いだろう。

僕自身、そのような環境でよく開発をする。 僕はCSSはそこそこ書けるが、デザイナーではないのでサイトのデザインについては他のエンジニアと相談しながら決定している。 IllustratorPhotoshopもほぼ全く使えないので(紙にざっくりレイアウトを書くことはあるが)、HTMLとCSSを修正しながらデザインを検討することになる。

CSS書きました。」

「うーん、ここのコンテンツはもっと大きく表示させたい。色ももっと目立つ感じで。」

「なおしました。」

「うーん、やっぱり微妙かも。試しにここ2段組にしてみて。」

「」

なんてことになる。

今更言う必要はないと思うがCSSの設計は非常に脆く、アドホックな修正を繰り返したCSSはすぐに破綻する。 この、デザイナーのいないチームで、いかにCSSを書いていくか。 考えていることをまとめてみた。

SGDD: Style Guide Driven Development

スタイルガイド駆動開発(SGDD)という言葉がある。 これは、Webサイトを作るときに先にデザインの共通部分を見つけ出し、コンポーネント化し、構造化されたHTMLと合わせたスタイルガイド作っておくというものだ。 SGDDをすることで、UIが一箇所にまとまり、再利用や調整が楽になる。 また、OOCSSやSMACSSのようなCSSの設計手法を適用しやすくもなるだろう。

しかしSGDDは、Webサイトのデザインが予め決定していないといけない。 なので、冒頭に書いたようなデザインの決定権を誰も持っていないチームでは導入することはできない。

汎用クラス

デザイナーのいないチームでどうやって上手く、CSSを書いていくか。 僕は汎用クラスをたくさん書くのがいいと思っている。

CSSにおける汎用クラスというのは、下記のような単一のプロパティで定義されてたルールセットのことである。

.bk-gray {
  background: #eee;
}
.text-center {
  text-align: center;
}
.pdr-10 {
  padding-right: 10px;
}
.font-lg {
  font-size: 22px;
}

この汎用クラスのメリットは、急なデザインの変更が必要なときに、その都度そのためのルールセットを定義しなくても、汎用クラスの組み合わせで対応できるということだ。 paddingやmarginを細かく汎用クラス化しておくことで、レイアウトの修正が楽になる。 これらの汎用クラスが大量に定義されてあるBASSCSSというCSSフレームワークツールキット)もある。

しかし、すべてのスタイルを汎用クラスを使ってあてると、それはHTMLのstyle属性に書いているのとほぼ同じで、管理しにくくなるだろう。 セマンティックを損ねることにもなる。 汎用クラスを多用するのは、デザインが決定するまでが良い。

@extendとplacehoderセレクタ

汎用クラスを多用すると、管理が難しくなり、セマンティックさが低下する。 デザインが決定したら、汎用クラスまみれのコードをリファクタリングする必要がある。

リファクタリングの方法として、Sassでいう@extendと、placeholderセレクタを使うのはどうか。 まず、作った汎用クラスを全てplaceholderセレクタに置き換える。

%bk-gray {
  background: #eee;
}
%text-center {
  text-align: center;
}
%pdr-10 {
  padding-right: 10px;
}
%font-lg {
  font-size: 22px;
}

そして、これらを継承した新しいルールセットを定義する。

.content-box {
  @extend %pd-20;
  @extend %bk-gray;
  width: 480px;
  ...
}

このようにすることで、作った汎用クラスを意味のあるまとまりとして再定義することができる。 リファクタリングとしてこれでいいのかは微妙だし流行りの理想的な設計とは異なるかもしれないが、応急処置的には十分な気がしなくもない。

まとめ

  • デザイナーいるならスタイルガイド駆動開発良い
  • デザイナーがいないとOOCSS等のCSS設計パターンに当てはめるのきつい
  • 汎用クラスの量産で細かいデザインの修正に耐える
  • @extendで汎用クラスをまとめて意味を持たせる

CSSのマルチクラス設計の問題点

CSSのルールセットを細かく(classセレクタで)定義し、HTMLに複数のclass属性値を書いてスタイルをあてるような設計をマルチクラス設計と言ったりする。 マルチクラスにすることで冗長な記述が減り、ファイル容量が減り、ルールセットの再利用性が高くなり、保守性が向上する。

OOCSSをはじめとしたCSSの設計概念はマルチクラスを前提としており、Twitter Bootstrap等の多くのCSSフレームワークはマルチクラスでスタイルをあてるようになっている。

<!-- Twitter Bootstrapのボタンの例 -->
<button class="btn btn-primary btn-lg">Save</button>

良いことしかないように見えるマルチクラス設計だが、いくつか問題点もある。

まず、HTMLに複数のclass属性値を書くと共通するプロパティが上書きされるということ。 当前のことだが、共通するプロパティがあった場合、カスケーディングされ詳細度が高い方のルールセットのプロパティが適応される。

そして、ルールセット間に暗黙の依存関係が生まれること。 上記のTwitter Bootstrapの例だと、btn-primarybtn-lgbtnと同じ要素に書かないと行けない。 僕も初めてBootstrapを使ったときにbtn-primaryだけ書いてアレ?ってなったことがある。

今流行りのOOCSSっぽいマルチクラスなCSSの設計手法をとろうとすると、書いた人以外には見えないルールセットの依存関係が存在するので分厚いスタイルガイドが必要になってくる。

僕は、CSSの容量を少しでも削らないといけないほどパフォーマンスにシビアでない限り、Sassでいう@extendを利用したシングルクラスな設計の方がいいと思っている。 HTMLもよりセマンティックにできる。

%btn {
  display: inline-block;
}

%btn-md {
  padding: 5px 10px;
  font-size: 14px;
}

%btn-blue {
  color: #fff;
  background-color: #3071a9;
  border-color: #285e8e;
}

.save-btn {
  @extend %btn;
  @extend %btn-md;
  @extend %btn-blue;
}

また、SassやStylusよりも安全にルールセットの継承ができるYACPというCSSプリプロセッサーがある。

YACPを使ったextendによるシングルクラスな設計、小中規模なWebサイトでスタイルシートの複雑性を削減し、保守性を担保するのに最高感ある。

CSSポストプロセッサーの必要性

PostCSSというかCSSのポストプロセッサーにいろいろ思うところがあったのでツイートしたら、作者のai氏からリプライ来て震えた。

ai氏はベンダープレフィックスを自動で付与するツールAutoprefixerを作ってる人。 Autoprefixerはもともとreworkというプリプロセスを定義するフレームワークを使ってたけど、Autoprefixerがやってることはプリプロセスっていうよりポストプロセスじゃね?って考えてreworkとほぼ同機能のPostCSSを作ってそれに乗り換えた。

PostCSSは、CSSのポストプロセスを定義するためのフレームワーク。 僕はPostCSS自体はCSSをパースしてごにょごにょするための便利なAPIが備わっていて良いものだと思っている。しかしポストプロセスという概念が微妙だと感じている。

PostCSSの登場により、いくつかのポストプロセスのためのプラグインが作られた。 今はまだ数はすくないけど、中にはpostcss-varsのような本来はプリプロセスでするべきものもある。

CSSに対するどのような処理がプリプロセスなのかポストプロセスなのか、境界が曖昧になっている。 個人的には、minifyやconcat、CSScombのようなプロパティの順序を入れ替えるものをポストプロセスと定義すべきだと思う。 いや、ポストプロセスという言葉も使わない方がいいかもしれない。 JavaScriptでもminifyやconcatはするが、それをポストプロセスと呼ぶことはない。 CSSの場合はプリプロセスという言葉があったから、ポストプロセスという名前になっただけだ。

だからAutoprefixerはポストプロセスではないと思うし、現に僕が作ってるCSSプリプロセッサーではコンパイル前にAutoprefixerを使っている。 コンパイルされた結果に何か処理を加えたいと思うのはコンパイラプリプロセッサー)に問題があるので、プリプロセッサーを良い方向に持っていく方が健全だ。

CSSプリプロセッサーとポストプロセッサーについてはもっと考えをまとめられたらまたブログに書こうと思う。


ai氏との会話の続き

せっかくリプライもらったしこれでもかと絡んでみた。 ai氏もプリプロセッサーとポストプロセッサーに分けるのは良くないから新しい説明考えるよって言ってた。

拙い英語に付き合ってくれて、ai氏いい人だった。 日頃から英語勉強しとかないとやばいと思った。

CSSセレクタの名前を付けるときに考えていること

idを使うときも同じだけど、話をわかりやすくするためにclassに統一するということで。 個人的にはセレクタにidは使わない派です。

先日、@cssradarさんが「自分の仕事はclass名を決めた時点で8割終了している」みたいなことを言ってて、僕も概ね同意している。 それほどにCSSでは命名が大切だと思う。 そこで僕が普段どう考えてCSSセレクタに名前をつけ、ルールセットを定義しているのか書いてみた。

1. class名は意味を表すようにする(見た目の情報をのせない)

例えば、以下のようなもので

.red {
  color: #f52;
}

.rounded {
  border-radius: .25rem;
}

.left-arrow {
  ... 
}

赤色だとか角丸だとか、見た目を表したclass名は付けないようにしている。 というのも、class名はHTMLのclass属性に書くもので、HTMLには論理構造だけを書きたいからだ。

HTMLの要素を視覚的に強調させる意味で.redという名前になっているなら、.emphasisとかにするし、もしエラーの意味があるなら.error等にする。 Twitter Bootstrapの色も、赤は.dangerだったり、緑は.successだったりする。

.roundedもコンテンツが入るボックスを角丸にしたいのなら.content-boxの中にborder-radiusを書くべきだと思し、.left-arrowについても、戻るボタンを意味しているなら.back-btn等にする。

また、.roundedはSassで言うところの@extendのような、ルールセットを継承する機能を持つプリプロセッサーを使っているなら、

%rounded { 
  border-radius: .25rem;
}

.content-box {
  @extend %rounded;
  ... 
}

このようにしても(した方が)いいと思う。 HTMLのclass属性に書かれないセレクタには見た目の情報が入っていてもいいし、こうすることでSassファイル内での再利用性が高まる。

2. 全く同じスタイルでも意味、用途が違うなら違う名前にする

例えば、Twitter Bootstrapを使ってたりすると、赤いボタンは全て.btn-dangerにしがちだと思う。 同じ赤色のボタンでも、強調させたいから赤色にしているボタンには.btn-emphasis、削除ボタンには.btn-dangerとすべきだと思う。

たまたま、見た目(この場合は色)が同じであっても、意味や用途が異なるなら別に名前を付け、セレクタをわけるべきだと思う。

.btn-danger,
.btn-emphasis {
  background-color: #f52;
}

これはHTMLに正しく意味を記述するということでもそうだし、もし後で「強調させているところの色はオレンジにしよう」となったとき等にデザインの修正に耐えやすい。

最後に

かなり細かいことを書いたが、真にHTMLとCSS疎結合にし保守性を保つためには大切なことだと思っている。HTMLとCSSをただ別ファイルに書くだけで構造と体裁を分離することはできない。

あと、僕は主にWebサイトのHTMLとCSSを書くことが多いので上記のことを気をつけているが、アプリケーション(WebViewのスマホアプリとか)を作ってたりするとこのようにしない方がいいかもしれない。

時と場合によるCSS記述の良し悪しを評価できるようなものを作りたい。

スタイルガイドジェネレータを自作した

Cheatahというスタイルガイドジェネレータを作った。

スタイルガイドというのはスタイルシート仕様書みたいなもので、HTMLにどのようなclass属性(またはid)を書くとどのようなスタイルが適用されるのかが書かれているもの。例えば、GitHubのStyleGuideTwitter BootstrapのCSSのページがそれにあたる。そして、スタイルガイドジェネレータというのは、スタイルガイドを自動生成してくれるもので、StyleDoccoKSSが有名。

Cheatah

Cheatahの特徴は、既存のスタイルガイドジェネレータよりも気軽にスタイルガイドを作れることである。

StyleDoccoやKSS使う際、スタイルガイドとして作りたいHTMLをCSS(もしくはプリプロセッサ)にコメントとして記述しなければいけない。 Cheatahではそのようなコメントを一切書かずにスタイルガイドを生成できる。 使い方はGitHubリポジトリREADMEに書いてある。

開発者同士の円滑なコミュニケーションのためにスタイルガイドは作りたいが、いちいち丁寧にコメント書くのはめんどくさいし、簡単なものでいいからもっとカジュアルに作りたいというモチベーションからCheatahは作られた。

しかしCheatahでは、colorborder-radiusfont-familyなどの装飾を施すプロパティを含むルールセットのガイドしか生成できない。 marginfloatなどのレイアウトのためのプロパティは、HTMLの構造に依存するので、StyleDoccoのようにコメントでHTML(Markdown)を書いてやらないといけない。 今はこの点をどうにか解決できないかと模索している。

スタイルガイド

上述したように、スタイルガイドは開発者の円滑なコミュニケーションのために必須だと思っている。 特にCSSを書く人が複数人いるような場合だと、誰がどんなルールセットをどのように定義しているのかを共有する必要がある。何も考えずに各々がそのページで必要なスタイルを独自に定義していくと、冗長で再利用性が低く、CSSファイルの容量は膨れ上がりロードに時間がかかる。

またCheatahでは、そのルールセットがどのように書かれているのかを確認することもできるので、開発者同士でCSSのコードのレビューをすることもできる。

CSSは、ただWebのビジュアルデザインを表現できれば良いというものではなく、他のプログラミング言語と同様に保守の対象であるべきである。 その後のメンテナンスを助けるという意味でも、スタイルガイドは作るべきだと思う。

さくらVPSを解約した

先日、2年弱ぐらい利用していたさくらVPS(メモリ1GBのやつ)を解約した。 支払い分が残っているので、6/20(?)まではまだ使えるらしい。

VPSで動いてるのは、もう1つのブログとプログラミングを初めた頃に作った黒歴史ぐらいだ。 別に何かちょっとしたサービスを運用しているわけでもないし、毎月1000円払うのもなって思ったので解約した。 このブログはもう更新するつもりはないけど、GitHub Pagesに置いておくかもしれない。

今思うと、2年前VPSを借りたときもサービスを運用したいという理由で利用し始めたわけではなかった。 ただプログラミングを勉強するためのLinuxの開発環境が欲しいだけだった。 借りたVPSにCent OSをインストールし、PHPApacheMySQLをインストールして、SSHでログインしてサーバーで直接簡単なWebアプリを書いて遊んでいた。

今は開発環境は、Railsだとローカルサーバーを簡単に立てられるし、VagrantとかでVM立てたりするようになった。 それに、最近は個人でサービスを作りたいという気持ちがなくなりつつある。もし作ったとしてもとりあえずはherokuとかにpushしとけばいいし、ちゃんと運用していくことになったらAWSを使うと思う。

今のこの便利なご時世、新規にVPSを借りて何かすることはないんじゃないかなと思った。

ゴールデンウィークで作ったもの

mizchiさんの記事に触発されて書いた。

ゴールデンウィーク中は、Nodeのモジュールを4つほど勢いで作って遊んでた。

つくったもの

grunt-yacp

https://github.com/morishitter/grunt-yacp

前に作ったCSSプリプロセッサーコンパイルするGruntプラグイン

magicn

https://github.com/morishitter/magicn

CSS内でマジックナンバーが使われていたら、「あるよ!」って言ってくれる。 今はこれだけ。YACPで使おうと思って作った。

css-unit

https://github.com/morishitter/css-unit

CSSのvalueで使われている単位(unit)を分析するツール。 magicnのコアモジュールとして使ってる。

magicnとcss-unitはもっとなんとかしないといけない。

colored-tape

https://github.com/morishitter/colored-tape

npmマイスターのsubstack氏が作った、tapeっていうテストフレームワークがある。 tape、シンプルで良さそうだったので最近使ってるんだけど、出力に色が付いていなくて脊髄反射のレベルでテストが通ってるのかどうかわかりづらかったから作った。 やっぱりテストが通ったら「オールグリーン!テストクリア!」って叫びたい。

読んだ本

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

今まで我流でJSを書いてたので読んだ。他の言語を経験している人が初めてJSを書くときに読むといい感じの本だった。

開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質

開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質

こっちはまだ半分ぐらいしか読んでないけど、僕にはこの本の方が発見が多かった。

最後に

ゴールデンウィークって言っても、毎日が休みみたいな学生にとっては普段の日常と特に変わらない。 モラトリアム!モラトリアム最高!

社会人の皆様、また今日からお勤めがんばってください。