当サイトはアフィリエイト広告を利用しています。

width:100%が効かない!【ポイントは親の幅】

width:100%が効かない!【原因はhtmlの入れ子にあり】

「width: 100%が効かない…」

この問題が起きた時、見る箇所は決まっています。

それは、親の幅、またはその親。

なぜなら、width: 100%は親の幅の影響を受けるから。

そこで今回はwidth: 100%が効かない例をあげ、原因特定までの道すじを解説します。

htmlの親子関係【前提】

例を見ていく前に、htmlの親子関係をサラッと解説。

さっそくですが、以下は親が<div>・子が<p>です。

<div>
  <p>

  </p>
</div>

親:<div>
子:<p>

<div>は、<p>を含んでいます。

このように、親の中に子が入っているのを「入れ子」と言います。

【参考記事】css指定で見るべき、htmlの親子関係

ちなみにこれは、親子関係になってません。

<div>
 
<div>
<p>

</p>

この場合、<div>と<p>は兄弟関係になります。

入れ子

こちらはどうでしょう。

<main>
  <section>
    <div>
      <p>

      </p>
    </div>
  <section>
</main>

親が<div>、子が<p>。

ただし、<div>は<section>に囲われており、ここでも入れ子が成立。

親:<section>
子:<div>

さらに、<main>は<section>を入れ子にしてます。

親:<main>
子:<section>

それぞれの関係性↓

<main>↔︎<section>↔︎<div>↔︎<p>
↔︎子/親↔︎子/親↔︎

注目すべきは…

<p>は<div>だけでなく<section>などにも含まれ、入れ子が何層にもなっている点。

それでは、この入れ子構造を踏まえて次をご覧ください。

祖先要素・子孫要素

「祖先要素」
ある要素から見た、その上の要素(親を含める)。

「子孫要素」
ある要素から見た、その下の要素(子を含める)。

上の例で言うと、

<main>
  <section>
    <div>
      <p>

      </p>
    </div>
  <section>
</main>

<p>の祖先要素

<div> <section> <main>

<main>の子孫要素

<section> <div> <p>

となります。

  • 親要素の中に子要素が入っている状態が入れ子。
  • 入れ子構造は何層にもなる。

width: 100%が効かない原因を探る

冒頭のとおり、これから見ていく例がこちら。

「img画像を、レスポンシブさせるためwidth: 100%に指定。しかし、画面幅を変化させても画像幅は600pxのまま」

width: 100%とすれば、レスポンシブできるはず…

しかし、画像幅は600pxと固定された数値のまま。

つまりパソコン用では横幅いっぱいに広がらず、スマホでは縮小されないというケース。

もと画像がこちら↓

幅:1500px 高さ:1000px (縦横比3:2)

width: 100%が効いておらず、レスポンシブでも画像幅600pxのまま↓

width: 100%が効いておらず、画像幅600pxと固定
グレーの枠線が画面幅です。

書いてあるhtmlレイアウトとcss指定は、以下となります。

少しコード量が多いですが…

<main>
  <section>
    <div>
      <p>
        <img src="airport.jpg" alt="空港">
        夕暮れの空港
      </p>
    </div>
  </section>
</main>

main {
  background-color: #fffae5; /* クリーム色 */
}
section {
  width: 600px;
  margin: 0 auto;
}
div {
  margin-bottom: 30px;
}
p {
  font-size: 24px;
  background-color: #ffffff;
}
img {
  width: 100%;
}

親子関係はこちら。

<main>↔︎<section>↔︎<div>↔︎<p>↔︎<img>
↔︎子/親↔︎子/親↔︎子/親↔︎

それでは解説します。

親のwidthを見る

もう1度、どのように効かないのかを確認。

「img画像を、レスポンシブ対応させるためwidth: 100%に指定。しかし、画面幅を変化させても画像幅は600pxのまま」

「imgにwidth: 100%と指定したけど、画像幅は600pxのまま」とあります。

なので、まずwidth: 100%とはなにかを考えます。

width: 100%は、親の幅に対する子の割合ですね。

で、<img>の親はなにかというと<p>。

<main>
  <section>
    <div>
      <p>
        <img src="airport.jpg" alt="空港">
        夕暮れの空港
      </p>
    </div>
  </section>
</main>

width: 100%なので、親と同じ幅になります。

<p>の幅 = <img>の幅

これは大丈夫ですね。

それじゃあ、<p>の幅はいくつなのか。

<p>を見るとwidthは指定していません。

p {
  font-size: 32px;
  background-color: #ffffff;
}

幅に対する指定がないので、widthの値はauto(初期値)になります。

※初期値 = 指定を行っていない時、はじめから与えられている値。

【参考記事】初期値の使い所を理解する

そして、<p>はブロック要素なのでautoだと、親と同じ幅をとります。

ですので、<p>の親を見ましょう。

【補足】width: autoとwidth: 100%の違い

auto100%の違いはこちら。

width幅の計算方法
auto幅 = 左右padding + 左右border + 要素の幅
100%幅 = 要素の幅

autoでは幅を計算する時、左右のパディングやボーダーを含みます。

一方、100%で幅を計算する時は、左右のパディングやボーダーを含みません。

width:autoとwidth:100%の違い
width:100%だと親要素からはみ出る

もしwidth:100%で、かつ左右にパディングやボーダーを指定したら、親からはみ出てしまいます。

なので、この場合はbox-sizing: border-boxという指定を行いましょう。

すると、親と同じ幅をとれます。

理由は、box-sizing: border-boxを指定することで、パディングやボーダーを含んで幅の計算をしてくれるから。

つまりautoと同じあつかいになるんです。

くわしくは、box-sizingとは?をご覧ください。

なぜ、<p>はautoで<img>は100%?

<p> <img>ともにwidthを指定しないと初期値autoになります。

この時、<p>はブロック要素なので親と同じ幅に。

一方、<img>はインライン要素のため、画像本来の大きさで表示されます。

ですので、<img>を親と同じ幅にするなら、width: 100%とする必要があるのです。

このような理由で、ブロック要素にはautoをインライン要素には100%を指定するのが一般的です。

【参考記事】ブロック要素とインライン要素の違い

補足が長すぎですね、すみません。

一応さきほどは、

「<p>はブロック要素なので、widthの指定がない場合、親要素と同じ幅となります。

なので、<p>の親を見ましょう。」

と述べてました。

というわけで、次へ。

親の親のwidthを見る

<p>の親は、なにかというと<div>です。

<img>からみると、<div>は「親の親」になります。

<main>
  <section>
    <div>
      <p>
        <img src="airport.jpg" alt="空港">
        夕暮れの空港
      </p>
    </div>
  </section>
</main>

先ほど、<p>は親と同じ幅をとっていると分かりました。

なので、

<div>の幅 = <p>の幅

となります。

というわけで、<div>の指定を見ると幅の指定は…ありません。

div {
  margin-bottom: 30px;
}

そうすると、widthは初期値autoとなるため、<div>も親と同じ幅をとります。

次に見るのは、やっぱり<div>の親ですね。

と、ここまでは大丈夫でしょうか?

一旦、レイアウトを見返しましょう↓

<main>
  <section>
    <div>
      <p>
        <img src="airport.jpg" alt="空港">
        夕暮れの空港
      </p>
    </div>
  </section>
</main>

親の親の親のwidthを見て、入れ子を理解する

<div>の親は、<section>です。

そして、<img>から見ると<section>は「親の親の親」になります。

<main>
  <section>
    <div>
      <p>
        <img src="airport.jpg" alt="空港">
        夕暮れの空港
      </p>
    </div>
  </section>
</main>

<div>は親と同じ幅をとるので、

<section>の幅 = <div>の幅

となります。

で、<section>の幅はどうなっているかというと。

width: 600pxの指定がありました。

section {
  width: 600px;
  margin: 0 auto;
}

ということは、各要素の幅は以下のようになります。

<section>=<div>=<p>=<img>
スマホは、横にスクロールしてください。

結果、

<section>のwidth: 600px=<img>のwidth: 100%

となるわけです。

だから画面幅が変化しても、<img>の幅は600pxのままだったんですね。

これは<section>の幅が、<img>の幅にまで影響を及ぼしていたということになります。

<img>から遠く離れた<section>のwidth: 600pxがちゃんと影響していたわけです。

例えると、おじいちゃんの遺伝子がひ孫くらいまで引き継がれた感じかと。

場合によってはもっと離れたケースもあります。

ですので、その時はさらに上へとたどりましょう。

親を見る → 親の親を見る → 親の親の親を見る → 親の親の親の親を見る

さいごに、つけ足しみたいで恐縮ですが、サラッと解決策をお伝えします。

<section>をwidth: autoとしましょう。

またはwidthの指定を削除してください。

すると、<section>の幅は初期値autoを取ることになるので。

<section>のwidthautoだと、画像の幅も画面幅の拡大・縮小によって大きさが変化します。

参考サイト

この記事は、HTML Living StandardCSS3をもとに書きました。

HTML Living Standardはhtmlの、CSS3はcssのルールブックみたいなものです。

両方とも、その最新版です。

いずれも翻訳ありです。

やや専門的に書かれてるので、お時間ある方だけどうぞ。

まとめ

今回は、width: 100%が効かない場合の原因を突き止めました。

ポイントは、こちら。

width: 100%が効かない時は、親やその親の幅を確認する。

参考してみてください。

次は、コメントアウトの使い方をマスターしてみませんか?

コメントをうまく使えば、複雑な入れ子も見やすくできます。

また、レイアウト構造を理解する助けにもなるので、ご覧ください。

タイトルとURLをコピーしました