HTML+CSS 子要素の幅を合計100%にしても崩れる時のチェックポイント

こんにちは、オオニシです。2回目の投稿です。
最近マスク着けてる人を多く見かけるようになってきましたね。風邪やインフルなんかで年越ししないように、しっかり健康には気を付けていきましょう。
今日は、友人からウェブコーディングのヘルプを受けた内容でひとつ書いてみます。

子要素の幅を合計100%にしても崩れる

さて、タイトルの通り本題です。
プライベートな時間で友人のサイトコーディングを手伝っていたら、こんなことを言われました。
慣れた方ならどこが原因なのかある程度目星を付けて調べられると思いますが、慣れないと対処にかなり時間とられてしまいます。

まずはfloatを使った場合の正常ケース

<div style="width:100%;">
<div style="width:50%; height:20px; background-color:red; float: left;"></div>
<div style="width:50%; height:20px; background-color:blue; float:left;"></div>
</div>

いいですね。問題なく表示されています。
これから実際に崩れたケースを紹介します。

1. 子要素のmargin

marginのせいで崩れたバージョン。子要素のmargin幅はwidthに含まれないため、はみ出してしまいます。

<div style="width:100%;">
<div style="width:50%; height:20px; background-color:red; float: left;"></div>
<div style="width:50%; margin-left:1px; height:20px; background-color:blue; float:left;"></div>
</div>

ちなみに親要素のpaddingは大丈夫です。paddingの内側に対しての100%なので、横にはみ出すことにはなりますが崩れはしません。

<div style="width:100%; padding-left:10px;">
<div style="width:50%; height:20px; background-color:red; float: left;"></div>
<div style="width:50%; height:20px; background-color:blue; float:left;"></div>
</div>

2. 子要素のborder

borderのせいで崩れたバージョン。これも1と同じくらいか1より多いくらいで初心者の頃にやらかすケースだと思います。

<div style="width:100%;">
<div style="width:50%; border: 1px solid black; height:20px; background-color:red; float: left;"></div>
<div style="width:50%; height:20px; background-color:blue; float:left;"></div>
</div>

borderはmarginと同じでその要素の外側に作られてしまうので、このケースだと上下左右に1px分、つまり横方向には2px分オーバーしてしまっているんですねー。

番外編: インラインブロック要素で崩れるケース

floatを使わなくとも、インラインブロックであれば横並びのレイアウトを実現できます。
たとえばinputselectなどのタグが元々インラインブロック要素ですが、
display: inline-block;を使えばすべての要素はインラインブロックになります。

実は今回相談されたケースでは、上記のfloatが原因ではなくこのケースで問題になっていました。
このケースは意外と慣れないと気がつかない点で、諦めてfloat使っちゃう人も多い気がします。

普通に書くとこうなります。

<div style="width:100%;">
<div style="width:50%; height:20px; display:inline-block; background-color:red;"></div>
<div style="width:50%; height:20px; display:inline-block; background-color:blue;"></div>
</div> 

で、これは間違っていないんです。間違っていないので、CSSをいくら調べても解決しません。

何が悪いかというと、HTMLの(連続する)改行・半角スペース半角スペース1つ分の文字として内部的に扱われることに起因します。

25%対25%で合計50%にしてみると理解しやすいです。

25%
25%
<div style="width:100%;">
<div style="width:25%; height:20px; display:inline-block; background-color:red;">25%</div>
<div style="width:25%; height:20px; display:inline-block; background-color:blue;">25%</div>
</div> 

25%のインラインブロック要素の間に、微妙に間が空いているのが分かるでしょうか?これがレイアウト崩れの原因です。

さて、どうすれば直るかですが、先ほど言ったとおり改行やスペースが半角スペースとして現れているのが原因なわけです。
ですので、HTML上でコメントを使って改行やスペースをコメントアウトしてやればOKです。

<div style="width:100%;"><!--
--><div style="width:50%; height:20px; display:inline-block; background-color:red;"></div><!--
--><div style="width:50%; height:20px; display:inline-block; background-color:blue;"></div><!--
--></div>

または、見やすさを犠牲にして1行にする手もあります。でもこんな長い行は見たくないですよね…。

<div style="width:100%;"><div style="width:50%; height:20px; display:inline-block; background-color:red;"></div><div style="width:50%; height:20px; display:inline-block; background-color:blue;"></div></div>

以上です!特に最後のインラインブロックについては、中級者程度になってもハマる人が多いポイントなので使うことがあれば気を付けましょう!

以下は余談ですが、CSSのwhite-spaceプロパティを使うと改行や半角スペースの挙動を変更できたりします。
さっき崩れたコードでも、親要素の方に white-space: nowrap; を指定してあげれば、半角スペース1つ分のスペースは残りますが段組みが崩れることがなくなります。

<div style="width:100%; white-space:nowrap;">
<div style="width:50%; height:20px; display:inline-block; background-color:red;"></div>
<div style="width:50%; height:20px; display:inline-block; background-color:blue;"></div>
</div>