HTMLとCSSの記述順序を意識することはデザイナーとの対話をなめらかにするという話


みなさんは記述順序を意識していますか?

こんにちは。ひらやま(@rhirayamaaaan)です。

さて、唐突ですが、Twitter でこんな質問をしてみました。

みなさんはどの記述スタイルに当てはまりそうでしょうか?
(3つ目の書き方をしている人はなかなかいないとは思いますが…笑)

ちなみに私は2つ目の書き方派です。
この質問をした意図は、案外1つ目の書き方の人が多いのでは?という素朴な疑問を抱いたからでした。

アンケートの結果を見ると2つ目を選んでいる人が多く、私も同じ考えを持ってはいて、そうだよねと思ったのですが、なぜ2つ目の書き方が良いと思っているのかを自分の中で言語化できていないことに気づきました。

なので、今回は私なりになぜ「HTML をある程度書き切ってから CSS を書く」のが良いかをここに記していきます。

HTML はあくまでも「骨組み」

HTML はマークアップ言語なので、そもそも UI デザインを再現する言語ではありません。
HTML5 が登場によって UI デザインの再現の責務をより負わなくなったと感じます。
新しいタグが登場し、今まであった HTML タグに明確な意味が付与され、より「文書設計」に特化した印象でした。
これにより「セマンティクス」という言葉がかなり浸透したのではないでしょうか。

このように、HTML は「文書設計」に長けた言語であるので、言い換えると、情報を整理することにとても長けている言語なのだろうと私は思っています。

UI デザインから「情報設計」を紐解く

さて、デザイナーからデザインデータが上がってきて、いざコーディングしようとしたとします。
そのときに、「このデザインを再現しよう」と HTML と CSS を記述していく方は案外多いのではないでしょうか?
私はこの考えはあまり良くないだろうと考えています。

「このデザインを再現しよう」と考えてしまうと、「どのように横並びにしようか?」とか「どうしたら余白が空くだろうか?」というように、見た目ばかりを気にしてしまいます。
そうなると、情報を整理することに長けている HTML を、見た目ばかりに関心を寄せて書くことになってしまい、言語の特徴と記述の姿勢に齟齬が生まれた状態になります。
では、この齟齬はどのようにすればなくしていけるのか…?

Qiita の私のマイページから一部 UI を抜粋してみました。
このデザインを見てみると、タグ、タイトル、LGTM数、日付の情報があります。そして、文字に強弱がついていて日付が右付きになっています。

ここで一つ疑問に思うべきは「なぜこのデザインになっているか?」です。
デザイナーはなんとなくこの見た目にしているかというと、それは絶対にないです。
表示する情報のヒエラルキーを決め、情報をグルーピングし、情報の依存関係を考慮した上でこのリストがデザインされているはずです。
つまり、UI は情報設計が表現されているはずなのです。
そして、今我々が書こうとしているのは HTML です。
ということは、UI の情報設計をうまく読み解ければ、情報を整理することに長けている HTML にうまく落とし込めるのではないか?と考えることができます。
UI デザインの情報設計を HTML で表現していくという考え方にすれば、齟齬がなくなっていくはずです。

このことを踏まえた上で、上記の UI を勝手に HTML にしてみました。
(BEM で書きます。Qiita の実際のコーディングとは異なります。)

<div class="articleList">
  <ul class="articleList__items">
    <li class="articleList__item">
      <ul class="articleList__itemTags">
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">HTML</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">CSS</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">HTML5</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">CSS3</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">フロントエンド</a>
        </li>
      </ul>
      <p class="articleList__itemTitle">
        <a href="#" class="articleList__itemTitleLink">HTML/CSSをもう少し極めたいデザイナー/エンジニアに伝えたい「3つ」のこと</a>
      </p>
      <div class="articleList__itemStatus">
        <div class="articleList__itemState">
          <span class="articleList__itemLgtm">45</span>
        </div>
        <div class="articleList__itemState">
          <span class="articleList__itemDate">2019/01/06</span>
        </div>
      </div>
    </li>
    <li class="articleList__item">
      <ul class="articleList__itemTags">
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">JavaScript</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">UI</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">React</a>
        </li>
        <li class="articleList__itemTag">
          <a href="#" class="articleList__itemTagLink">AtomicDesign</a>
        </li>
      </ul>
      <p class="articleList__itemTitle">
        <a href="#" class="articleList__itemTitleLink">Atomic Designってデザイナーには難しくない!?という話</a>
      </p>
      <div class="articleList__itemStatus">
        <div class="articleList__itemState">
          <span class="articleList__itemLgtm">467</span>
        </div>
        <div class="articleList__itemState">
          <span class="articleList__itemDate">2018/07/30</span>
        </div>
      </div>
    </li>
  </ul>
</div>

hx やセクショニングコンテンツを使っていない理由は、ページ上でのモジュールの配置位置や、前後のモジュールの関係性、モジュール内部の保守による情報ヒエラルキーの可変等々を考慮したためです。

いかがでしょうか。まずはデザインを再現できるかどうかではなく、UI から情報の粒度やグルーピングを見極め、HTML のみで表現してみました。

element(__xxx) の命名にも lowerCamelCase を使っていて、これはどの親 element の子として扱うかを示しています。

例えば、__itemDate__itemStatusDate にしていない理由は、__itemStatus の中にいなくても、__itemDate 自体は要素として独立しているからです。
あくまでも今回の UI では __itemStatus というグループの中に __itemDate を入れているだけであって、新たに __itemInformation というグループができたとしても __itemDate の意味合いは変わらないためこのような命名にしています。

それとは逆に、__itemTitleLink__itemTitle の子として定義しています。
これを __link にしてしまうと、このモジュールの中で「もっと見る」リンクができた場合に扱いに困ります。
また、__itemLink にしたとしても __item の中には、__itemTag の中にもリンクがいるので、別のリンクであることを示さないといけません。
そのため、このリンクは限定的に定義しています。

このように、情報の依存関係やグループ等々の設計を捉えていきながらこの block の HTML を組んでいます。
このような姿勢で HTML を組むと、デザイナーの情報設計の意図を把握しやすくなり、作っているモジュールのデザイン的な理解に大きく繋がるはずです。

骨組みにスタイリングしていく

ここでようやく、情報設計を考慮して作った HTML に CSS をあてていきます。
上記のように HTML を作っていれば、実は CSS はかなり楽に記述できるようになっています。
何個か CSS の例を挙げていきますが、その前にもう一度 UI のキャプチャを貼ります。

このキャプチャのデザインを再現していくにあたり、以下より CSS の適用例を示していきます。
HTML を変えずに CSS を適用できていく過程を、読みながら体験してもらえたら嬉しいです。

記事ごとの border

一つひとつの記事は articleList__item という形で同じ名前が振られているので、border を引きたい場合は以下のようにスタイルを当てれば終わりです。
情報の粒度があっているので、隣接セレクタも使いやすくなります。

.articleList .articleList__item {
  border-top: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
}

/* 隣接したときだけ相殺し、ボーダーが重複しないように調整 */
.articleList .articleList__item + .articleList__item {
  margin-top: -1px;
}

タグの実装

タグは横並びにしないといけませんが、__itemTags というグループができてるので、これを使って横並びにすれば OK です。
flex でも inline-block でも問題ありません。このご時世だとなかなかいないとは思いますが float でも HTML は変えずにいけます。笑
例では flex で書きます。

.articleList .articleList__itemTags {
  display: flex;
  flex-wrap: wrap;
  /* 子要素の margin を相殺 */
  margin: -4px 0 0 -4px;
}

.articleList .articleList__itemTags {
  display: inline-block;
  /* 要素が折り返したときのための指定 */
  /* margin-right で指定すると、折返し判定が早くなるため左でとって親で相殺する */
  margin: 4px 0 0 4px;
}

要素間のマージン制御

タグとタイトルの余白を取りたい場合、タグの有無によってタイトルの上に margin をつけるか否かの制御が必要になります。
その場合も、タグとタイトルで情報の粒度を同じにしているため、以下のようにスタイリングをすれば良いです。
(Qiita の実装では margin はありません。あくまでも例です。)

.articleList .articleList__itemTags + .articleList__itemTitle {
  margin-top: 4px;
}

このように情報の粒度を意識できていれば、__itemTitleLink に margin をつけると違和感が生まれるはずです。
タグとタイトルの余白を取りたいわけで、リンクの余白を取りたいわけではないので、余白の意味に対しての認識がデザイナーとあってくるはずです。

また、情報の粒度を揃えておくと、margin と padding の取り方もわかりやすくなってきます。
今回は、意味合いの違う要素間の余白(外側の余白)なので、margin を取ればいいわけです。
(タグの下側に余白つけるという手もありますが、タイトルとタグの間に要素が入るときに制御が難しくなります。詳しくは こちら。)

情報設計をうまく HTML で表現できていれば、ある程度は HTML と CSS を行き来せずに CSS を記述することができます。
これは、デザイナーのデザイン意図をしっかりと読み取れているからこそできることです。UI に対しての情報設計の考えがデザイナーと一致していればデザインに対しての理解が促され、スタイリングもしやすくなるはずです。

調整が必要なこともある

とはいえ、今回の考え方と記述順序を使えば、必ずしもきれいに CSS でデザインが表現できるわけではありません。絶対的な方法ではありません。
例えば、__itemStatus の部分は、現状の class 名の振り分けでデザインを表現するのは難しいように思えます。
今の HTML のままでやるなら、以下のような CSS になるだろうと思います。

.articleList .articleList__itemStatus {
  display: flex;
}

.articleList .articleList__itemState {
  flex-grow: 1;
}

.articleList .articleList__itemState:last-child {
  flex-grow: 0;
  flex-shrink: 1;
  margin-left: 8px;
}

:last-child が DOM に依存していて、ちょっと無理があるコーディングな気もします。

なので、こういう場合は、__itemStatus の中で、__itemStatusMain__itemStatusSub という形で、2カラムにするための DOM を増やしたり、modifier をつけてみたりと、少し HTML に手を加えなければならないこともあるはずです。

また、必ずしもデザインが正しいわけでもありません。もしかしたらデザイナーの情報設計が甘いケースもあります。
なので、コーダーが情報設計を気にしていれば、コーダー側から「ここの情報設計はもう一回見直したい」という提案ができるようになります。
そうすれば、より品質の良いデザインをアウトプットできるようになるはずです。

さいごに

いかがだったでしょうか。
ただ単に、HTML を書いてから CSS を書くと良いわけではなく、今回紹介した順序で取り組むことでより UI デザインと向き合い、そのデザインを通してデザイナーとなめらかに対話できるようになるのではないでしょうか。

ものづくりは協同するものです。
もちろん直接的なコミュニケーションも必要ですが、ものを作る者同士、もので語らうことを意識してみると面白いのかもしれません。

ご意見ある方はコメント欄までどうぞ!