CHROMA

世の中の "当たり前" を確認する

スタイルは適度に小さく正確に

CSS Architecture Advent Calendar 2014 の12日目。

SMACSS や BEM など、去年のように新しい CSS の設計手法は今年学ぶ機会が作れなかった。その代わり、いくつかのサイトを作る中で気づいたことや、自分なりに気にかけたことがあるのでそれを書いておこう。

コードを載せたら少し長くなってしまったので、ページ内リンクを貼っておく。

CSS を書く以上はプロパティや値の扱いを軽視することはできない。もしかしたら設計の話からは逸れているかもしれないが、2つ目と 3つ目ではプロパティや値に注意して書くことで予期した結果が得られるというようなことを書いた。

要素本体と変化しやすいスタイルを分ける

基準となるものは除いて、配置場所によって内容が変化しやすいスタイルは主要なスタイルと切り離しておいたほうが良さそうだ。

そして、"変化しやすい" スタイルと聴いて思い浮かぶのはサイズや余白ではないだろうか。

これらの指定をモジュールの派生クラス( Modifier )として扱ってしまうとクラスはどんどん数を増していく。

サイズの変更だけでも、ボタンなら .btn--small, .btn--large, .btn--small-x, .btn--large-x... と増えていくことになるだろう。

また、余白に関してはボタンそのものの大きさや周囲の要素を考慮しながら変更する必要が出てくる。これもまた多くの派生クラスを生むだろう。

つまり、このようにクラスが増える。

.btn { ... }
.btn--small { ... }
.btn--small-x { ... }
.btn--small-xx { ... }
.btn--small-xxx { ... }
.btn--large { ... }
.btn--large-x { ... }
.btn--large-xx { ... }
.btn--large-xxx { ... }
... /* このあとに余白に関する派生クラスが続く */

個人的にこれはあまり好ましくないので、ボタンやアイコンを定義したモジュールでは色や画像ソースの指定と基準となるサイズの指定にとどめ、サイズを変更したり余白を加えたい場合はそれ自身が置かれるモジュール内で定義したほうが良いと思う。

このように:

/* button */
.btn {
  box-sizing: border-box;
  display: inline-block;
  text-decoration: none;
  cursor: pointer;
}

.btn-primary {
  border: 1px solid #519bf2;
  background-image: linear-gradient(180deg, #73aff4, #519bf2);
  background-color: #519bf2;
  font-weight: bold;
  color: #fff;
  text-align: center;
  text-shadow: 0 1px 0 rgba(0,0,0, .2);
  box-shadow: inset 0 1px 0 rgba(255,255,255, .2), 0 2px 2px rgba(0,0,0, .2);
}

/* box */
.box {
  overflow: hidden;
  padding: 1em;
  border: .1em solid #eeefef;
  background-color: #fcfcfd;
}

.box__text {
  float: left;
  margin-top: 0;
  margin-bottom: .5em;
}

.box__button {
  float: right;
  padding: .25em 1.25em;
}

尚、要素本体の存在はそれ自身だけで成り立つことも重要だ。上の例でいうとボタンは最低限それがボタンであるとわかるスタイルを振っておく必要がある。

スタイルを分ける際には「基準と異なるサイズと余白、配置の指定だけ」のように、ある程度ルールを決めておいても良いかもしれない。

表現したい内容を正確に表す

例えば要素を円形にするクラスを定義するとき、border-radius の値は要素に対して半分の値を適用すれば思い通りの結果になる。

しかし、40 * 40 の要素に border-radius: 20px を適用すれば、これは 40 * 40 以下の要素でしか効果が発揮されない。

.circle {
  border-radius: 20px;
}

「要素に対して半分」というのを 50% という値で指定するとどうだろうか。

.circle {
  border-radius: 50%;
}

同じクラスを使って要素を円形にするという目的が果たせたのがわかる。

少し例が悪かったかもしれないが、これは何もピクセルの指定を一切使うなと言ってるわけではないし、ヘルパークラスを増やすことを目的としているわけでもない。

プロパティに値を指定するときは、自分が表現したい内容を正確に表すのが重要だということが言いたかった。

ショートハンドは少なめに

初めから要素に当たっているスタイルの打ち消し・上書きは、それを適用したい箇所に対してのみ行うようにしている。

プロパティが重複したときがつらいというのと、ショートハンドの指定を覚えるのが面倒なのが理由だ。

次のような場合、後から指定した background プロパティが前のものを上書きしてしまう。結果、background-image やその他の指定は初期値に戻されるので画像は表示されず、.image-bg で指定した背景色だけが表示される。

.image {
  width: 36px;
  height: 36px;
  background: url(data:image/png;base64, ...) center center / 75% 75% no-repeat;
}

.image-bg {
  padding: 5px;
  background: linen;
}

以下のように書くことでこの問題は避けられる。多少手間が増えても、分けて書いたほうが予期せぬ結果を生まないので良い。

.image {
  width: 36px;
  height: 36px;
  background-image: url(data:image/png;base64, ...);
  background-position: center center;
  background-size: 75% 75%;
  background-repeat: no-repeat;
}

.image-bg {
  padding: 5px;
  background-color: linen;
}

状況にもよるけど、僕がショートハンドを使って書いてるのは border と全方向の指定をする margin および padding くらいだと思う。