HTML(情報設計)はCSSより優先して考えよう|CSSリファクタリング実例

2016年7月13日

テクテク関西で、「連載モジュールデザイン」と題して、デザインとWebについての関係性を整理していっております。
その中で軽く、情報設計はグラフィックよりも優先度が高いことについて触れておりますが、今回はその点についてリファクタリング実例をみながら考えていこうと思います。

 

いいHTMLと、いいCSSって何だろう

「UIデザイン再考――UIデザインの3要素と仮説精度」で、作業工程からみる情報設計とグラフィックの分類などについて書いておりますが、コーディング上はざっくりと「情報設計 = HTML」「グラフィック = CSS」ということができます。「imgタグで呼び出すのは画像だからグラフィックだ!いや、画像自体が情報を含んでいるから情報設計だ!」みたいな話をしはじめると泥沼になりますので、細かいところは皆さんの職場の同僚とかと議論して下さい(笑)

では、リファクタリング実例をみる前に、いいHTMLといいCSSについて見てみましょう。
 

いいHTMLとは

いいHTMLとは、すなわち「情報設計がしっかりされている」HTMLです。
 
皆さんがお使いの各ブラウザには、デフォルトである程度標準的にHTMLタグについてデザインがあたっております。例えば、<blockquote>を使うと、標準でpaddingが設定されてたり、左に線をひかれたり。<ul>を使ったら、list-style-typeが初期設定されておりますし、<th>だったら太文字になったりします。<h1><h2>などについては言うまでもないですよね。
ちなみに、それがブラウザ毎にちょっとずつ差があるので、resetCSSを使わないと「Chromeではちゃんと表示できるのに、Safariでは表示が崩れる!」みたいなことが起きたりするんですよね^^;
 
話は外れましたが、悪いHTMLというのは、そのデフォルトデザインのためにタグの意味を無視したコーディングによって生まれます。
 
例えば、左右にカルムを用意するとします。見た目だけの問題だったら、<table>を使って、右と左にカルムスペースもつくることができるのです。しかしながら、<blockquote>はテーブル構造を意味するタグですので、本来の意味を無視しています。アンチパターンです。
<br>によるデザインもアンチパターンに該当します。<br>は、改行を意味するタグであって、デザイン上マージンをとる意味を持っていないからです。
 
当然ながら、項目を書く時は、以下の通りですよね。

// アンチパターン
・その1
・その2

// 正しい
<ul>
  <li>その1</li>
  <li>その2</li>
</ul>

 
ですので、HTMLを覚える時は、「ブラウザでどう表示されるか」ではなく「どういう文章構造上の意味を持つのか」を意識することが大切です。
まぁ、ここらへんは、Webアクセシビリティと組み合わせて学習するのがいいのではないでしょうか。Webアクセシビリティのために、読み上げソフトに完全対応!みたいな話ではなく、文章構造がしっかりしていれば、文章構造を読み取って、意味を解釈できるHTMLになるので、おすすめです。
 

いいCSSとは

「モジュールデザインのすゝめ――CSSから逆算してデザインを考える」で軽くご紹介しておりますが、これは言い出すときりがないといいますか、それだけで書籍が執筆できてしまいます(笑)。
そういう意味で、CSS設計論(可読性とか、拡張性とか)についてのあれこれはここではふれずに、HTMLとの関係性で「いいCSS」について書きますと、
 

  • HTML(文章構造)に極力手を入れない

 
かなと思います。 
例えば、以下の2つは同じものを表示しますが、アンチパターンでは全てのliにclassをつけないといけません。それに対して、前者はulにつけたら終わりです。
 

// アンチパターン
<style>
  li.red {
    color:red;
  }
</style>
<ul>
  <li class="red">その1</li>
  <li class="red">その2</li>
</ul>

// まだまし
<style>
  ul.red li {
    color:red;
  }
</style>
<ul class="red">
  <li>その1</li>
  <li>その2</li>
</ul>

 
まぁ、もうちょっといいますと、CSSの名前に意味を持たせることができる方がいいですよね。そうすると、CSSのためにHTMLにclassをつけるのではなく、HTMLの可読性を高めるためにclassをつけて、それにCSSを当てることができます。
 

// 正しい
<style>
  ul.red-label-list li {
    color:red;
  }
</style>
<ul class="red-label-list">
  <li>その1</li>
  <li>その2</li>
</ul>

 
CSSを当てるためには、HTMLのセレクター、親子関係、id、classを用いますが、CSSのために親子関係を複雑にしたり、id、classをたくさん書くのは最小限にすべきであり、CSSをどこまでHTMLに対して従属関係におくことができるかというのが「良いCSS」ではないでしょうか。
 

実例のリファクタリングから良いコードを考える

コードの経緯

Twitterで、 @sakanatechさんが以下のようにツイートしまして、それのやりとりをしたあとで私が酒のみながら「リファクタリングしてみるかー」と思って書いたというのが次第です。

 
で、リファクタリングした時のツイート。

 

リファクタリング前のコード

最初のコードがこちら。直接CodePenからみた方が読みやすいと思います。
全体的に、CSSの都合でHTMLにclassを振ってる感じ。あと、縦項目の中に横項目があるのに、なぜか縦項目は<div>で括られたりしていました。 
あとは拡張性ですね。縦項目の<div>に、.diamond1,.diamond2,.diamond3と振ってあるのですが、このままだと「もう一行増やすことになった」とかあったら、.diamond4,.diamond5とHTMLサイドにclassを振った上で、CSSに書き足さないといけない状態だって、全く拡張性がない状態でした。縦項目もnth-child(2)とかでひとつずつ指定されてるから、一列足す、とかなったら悲惨。
 
なので、そこあたりを基本方針にリファクタリングしてみました。
 

See the Pen DiamondCat by lyca (@sakanatech) on CodePen.

リファクタリング後のコード

まず、HTML側のclassをごそっとなくしました。具体的には、縦項目のulに.list-image-degをつけた以外、構造に関してはclassを全てなくしています。
CSSは、使い回しを考えて組んでいきますが、この縦横項目については「中のどっかのパーツを抜き取って使い回す」ということはないと考えた結果です。大本のulさえ指定できたら、あとは縦横項目の構成なので親子関係と擬似要素だけで指定できますし。
また、擬似要素については、nth-child(2)とかで番号を指定するのではなく、奇数の出現(nth-child(odd))と、あとは最初の出現時のみの指定に変更しました。このことによって、縦行・横行がどれだけ増えても対応できるようになるからです。これは拡張性に資する部分ですね。
 
あとはfloatでのレイアウトをやめて、display:flex;に入れ替えたあたりが大きな変更ですが、具体的なところについてはコードを見比べていただければと思います。
 

See the Pen DiamondCat by Masahiko Sakakibara (@rdlabo) on CodePen.


 

まとめ

大体、私がコーディングする際は、

  • 可読性
  • HTMLだけで意味が通るか
  • 拡張性をどれだけもてるか
  • どれだけ使いまわせるか
  • どれだけ少ないコードで表現できるか

あたりを考えている感じです。ご参考になりましたらー。
といいつつ、まぁコーディングに正解はありませんし、私のやつも「いやいや、こう書こうよ!」はまだまだあるかと思います。つっこみ、Forkして更なるリファクタリング、お待ちしておりますー。
 
それでは、また。