読者です 読者をやめる 読者になる 読者になる

タオルケット体操

サツバツいんたーねっと

テーブルレイアウトから抜け出せないエンジニアがとりあえず最低限押さえるべき仕様

css デザイン

社内で勉強会を開きたいので、その叩き台みたいな感じのテキストです。

マークアップを書けるプログラマーというのも世の中には沢山いますが、ちゃんと書けない or なんとなく書いてるだけという人も多いです。*1

また当然のように、ゲームを作るのでもない限りは、日頃フロントエンドで書くようなJavaScriptは結局のところDOMやスタイルをいじるようなものが殆どです。最近はそうでもないかもしれないですけど、まぁだいたいはそうです。そういうことにしてください。なので、HTMLやCSSへのきちんとした理解なしでJavaScriptを書くのはあまりよろしくないような感じになることが多いと思います。

CSSを知らないプログラマーが書きがちなHTMLアンチパターン

以下にあげるのはよくみる悪いHTMLですが、仕様をちゃんと把握することで、このようなコーディングに頼らず、綺麗で保守性も高く、かつ早く作ることが出来るようになります。

1. とりあえず全部tableで囲む

エンシェントマークアップにありがちなパターンですね。最近はとにかくtableを消しまくる作業をしているので心が折れかけています。

これが生まれるのは、

  • HTMLのコンセプトやCSSそのもの

  • ブロックレベル要素とインライン要素の違い

  • ボックスモデルとfloatの挙動

への不理解が原因であることが多いです。

2. brタグを連打しまくってスペースの調整

これもtableと同じで、コンセプトや仕様への理解不足が招くパターンですね。合わせて、marginの相殺というわかりにくい仕様もその一因になっているかもしれません。

3. fontタグなどを使う

HTML5になってから、「HTMLで構造を定義してCSSでデザイン」するというコンセプトがより明確になりました。なので、fontなどの見栄えを表現するようなタグは基本的には使わないようにしましょう。仕様から削除されたものもあります。

なお、テーブルレイアウトやbrでのスペース調整が悪だとされるのも「HTMLはあくまで構造を定義するもの」だというコンセプトがあるからなんですね。SEO的にも不利だとかなんとかきいたこともあります。

プログラマーにとってのマークアップのハードルの高さ

マークアップ(特にCSS)を敬遠するプログラマーは多いです。
そもそもが見た目に気を使う人種ではないことに加えて、いわゆる手続き型ではなく、宣言的に構造を作っていくマークアップ言語のやり方が「トライアンドエラー」型の試行錯誤と相性が良くないからではないかな、と僕は推測しています。*2

printでもデバッガでもなんでもいいんですが、トライアンドエラー的な試行錯誤は手続き的な思考に陥りがちです。手続きのステップ毎に状態を出力していくやり方は、トライアンドエラーなやり方と非常に相性がいいからです。

反面、HTMLとCSSに関して言えば、ステップ毎のprintデバッグは不可能です。書いたものが反映されておしまいです。もちろん、書く -> 表示 -> 修正というトライアンドエラーは出来るのですが、その中間のプロセスをのぞき見ることは基本的に出来ません。宣言が仕様違反だったりコンテクストを見誤ったものだと、単に無視されたりファンタスティックなCSS現象*3といった結果だけがいきなり表示されておしまいになってしまいます、

何人かにヒアリングした結果、ここらへんの取っ付きにくさがプログラマーがマークアップを書く際の障壁になっている感を感じました。そして、CSSで出来ることもjQueryで無理矢理解決しようとする方が多いのもここらへんに事情がありそうです。

つまりここの障壁を壊してやれば、多くのプログラマーが感じているCSSへのとっつきにくさを緩和出来るわけです。

なお、よく話題にあがるブラウザ非互換ですが、今となっては大抵の現場でIE9〜10以下を切れるようになっていることだろう思うのできっと問題ないよね?ね?なお僕はIE8までしか対応したことない。昔は大変だったみたいですね。

解決策

仕様を読め。

先に宣言的な、と書きました。つまり、仕様通りに書けば(基本的には)正しく出力されるわけです。何一つ仕様を把握せずにいきなり書き始めるから「高さがかわらん!」とか「真ん中に動かせない!」とか言い始めて、最終的に全てをtableとtdで囲むようになるわけです。
そういう人に限って「CSSはブラウザ毎の解釈が」などと言い始めますがそういう恥ずかしいことはやめましょう。IEを隠れ蓑にするな、自分の未熟さと向き合え。そう、あの頃は俺も若かった……

とはいうものの、見た目に無頓着なプログラマーがわざわざ見栄えをちょっとよくするためだけに無味乾燥なCSSの仕様書を喜んで読むとは思えない*4ので、これさえ押さえておけば(CSS2.1レベルでは)謎現象でイライラすることはかなり減るはずだぜイェーイみたいな要点をまとめます。

CSSの仕様を理解することで、以前はただの不思議現象だとしか思えなかったファンタスティックなレイアウト崩れも、ちゃんと原因を見据えた上で適切な対処ができるようになりますし、以前のソースをコピペするような無体を晒さなくても、デザイナーの上げたイラレ案をパパッとマークアップで仕上げられるようになります。ほとんどは。

CSSでレイアウトするのに押さえておきたい知識

以下で紹介するのはデザイン的な観点ではなく、あくまでメカニカルなCSSコーディングをする上での前提知識です。またCSSはあくまでスタイルを定義するものであり、適切に構造化クラス化されたHTMLを書いてこそだということも付け加えておきます。

  • ブロックレベル要素とインライン要素の違い

  • ボックスモデル

    • marginとpadding
  • float

    • 独特の挙動

    • overflowプロパティ

  • position(相対配置、絶対配置、固定配置)

大体こんなところでしょうかね。ここらへんを覚えておけば、大抵のレイアウトやパーツは自分で作れるようになります。

なお頑張って書こうとおもいますけども、本稿はあくまで簡潔に記述することを目的とするので、出来れば他の人のブログでも仕様でもMozilla Developer Networkの文書でもなんでもいいので合わせて読んでより正確な理解を得ることをおすすめしますよ。

ブロックレベル要素とインライン要素の違い

理解すると得られるもの

たぶん誰しもが一度は躓いたことのある「heightを指定してるのに高さかわらねーんだけどクソが!」みたいな現象に対処出来るようになります。

ブロックレベル要素

存在するほとんどのタグがブロックレベル要素としての性質を持ちます。CSSのプロパティもほぼ全てが利用可能です。

高さと幅を持っていて、上から下へと積み重なっていくように配置されていきます。

インライン要素

初学者を苦しめるのがコイツ。置換インライン要素と非置換インライン要素というのがあるけども、煩雑なので省略します。imgタグもちょっと例外的な存在なんですけど省略します。

いくつか存在しますけども、代表的なのはa, span, inputなどでしょうか。また、タグで囲まないただのテキストも暗黙のうちにインラインとして認識されます。

この要素は、ライン(行)の中に存在するということで、左から右へと配置されていきます。また、インライン要素が中に持てるのはインライン要素だけです。なので

<span><p>アバババーッ!?</p></span>

みたいな書き方は仕様違反です。

そして、この要素にはwidth, height, margin, floatの指定が出来ません。paddingの指定も左右に限定されます。ここテストに出るからな。
ただし、vertical-align: middleが指定出来るのはインライン要素とテーブルのセルだけです。

基本

基本的にブロックレベル要素で構造を作っていきます。どうしてもdivが多くなるとはおもいますが、HTML5の新しい要素とかも使ったりしてなるべく頑張りましょう。

インライン要素でレイアウトを作ることは殆どないかと思われます。ラインを下に移したい場合は、brタグを打つのではなく、pやdivなどのブロックレベル要素で囲みます。 また細かいパーツ作りなどをする際、中にdivなどを置かないように注意しましょう。

要素同士の上下の幅を調整したい場合は、brタグを連打せずに、marginやpaddingの指定をしていくことで対処します。marginやpaddingの使い分けについては後の項で解説します。

テーブルレイアウトが生まれる元凶の一つである、vertical-align: middleがインラインとセルでしか指定出来ない仕様ですが、これはそもそも要素内のテキスト( + img)の高さを指定するものであるvertical-alignブロックレベル要素内のエレメントの位置も変えられるというそもそもの誤解に起因するものです。
この勘違いは結構根強く、同様にtext-alignを使ってエレメントの中央揃えを試みて失敗した結果テーブルレイアウトにはしる例も見られます。

エレメントの中央寄せなどを試みる場合は、marginを使う、絶対配置を使う、などのやり方があります。どちらのアプローチも後の項で説明しますが、僕は基本的にはmarginでレイアウトすることをおすすめします。

発展

実はスタイルプロパティのdisplayを指定することでinline, blockを切り替えることが出来ます。

そして、最近のブラウザではもう一つ、inline-blockという要素が存在します。*5

このinline-blockは

  • インライン要素のように横に並んでいく
  • でもwidth, heightが指定可能
  • しかも padding, margin を上下左右に指定可能
  • その上 vertical-align も指定出来る

といういいとこ取りな要素です。

使い方の例としては、例えば「ページ上部に横並びのリンクを置きたい」とします。以下のようなhtmlになります。

<nav>
  <ul>
    <li><a href="#">foo</a></li>
    <li><a href="#">bar</a></li>
    <li><a href="#">baz</a></li>
  </ul>
</nav>

liはブロックレベルですので、このままですと縦並びになってしまいますが、display: inlineをした場合、height, marginの指定が出来なくなるのでボタンの大きさや、合間に適切なスペースをとるなどのユーザビリティに配慮したデザインが出来なくなります。
かといって、floatはごちゃごちゃとややこしいし、各要素のセンタリングを行うのが面倒になります。

こういう時にdisplay: inline-blockを利用すると問題を全て解決出来るようになるわけですね。便利!

他にも筆者は、input系の要素はサイズや横に並んだ際のmargin調整をめっちゃ重視したい系男子なので、一括でdisplay: inline-blockを振ってしまいます。

おしまい

今回はCSSを書く上でのはじめの一歩を解説しました。

イカしたプロパティの指定や、ナウいCSS3みたいなキャッチーさはないですが、これを知らずしてまともなマークアップを書くことは出来ません。バスケでいうドリブルの練習みたいなもんです。
詳しく調べると色々奥深い感じなんですが、とりあえずはこんくらいのフワッとした理解で事足りるかとおもいます。

とりあえず長くなりそうで疲れたので残りは別記事にします。突っ込みどころとかあったら勉強しなおすので指摘オナシャス!

おしまい。

続きを書きました

hachibeechan.hateblo.jp

*1:弊社は、いわゆるWeb系の会社ではないせいか、アプリケーションエンジニアリングやUIを軽視する傾向が強く、未だにテーブルレイアウトとコピペ継ぎ足し伝統のCSSが蔓延っています。なので保守が悪夢です。どげんかしたいのです

*2:逆に手続き型に染まっていないプログラマーはそれほど抵抗感を持たないのではないかと予想している

*3:特にfloatに慣れていないとよく発生する

*4:僕だって読む気にはなれなかったし

*5:IE9以下とかへの対応はググれば出ます