floatした画像が左寄せにならない原因とfloatイコール「回り込み」ではない理由

floatした画像が左寄せにならない原因とfloatイコール「回り込み」ではない理由

カスタマイズ HTML, CSS, JavaScript
2019/04/05
6
vanillaice (Akira)
vanillaice (Akira)
EducationInstruction初心者向けHTMLCSSトラブル対処

画像(img要素)のdisplay値は文法上はinline(ふるまいはinline-block)のため、普通にコードを記せば勝手に並びますからそもそもfloatする必要は無いのですが。 ブログサービスのシステム上floatを利用して並べていた方もいらっしゃるかと思います。Yahooとか(笑)

高さの異なる画像が並んでいる時、左に寄せられるべき画像が何故か右になってしまうことがあると思います。その原因について。そして「floatとは回り込みのことです」と説明している、あるいは思っている方に反論するものでもあります(笑)

理想と現実の違い

理想というか想像では以下のような感じ。

便宜上親要素に薄い緑の背景色を付けてます。で、一応これが「たぶんこうなるだろう」という予測の形だと思います。ですが実際は以下のようになrます。

問題は 4枚目 ブランコに乗る女性の画像 です。float: left に指定しているのに右に寄ってますよね。

なぜ左端まで行かないのか

<div style="overflow: hidden;">
  <img src="画像①" alt="" style="float-left;">
  <img src="画像②" alt="" style="float-left;">
  <img src="画像③" alt="" style="float-left;">
  <img src="画像④" alt="" style="float-left;">
  <img src="画像⑤" alt="" style="float-left;">
  <img src="画像⑥" alt="" style="float-left;">
</div>

width指定などはしょってますが、各画像に float: left を指定しています。図解するとこういうことです。

至って単純な話です。2枚目のアメを舐めているオネエたまの縦幅が邪魔して左まで移動できないわけです。ここでわかるのは floatは高さが不揃な場合は適さない ということ。これがまずポイント。

vertical-alignの指定

ここから思考の展開です。img要素なのですから vertical-align で垂直位置の指定ができますよね。画像を上辺ではなく 下辺揃え にすれば移動を邪魔するものが無くなりますから解決するのではないか、と。

<div style="overflow: hidden;">
  <img src="画像①" alt="" style="float-left; vertical-align: bottom;">
  <img src="画像②" alt="" style="float-left; vertical-align: bottom;">
  <img src="画像③" alt="" style="float-left; vertical-align: bottom;">
  <img src="画像④" alt="" style="float-left; vertical-align: bottom;">
  <img src="画像⑤" alt="" style="float-left; vertical-align: bottom;">
  <img src="画像⑥" alt="" style="float-left; vertical-align: bottom;">
</div>

下揃えになりませんね。これは floatは高さが無くなるため余白の概念も無くなるから です。つまり縦方向の領域がありません。領域が無い中では「中央」「下」という概念も存在しませんよね。例えばビルの2階に居て、「下に降りてください」はできても、ビルの高さがゼロ、つまりビルが「無い」状態で「下に降りて」と言われても。「え?… どこのこと???」って話です。

ここでまた一つポイント。float要素に垂直位置の指定は効かない。

サンプルケースの結論

そもそもfloatを使う場面ではなかった、というのが結論です。バラバラの高さを持つ要素を並べるにはdisplayプロパティの inline-block値を利用するのが妥当です。しかも「画像」というimg要素なのですから、もとよりinline-blockと同じふるまいをする要素です。そのまま並べた様子が以下の通り。
* 注) 私の製作テンプレートは画像の垂直合わせデフォルトをbottomにしていますので、topに指定し直しています。

<div>
  <img src="画像①" alt=""><img src="画像②" alt=""><img src="画像③" alt=""><img src="画像④" alt=""><img src="画像⑤" alt=""><img src="画像⑥" alt="">
</div>

floatなんて要らんことする必要なし。そしてfloatではないので高さ出しのための親要素の overflow: hidden の指定も不要です。親を必要とするのは全体の横方向位置合わせか横幅の最大値指定ぐらいでしょうか。

注意点としてはimg要素間でソース改行を行わないことです。以下の記事を参照のこと。

inline-block の隙間を無くす方法

inline-block の隙間を無くす方法

display: inline-block が指定されている要素間および要素下にできる隙間の対処についてです。 要素自体が inline-block である、という認識が無い場合もありますので、隙間に悩んでいる場合はまずその要素のdisplay値が何になっているか、という点を調べてください。...

で、「なぜ左に寄らないのか」の件はここでもう答えが出ていますが、ここでちょっとまた疑問点が。floatというのはそもそもが「浮動化」などという物理法則を無視したものなんですよね、そして「そこに居ないかのように扱われる」のにそう扱われないパターンがあることはみなさんよくご存知だと思います。

回り込み

以下の例では画像とボックスが横に並んでいます。赤いボックスはdiv要素ですが display: inline-block を指定して横に並ぶようになっています。

画像に float: left を指定すると以下のようになります。

floatを指定された画像は「浮いている」ため存在しないかのようになっているわけですから、赤いボックスはfloat画像を無視して左隅、画像の背面に配置されます。

赤いボックスdiv要素の中に テキスト が入っていると以下のようになります。パソコンから閲覧中の方はブラウザの横幅をマウスで縮小して頂くとわかります。

いつも結果充分その学問どもという事の以外にきまっですた。
何でもかでもたくさんを意味者はあたかもわが病気ますだじゃがおっしゃれてくれないをは講演眺めるですでて、まだには描いたないうない。気持が得うのもよく場合がもっとたませです。
できるだけ大森さんに矛盾道具どう忠告がめがけで国家こういう農家あなたか学習がに対して
小教育ないたただが、その昨日は私か胃兵隊へ防ぐて、嘉納さんの方に人の私が同時に不助力と云えから私申からお鑑定がありようにしかるにお利用をするありないから、何でもかでもどうか関係で云っでがいで気をしまいた。

これが日本語表現で言うところの「回り込み」ですよね。「回り込み」という表現はfloatそのものをズバリと指し示しているわけではなくて、一定条件下で見られる特徴のひとつ を言っているだけなんですね。ですから
float = 回り込み
欧文でfloatに「回り込み」と表現を宛てることはありません。これは日本語の対訳をする人が頑張った、という感じで。欧文ではこれを表現するに

A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box.

A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float. If there is a line box, the outer top of the floated box is aligned with the top of the current line box

W3C recommendation

〝floatは現時点での行に沿って左または右へ移動するボックスです。floatの最も興味深い特徴は〟コンテンツがその側面に沿って流れる可能性があることです(もしくは「clear」プロパティによる禁則指定)。コンテンツは左floatボックスの右側と右floatボックスの左側に流れます。〟

〝フロートボックスは、その外側の端が別のフロートの外側の端またはブロックの端に触れるまで、左または右に移動します。行ボックスがある場合は、フローティングボックスの外側の上部と現在の行ボックスの上部が揃います。

行ボックスが有る場合は云々〜の見た目特性を日本語では「回り込み」と端的に表現できているわけです。これは一部の特徴説明であって、決してfloatイコール「回り込み」ではない、ということですね。日本語表現が独り歩きしてしまっただけ。

行ボックス

floatが「浮いて」おり、他のコンテンツがこの浮いた要素を無視するならば、結果的には以下のようになるのではないか、というのが通常の予測ですよね。(以下はスクショです)

こうして背面に配置されるのではないか。でも実際にはそうはならない。そうならないのが「回り込み」という特徴があるからだ、ということです。

行ボックス (line boxes) というのは「テキストが入ると予測され得る(内容にテキストが含まれている)ボックス」のことです。逆の言い方をすると 回り込みが発生するのは行ボックスと組み合わさった時のみ です。

まとめ

後半は理屈屁理屈で難しくなりましたが、ポイントをまとめたいと思います。

  • 高さが不揃いな要素を並べるのにfloatは向かない
  • float要素にvartical-align指定はできない
  • 高さが不揃いな要素を並べるにはinline-blockを利用する(画像は特に何も操作する必要なし)
  • floatは「浮動化」であって「回り込み」ではない

画像を意図的にfloatで並べる場面は少ないのではないかと思います。画像がdivに包含されている場合などは利用することもありますが。
とはいえブログサービスのエディターツールを利用した結果、意図せずfloatになってしまった、というケースも。「操作が簡単であること」は時として「その場(ブログサービス)を離れたら良くない結果を招く」ことも多いんですね。それはもうシステム上仕方がありません。

あと一番最初に掲載しているサンプルと、その下にあるfloatで並べたサンプルを比較すると、右側の余白の有無 に気づくと思います。floatの方は右に余白がありますよね。親要素に背景色がついていると丸わかりです。全ての画像右横にmarginが付いているためこうなります。

これも気になる人は気になると思います。この余白を消したい方は以下のソースを利用すると良いでしょう。flexで並べるサンプルコードです。画像を横3枚づつ横幅を揃えて並べる例です。

<div style="display: justify-content: space-between; flex-wrap: wrap; align-items: flex-start;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
  <img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">
</div>
Related post

Comments  6

オカンチ
2019/04/05 (Fri) 22:21

お忙しい中 毎回申し訳ないです
覚えが悪く 御手を煩わせる事が多いと思いますが 宜しくお願い致します
コチラを 勉強し直してみます ありがとう 

vanillaice (Akira)
Akira
2019/04/06 (Sat) 01:18

To オカンチさん

こんばんは。お返事こちらでまとめます。

はい。ご自分のペースでやってくださいね。
お疲れ様です :)

-
2019/04/12 (Fri) 23:20

管理人のみ閲覧できます

このコメントは管理人のみ閲覧できます

vanillaice (Akira)
Akira
2019/04/13 (Sat) 01:08

To luminousの件 内緒さん

こんばんは ('0')/

<img src="画像" alt="" style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;">

上記を以下の内容に変更します。

<div style="width: calc(100% / 3 - calc(15px / 2)); margin-bottom: 15px;"><a class="luminous" href="画像"><img src="画像" alt="" style="width: 100%"></a></div>

これを枚数分です。画像への style="width: 100%;" は恐らく不要ですが保険として(画像原寸の横幅がボックス横幅に満たない場合の保険)
よろしくお願いします。

-
2019/04/13 (Sat) 10:47

管理人のみ閲覧できます

このコメントは管理人のみ閲覧できます

vanillaice (Akira)
Akira
2019/04/13 (Sat) 15:26

To luminousの件 内緒さん(完了のご報告)

お出来になったということで良かったです。
親に display:flex の指定があり、その上で子要素にサイズ指定を行う時は「子」にサイズ指定、とメモしておくと良いですね。
今回のデフォルトの雛形の場合はaタグで囲うことによってimgではなくaの方が「子」になってしまいます。ですからさらにdivで囲ってそちらにサイズ指定、という方法になります。divが子ですね。

ここを覚えておくと何かと応用が効くと思います。
お疲れ様でした :)

コメントに関する注意事項
  • テンプレートに関するご質問は各テンプレート専用記事でのみ受付致します。また、よくある質問をまとめているページも事前にご参照ください。
  • 専門的なご質問の場合、記事内容と明らかに関連の無い内容はお控えください(雑談の場合はその限りではありません)
  • 第三者が不快と感じる内容や論調でのコメントはお控えください(性的,高圧的,暴力的など)