HTML/CSSコーディングをやって気づいた勘所

バックエンドのサーバーサイドプログラマにして、インフラエンジニアやってましたが、ここ最近はフロントエンドというかHTML/CSSコーダーもやっている自分です。そろそろ勘所というか既存資産に対して愚痴を言うべき箇所が分かってきましたので書いてみようと思います。中上級者には釈迦に説法の内容なので温かい目で見て頂ければ。。なお、SPAはやってないので一項目からSPAのことガン無視してますのでご容赦ください。

初期状態表示にJavaScriptを使わない

ブラウザはDOMとCSSを完全に読みこんだ後にレンダリングを始め、しばしばJavaScriptの実行はそのレンダリング後(よくあるのはDOMContentLoaded後)になってしまいます。結果として、JavaScriptで画面のデザインをやると以下のような順序でレンダリングが行われ崩れた画面が表示されます。
1. HTMLとCSSによる中途半端なレンダリング結果がユーザに見える
2. JavaScriptのロードが開始され、この間中途半端な状態が表示され続ける
3. JavaScriptが実行され完全な画面が表示される

崩れ方にもよりますが、2の状態の間の見栄えがとても悪い上に、2から3に移る時に画面が高速に変動するため目に負荷を与えるので避けるべきなんでしょう。特にファーストビューに該当する部分はCSSのみでデザインして2が発生するのを防ぐことができます。ファーストビュー内でJavaScriptによる初期状態のデザインが避けられない場合は、ローディング画像や適当な枠を用意して2から3に遷移するところで画面が大きく動くのを防ぐという対策はありますが、これを綺麗にやるのはなかなか難しく、いいライブラリを探すなりvisilibity: hiddenを信じるなりが必要でしょう。

この問題については、デザインを外注した画面と言えど注意が必要と思われます。特に発注先で、ローカルのサーバを使い、デザインに関係ないJavaScriptを消している状態でコーディングしている場合には、ネットワーク遅延や他のJavaScriptによる遅延がほとんど発生しないため初期崩れの問題が見えづらくなっている可能性があります。 受取後も注意して見る必要がありますし、発注段階で注意点にあげておいていいと思います。

仕組み上この手の問題を回避しやすいAMPの採用も検討するのもいいと思います。というか、フルAMPしたい。怪しいJavaScriptレンダリングが遅くなる地獄から解放されたい。。。

floatよりflexboxを使う

要素を横に並べるためによく使われてきたfloat属性ですが、改修を続けていくうちにワンオフの技巧的なCSSになってしまいがちに思われます。floatでやりたいことはだいたいflexboxで出来てよりシンプルに書けるのでそっちに置き換えていくべきです。flexboxは横に並べた後の整列もやってくれますのでCSSを大きく削減できますし、場合によってはデザインのためのJavaScriptをなくすこともできて、パフォーマンス問題から解放されるかもしれません。また、flexboxには整列のためもオプションが多く、margin・paddingをあまり調整せずとも機械的にきれいな整列をできる場合もままあります。研究すると救われることも多いでしょう。

DOM構造を安定化させる

これはサーバーサイド(つまりPHP)やってる自分だから悩まされるポイントだと思います。例えばボタンの長めのものと短めのもの、onとoffのものでHTMLのDOMの構造をほいほい変えるのは本当に止めましょう。divタグがliタグになってたりするだけでも大概面倒なことになるのに、divとaタグの順序が入れ替わってたりして更にCSSがその順序に依存してるともう発狂します。

こうなるとPHPのテンプレート側でDOMの違いを吸収するしかないのですが、いちいちパターンごとに完全に別のテンプレートを作れば管理性が失われますし、一つのテンプレートでif文で吸収していくのも中々大変です。(JavaScriptで吸収するという手もありますが、初期状態表示の問題を引き起こす可能性もあります)DOM構造はそのままにパターンごとにクラス名だけを書き換えるのが理想ですね。。

深いセレクタを持つCSSを作り込まない

散々言われている話ですが、やたら深いレベルのセレクタを持つCSSを作ると苦しみます。セレクタが深いというのはつまり画面のDOM構造に強く依存しているということであり、そのままでは他の画面に適用できず、コンポーネントの再利用性が低くなります。また単純に同画面内でコンポーネントを移動しただけでもCSSの適用が失われることもあり、デザインの修正をおいそれとできないことにもなってしまいます。BEM等々のネーミングルールやgrepなどのツールを活用してクラス名の衝突を避けつつ、深いセレクタを回避していきたいところです。

また、どちらかというとマルチクラスでCSSコーディングしているときの問題なのですが、重要度を高めてデザインを切り替えるということをやる時もレベルが深すぎるセレクタがあると苦しみが発生します。5段のセレクタを6段で殴るというようなことが何度も起きてCSSに手が付けられなくなっていきます。思うに人間は2段を超えるCSSセレクタを完全には把握しきれないのです。3段目に到達したらもう増やせないということを意識して、段を下げ、それ以上段を増やさない努力をするべきでしょう。

余談

これを書いていた頃に二つ驚かされたことがありました。
一つはHTML5カンファレンスが開かれたらしく、はてぶホットエントリーでもスライドが流れてたので見ましたが、自分と見てる世界の違いに愕然としました。SPAだのReactだの全くやらないのでSSRだのなんだの言われても「何だこの異世界人…」みたいな気分になりました。
もう一つは、新しいスマホの性能についてです。最近スマホを新調したのですがこれでウェブを見るとJavaScriptで表示や反応が遅かった画面が一瞬で表示されてしまいました。おかげでチマチマした最適化を行っていた自分が馬鹿馬鹿しくなってきましたが、低性能スマホは世にも自分の手元にも溢れているのでこれからもデザインのためのJavaScriptの抹殺を続けていきます…