◆height:100%のtextareaとiframeは100%を超えてスクロールバーが出る

◆transitionalモードにしたほうがいいかも

◆overflow:hiddenという方法もあり

◆Firefoxちゃんと動いてくれる

height:100%問題といえば分かる人はあれのことかな と想像がつくかもしれません
cssでheight:100%;をしていた時にstrictモードとtransitionalモードで挙動が違うことでデザインが崩れる問題です

モードの指定方法は
strictモード
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

transitionalモード
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
これをHTMLファイルの1行目に書きます
省略してもtransitionalモードになります

HTML5 の書き方だと
<!doctype html>
だけで書けます
HTML5はstrictモードになります

height:100%

height:XX%は指定した要素の高さを親要素の何パーセントにするかという指定です
100%を指定すれば親要素と同じ大きさになります
親要素に2つの要素があって両方で100%指定すると当然 親要素からはみ出します

HTML自体が横書きで上から下へ向かって書いていくものなので幅(width)はブロック要素なら常に画面の端から端までですが高さ(height)は中身に必要な最低限の大きさが基本です
空っぽのdivを作ると幅は100%で高さ0になってます

transitionalモードでは親要素のheightが決まってないと画面全体として扱ってくれます
こうしてくれると全画面モードなスクロールを使わないページを作るときに楽です
html-height100%-transitional-ch42-0
Chrome42
<head><style>
html,body{margin:0;}
textarea{width:100%;height:100%;background:orange;}
body{background:red;}
</style></head>
<body><textarea></textarea></body>

html,bodyはブラウザ固有のmarginを消すだけで bodyの子要素のtextareaでheight:100%を指定してます
bodyを赤色 textareaをオレンジ色にしてます
スクロールバーはなくて赤色部分がないのでbodyの中身すべてがtextareaになってるということです


しかし strictモードでは 親要素のheightが決まっていないと 指定がない時と一緒で%で書いたスタイルは思い通りに動いてくれません
html-height100%-strict-ch42-0
Chrome42
<!doctype html>
<head><style>
html,body{margin:0;}
textarea{width:100%;height:100%;background:orange;}
body{background:red;}
</style></head>
<body><textarea></textarea></body>

textareaの中身は後から打っているので 元々は空です
なので 空のtextareaにとっての最低限のわずかな高さしかオレンジ色の場所がありません
これがstrictモードです

strictモードでheight:100%



じゃあ どうすればstrictモードで 画面いっぱいのページを作るかです
ネットでもよく出てきますが htmlとbodyでもheight:100%を指定します

html-height100%-strict-fx39
Firefox39.0a2
<!doctype html>
<head><style>
html,body,textarea{width:100%;height:100%;margin:0;padding:0;border:0;}
body{background:red;}
textarea{background:orange;}
</style></head>
<body><textarea></textarea></body>

これはFirefoxです
全画面がオレンジ(textarea)になっています
strictにするとbox-sizingcontent-boxになるのでpaddingとborderも0にしています

widthやheightで指定した値が
●content-box:中身だけ(paddingとborderはwidthやheightで指定した大きさの外側にある)
●padding-box:paddingまで(widthやheightで指定した大きさにpaddingも含む borderは別)
●border-box:borderまで(widthやheightで指定した大きさにpaddingもborderも含む)
のうちのどれなのかを決めるのがbox-sizingです

strictモードではcontent-boxになっているので width:100%やheight:100%を指定するとその外側にpaddingやborderができて親要素より大きくなってしまいます
box-sizingをborder-boxに指定するかpaddingとborderを0にする必要があります
これははみ出さない方法なのでbox-sizingを変更するかpaddingとborderを変更するかではデザインが異なるので必要な方にしてください


transitionalモードではborder-boxなのでpaddingとborderの指定はなくても変わらないです
html-height100%-transitional-fx39

Chromeだと

Firefoxで動いたし ネットで調べてもstrictはこういう仕様と書いてるしChromeでも動くはずです
はずなんですが
html-height100%-strict-ch42
html-height100%-strict-ch36

スクロールバーがあるんですけど!

Firefoxと同じようにうごいてくれません
こういうときに規準どおりの動きをしていないのはたいていChromeの方なので悪いのはChromeです(断言)
上がChrome42 下がChromodo36です

Chromeともあろうブラウザがなんでこんな重要な問題を放置してるの?


今までこんなことなかったようなと思って今までのを見てみるとほとんどDOCタイプ宣言を省略してる手抜きでした
strictよりtransitionalの動きのほうが好きだしtransitionalでいいかな
JavaScriptだってstrictモードなんて使うこと無いし……

とは言ってもHTML5ではstrictモードだけで transitionalモード自体が昔のものとの互換性を取るためのあまりすすめられたものではないので必要なければ避けたいんですよね

そんなtransitionalモードですが 何も書かないとこっちになるというのは危険に思えます
目的が互換性で昔のは何も書いてないんだから仕方ないのはわかります
しかし 新しくページ作る人でもめんどうだから省略しているのはよくあることですしDOCタイプ宣言 なにそれ?って人もいます
なので 昔の規格と言っても知らずにその規格で書いてる人がいっぱいいてわざわざそっちに合わせたCSSを書いてる人もいます
そんなところに 突然「そろそろtransitional時代のページは誰も見なくなったからstrictだけにしよう」 と切り替えられると困る人がいっぱいでてきます
私だって HTMLでページ作り始めた頃はDOCタイプ宣言なんて知らなくて そういうのがあるって知ってもなくても動くならなしでいいよ とほとんど書いてませんでした
テストするときは今でも省略していて 最後にちゃんと文字コード書いたりDOCタイプ宣言書いてCSSおかしいバグってるし なんてしょっちゅうですよ(「しょっちゅう」 に漢字がないことを今知ってすごい発見したと思ってます)

このまま両モードがずっと続いていってくれるならtransitionalで書きたいですが絶対とは言えないですから困ったものです


transitionalならChromeでもスクロールバーが出ない
html-height100%-transitional-ch42
html-height100%-transitional-ch36

原因は

なんとかできないかなーともう少し調べてみます
ChromeのDeveloer Toolsから要素サイズを調べます
html-height100%-strict-ch42-computed
これを見ると textareaもbodyもhtmlも同じ高さです
計算上はいっしょということは やっぱりChromeの表示部分がおかしいってことですよねー

前にDOCタイプ宣言ありのものでちゃんとできてたのがあった気がするので探してみると驚きのことがわかりました


divだと動く!

<!doctype html>
<head><style>
html,body,div{width:100%;height:100%;margin:0;padding:0;border:0;background:red;}
div{background:orange;}
</style></head>
<body><div></div></body>
html-height100%-strict-ch42-div
スクロールバーがないですね

なんでtextareaだと問題が起きるんでしょうか
起きる時が限られている問題だから気づかれてないだけのようにも思えてきました 
divの中にtextareaを作った版もやってみると
<!doctype html>
<head><style>
html,body,textarea{width:100%;height:100%;margin:0;padding:0;border:0;background:lightgreen;}
div{width:300px;height:300px;overflow:auto;background:red;}
textarea{background:orange;}
</style></head>
<body><div><textarea></textarea></div></body>
html-height100%-strict-ch42-div-textarea
やっぱりtextareaにスクロールバーがあります
body直下だからとかではなく textareaに問題あるようです

transitionalモードはいうまでもなく
<head><style>
html,body,textarea{width:100%;height:100%;margin:0;padding:0;border:0;background:lightgreen;}
div{width:300px;height:300px;overflow:auto;background:red;}
textarea{background:orange;}
</style></head>
<body><div><textarea></textarea></div></body>
html-height100%-strict-ch42-div-textarea-overhidden

divでは起きなかったのでtextarea以外のブロック要素をいろいろ試してみたのですがこの問題が起きるのはtextareaとiframeだけでした
マイナーすぎるタグは見逃してるかもしれません

textareaとiframe これらを100%で使うときってたまにしか使わないけど たまにはあるんですよね
ホント困ったものですよ
Google先生にはもっとしっかりしていただきたいものです

対策


(1) strictモードを捨てる

Chromeのためだけにstrictを捨てる覚悟があなたにはありますか?

(2) overflow:hidden

strictモードではtextarea要素のすぐ後に微妙な空白が入ります
そのせいで空白部分を表示するためのスクロールバーが出てしまいます
下側なので 親要素からはみ出ているものを切り捨てればちょうどよくなります
なのでoverflow:hidden を親要素に設定します
そうすればスクロールバーは表示されずに高さ100%の完成です

textarea自体の大きさが親要素より大きくなっていた場合は この方法だとtextareaが少し切れてしまいますが今回はtextarea自体の大きさはぴったり親要素にあってるのでoverflow:hiddenで完璧にできます



追記

コメントで正しい原因を教えていただいたので正しい対策方法を追加しておきます

原因

原因は textarea も iframe も inline 要素 (inline-block) で vertical-align が関係してくることです
vertical-align は transitional モードでは bottom が設定されています
ですが strict モードでは baseline です

MDN によると
<textarea> のような、いくつかの 置換要素 の baseline は HTML 仕様で未定義で、このため、このキーワードの挙動はブラウザにより異なるかもしれません。
とあります

baseline の位置が決まってないので Chrome だとスクロールバーが出て Firefox だとスクロールバーが出てなかったんです

また バージョンの違いもあるかもしれませんが ブラウザごとに大丈夫かどうかが決まってるわけではないです
コメントをいただいた人の環境だと Firefox でもスクロールバーがあったようです
なので Firefox しか使わないからー なんていわずにちゃんと対策しておいたほうがよいと思います

正しい対策方法

どちらかやればおっけいです

(1) display:block する
vertical-align は inline 要素に対するものなので block にしてしまえば大丈夫です
textarea も iframe もあまりインラインとして使うことがないのでこれでも問題ないことは多そうです
インライン要素のままにしたいなら (2) をやります

(2) vertical-align を top や bottom にする
そもそもの原因である vertical-align を正しく設定します


記事におかしなところがあったら気軽にコメント書いていってくださいね