CSS の書き方についてのメモ

Category : CSS

どんな感じで書けば楽できるかとか、後から修正しやすいかとか、そんなことです。
ボタンのスタイリングを例に、自分の通った道を追ってみます。

左から、緑色の編集ボタン、青色の公開ボタン、赤色の削除ボタンが並んでいます

今回使う HTML は次のようになっています。

<div class="buttons">
  <button class="edit">Edit</button><button class="publish">Publish</button><button class="delete">Delete</button>
</div>

これを CSS でスタイリングしていきます。

1. とりあえず個別指定

こんな極端な書き方する人はあまりいないでしょうけど、例として。

.edit {
  margin: 0 5px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  width: 6em;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  background-color: #2cad15;
  background-image: -webkit-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -moz-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -o-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  color: #fff;
  font-size: 100%;
  font-family: inherit;
  line-height: 1.6;
  text-align: center;
  text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}

.publish {
  margin: 0 5px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  width: 6em;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  background-color: #268bd2;
  background-image: -webkit-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -moz-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -o-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  color: #fff;
  font-size: 100%;
  font-family: inherit;
  line-height: 1.6;
  text-align: center;
  text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}

.delete {
  margin: 0 5px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  width: 6em;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  background-color: #dc322f;
  background-image: -webkit-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -moz-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -o-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  color: #fff;
  font-size: 100%;
  font-family: inherit;
  line-height: 1.6;
  text-align: center;
  text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}

各セレクタの宣言ブロックに同じ行がいくつもあります。
読みづらいし編集も大変だし、ファイルサイズも増えます。

これをどのように変更していくか、です。

2. 共通部分をまとめる

.edit,
.publish,
.delete {
  margin: 0 5px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  width: 6em;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  background-image: -webkit-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -moz-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: -o-linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255 ,255, 255, 0));
  color: #fff;
  font-size: 100%;
  font-family: inherit;
  line-height: 1.6;
  text-align: center;
  text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}

.edit {
  background-color: #2cad15;
}

.publish {
  background-color: #268bd2;
}

.delete {
  background-color: #dc322f;
}

共通部分を一つの宣言ブロックにして、セレクタをまとめて1つのルールセットにしました。
かなりすっきりしたと思います。

急にボタンを追加することになって「Private」ボタンが増えたとします。
そうすると、共通部分のルールセットに .private セレクタを追加し、個別指定部分に .private セレクタ用の宣言ブロックを追加することになります。
そのとき、CSS コードを行ったりきたりすることになります。1つだけならまだしも、3つ4つ追加されていくと大変です。
(一応、同じファイルを別タブで開いて同時に編集できるエディタもあります)

この面倒くささを解消するのに次の方法を考えてみます。

3. クラス名を増やす

共通部分のセレクタを1つにしてしまいます。

.edit,
.publish,
.delete {
  ...
}

.button {
  ...
}

といった感じです。
いわゆる OOCSS なアプローチです(たぶん)。
.button という親があり、その子たちは親のスタイルを継承しつつ、個別のスタイルを与えることができます。

ただし HTML 側にはまだそのクラス名は存在しないので、付け加えなければなりません。

<div class="buttons">
  <button class="button edit">Edit</button><button class="button publish">Publish</button><button class="button delete">Delete</button>
</div>

新しく追加するボタンの場合は

<button class="button private">Private</button>

となります。

個人的な感想ですが、この手法は HTML をスタイリングするというよりも、用意したスタイルを HTML に当てはめていくという印象があります。
便利で手軽ではあるのですが、そのクラス名が何をやっているかを把握していないと HTML が書きづらいと思います。

この方法は楽ではあるものの、HTML と CSS の関係を考えたら最終的には 2 の方法がいい。だけど書くのが面倒くさい。
ではどうするか。

残念ながら CSS だけの力では難しいと思って、Sass(SCSS) の出番となりました。

4. SCSS によるアプローチ

3 の共通部分のセレクタ .button をプレースホルダセレクタ %button にし、個別のセレクタにそれを @extend させる形となります。

%button {
  ...
}

.edit {
  @extend %button;
  background-color: #2cad15;
}

.publish {
  @extend %button;
  background-color: #268bd2;
}

.delete {
  @extend %button;
  background-color: #dc322f;
}

これをコンパイルすると、2 と同じような CSS が生成されます。

これでコードを行ったり来たりせずによくなります。新しいボタンが追加されてもルールセットを1つ追加し、@extend するだけで済みます。
HTML 側も特に変更する必要はなく、最初に書いたものを使えます。

グラデーションなどのベンダー接頭辞あたりも、mixin を用意しておけば楽に書けるのもメリットです。

ご指摘がありましたが、div.buttons button で共通のスタイルを設定するのが現実的です。
%buttons@extend するのは div.buttons button セレクタになります。
ボタンに焦点を当てすぎて忘れていました、すみません。

それと、クラス名ですが、<button class="button"> というつけ方は確かによくないですね……。
名前自体は本題ではないのでサンプルで適当につけましたが例として不適切でした。すみません。

一応言っておくと、必ずしも1要素1クラスにする必要はないと思っています。
@extend での継承が複雑になってきて自分の扱える範囲ではないと感じたら、3 と 4 の混合なんかを試しています。
また、そもそも役割の違うクラス名なら、最初から分けておいたほうが分かりやすいとも思います。

というわけで、2012年9月時点の自分の書き方のメモでした。

Trackbacks & Pingbacks

Comments

bouzuya

ぼくはSASSよりLESS( http://lesscss.org/ )の方が好きです。この記事の範囲なら好みの問題でしょうけど……。JavaScriptで実装されているので、サーバーサイド(例:Java+Rhino)で変換だけでなく、クライアントサイドで変換なんてことも簡単にできて素敵です。

Leave a Reply