WTF, HTML and CSS?

HTMLとCSSはなんてクソなんだと、あなたに言わせるかもしれない理由。一般的にイライラさせられるHTMLとCSSの困惑、間違い、ジレンマの厳選した一覧。

Created by @mdo.

コンテンツ

doctype を宣言する

常に doctype を宣言しましょう。 私はシンプルな HTML5 doctype を推奨します。:

<!DOCTYPE html>

不正な形式のtable、inputなどと一緒にdoctype を抜かすことが問題を引き起こし、ページは互換モードでレンダリングされます。

ボックスモデルの計算

widthが与えられている要素がpaddingborder-widthを持ったとき、幅が広くなります。この問題を避けるには、今では一般的なbox-sizing: border-box;リセットを使用することです。

Rem の単位とモバイルSafari

モバイルSafariが全てのプロパティの値でremの使用をサポートしていますが、メディアクエリのサイズ指定でremが使われたときに駄目になるようで、ページのテキストが違うサイズで無限に点滅します。

今のところ、remの代わりにemを使いましょう。

html {
  font-size: 16px;
}

/* モバイルSafariで点滅するバグを起こします */
@media (min-width: 40rem) {
  html {
    font-size: 20px;
  }
}

/* モバイルSafariで問題なく機能します */
@media (min-width: 40em) {
  html {
    font-size: 20px;
  }
}

助けが必要です! もし、これに関してAppleかWebkitのバグレポートへのリンクを知っていたら, それを追加できたらと思っています。私は、Safariのデスクトップではなくモバイルだけに対してこの報告がされているのがどこでなのか、明確に分かりません。

float が最初

floatの要素はドキュメントの順番において常に最初にくるべきです。floatの要素は囲う何かを必要とします。そうしないと内容に次いで表示されるのではなく、下に入り込んでしまいます。

<div class="parent">
  <div class="float">Float</div>
  <div class="content">
    <!-- ... -->
  </div>
</div>

float と clear

もしfloatが使用されていれば、おそらくclearする必要があります。floatを使用した要素につづくどんな内容も、クリアされるまでその要素に巻きつきます。floatを解除するには、以下のいずれかのテクニックを使いましょう。

別クラスでfloatを解除するにはthe micro clearfixを使いましょう。

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}
.clearfix:after {
  clear: both;
}

あるいは、親要素でoverflowautohiddenで使いましょう。

.parent {
  overflow: auto; /* clearfix */
}
.other-parent {
  overflow: hidden; /* clearfix */
}

一般的には親要素の中に配置された要素で、overflowが意図しない副作用を引き起こすことに気をつけてください。

ヒント! 他の理由のために使用されることがあるので、floatを解除するとき`/ clearfix /`のようなコメントを入れておくことで、あなたと共同作業者の未来を幸せにしましょう。

float と計算された高さ

floatを使用した中身だけを持つ親要素はheight: 0;に計算されます。ブラウザに親要素の高さを算出させるにはclearfixを与えましょう。

float を使用した要素はブロックレベル

floatを使った要素は自動的にdisplay: block;になります。floatdisplayを上書きするし、必要もないので、両方を指定するのはやめましょう。

.element {
  float: left;
  display: block; /* 必要ない */
}

面白い事実: 数年前、マージンが倍になるバグをIE6で避けるために、適切にfloatを働かせるにはdisplay: inline;を使う必要がありました。ですが、当時からずいぶん時間が経ちました。

隣接する垂直方向のマージンは崩壊する

隣接する要素(前後)のtopとbottomのマージンは様々な状況で崩壊しますが、決してfloatやabsoluteで配置した要素によるものではありません。詳しくは、MDNの記事を読むかCSS2の仕様のマージンの崩壊についてを参照してください。

水平方向に隣接したマージンは決して崩壊しません

table の行のスタイル

tableの行<tr>は、親の<table>に対してborder-collapse: collapse;を与えない限りborderを認識しません。さらに、<tr>とその子の<td><th>同じborder-widthを持っていれば、行にボーダーが適応されているのを見られません。例としてこのJSBinのリンクを見てください

Firefox と <input>ボタン

理由はよく分かりませんが、Firefoxは<input>のsubmitとbuttonに対してユーザー定義のCSSで上書きできないline-heightを当てます。これに対処するのに2つの方法があります:

  1. <button>要素にする
  2. line-heightをボタンに使わない

1つめの方法を取るのであれば(どっちみち<button>は素晴らしいので私はこっちを推奨します)、知っておくべきことは以下のようなことです:

<!-- あまり良くありません -->
<input type="submit" value="Save changes">
<input type="button" value="Cancel">

<!-- いつでも最高です -->
<button type="submit">Save changes</button>
<button type="button">Cancel</button>

2つめの方法を取るのであれば、line-heightを与えないこととボタンのテキストを垂直方向に中央寄せするのにpaddingだけを使用することです。Firefoxで実際の問題と回避方法をこのJSBinの例で見てください

グッドニュース! これについての修正がFirefox 30に含まれているようです。これは私たち自身の未来にとっていいニュースですが、古いバージョンでは修正されてないことに気をつけてください。

Firefox のボタンの内側のアウトライン

Firefoxは:focus時のボタン(<input><button>)に内側のアウトラインを追加しました。明らかにアクセシビリティのためですが、その配置は奇妙に見えます。上書きするのにこのCSSを使ってください:

input::-moz-focus-inner,
button::-moz-focus-inner {
  padding: 0;
  border: 0;
}

この修正を、前のセクションでも紹介したのと同じJSBinの例で見ることができます。

ヒント! ボタン、リンク、inputに対してfocusの状態を持つようにさせましょう。タブを使うユーザーと視覚障害を持つユーザー両方にとって、アクセシビリティのためにアフォーダンスを提供することは最高のことです。

<button>typeを常に与える

初期値はsubmitで、フォームの中のどのボタンもフォームを送信できてしまいます。フォームを送信しないボタン全てにtype="button"を与えて、送信するボタンのみtype="submit"を与えましょう。

<button type="submit">Save changes</button>
<button type="button">Cancel</button>

フォームの中にないけれどもアクションのために<button>が必要なときは、type="button"を使用しましょう。

<button class="dismiss" type="button">x</button>

面白い事実: 明らかにIE7は<button>value属性を適切にサポートしていません。属性値を読み取る代わりに、innerHTML(<button>の開始タグから終了タグの間の内容)から引っ張ってきています。ですが、2つの理由からあまり注目するべきことではないと思います: IE7の利用率は低下していってますし、<button>valueとinnerHTMLを両方与えることは、むしろ珍しいことなので。

Internet Explorer のセレクタの上限

IEの9とそれ以下のバージョンは、1つのスタイルシートで4,096のセレクタが上限になっています。また、1ページに対してスタイルシートと<style></style>を合わせて31の上限もあります。このブラウザでは、この上限を超えたものは全て無視されます。CSSを分割するか、リファクタリングしましょう。私は後者を推奨します。

助けになる注釈として、どうやってブラウザがセレクタを数えるかを以下に示します:

/* 1つのセレクタ */
.element { }

/* 2つ以上のセレクタ */
.element,
.other-element { }

/* 3つ以上のセレクタ */
input[type="text"],
.form-control,
.form-group > input { }

position の説明

position: fixed;を使用した要素はブラウザのビューポートに相対して配置されます。position: absolute;を使用した要素は、static以外(relativeabsolutefixed)で配置されている最も近い親要素に相対して配置されます。

position と width

position: [absolute|fixed];leftrightをもつ要素にwidth: 100%;を与えないでください。width: 100%;を使うことは、left: 0;right: 0;を合わせて使うことと同じです。どちらか一方を使って、両方を使わないでください。

固定された position と transform

親要素がtransformをもつとき、ブラウザはposition: fixed;を壊します。transformを使うことによって、新しい包含ブロックを作成され、事実上親要素にposition: relative;を持たせ、固定された要素がposition: absolute;として振舞うようになります。

デモを見てエリック・メイヤー氏によるこの問題についての投稿を読んでください。