なぜこのインラインブロック要素が押し下げられるのですか?


238

以下は私のコードです。なぜ #firstDivがすべてのブラウザによって押し下げられているのを理解したいと思います。どういうわけかそれを上に引っ張るのではなく、なぜ下に押されるのかという事実の内部の仕組みを本当に理解したいです。(そして私は彼らのトップを揃える方法を知っています:))

そして、私はそのoverflow:hiddenがそれを引き起こしていることを知っていますが、それがなぜそのdivを押し下げているのかはわかりません。

body {
  width: 350px;
  margin: 0px auto;
}

#container {
  border: 15px solid orange;
}

#firstDiv {
  border: 10px solid brown;
  display: inline-block;
  width: 70px;
  overflow: hidden;
}

#secondDiv {
  border: 10px solid skyblue;
  float: left;
  width: 70px;
}

#thirdDiv {
  display: inline-block;
  border: 5px solid yellowgreen;
}
<div id="container">
  <div id="firstDiv">FIRST</div>
  <div id="secondDiv">SECOND</div>
  <div id="thirdDiv">THIRD
    <br>some more content<br> some more content
  </div>
</div>

http://jsfiddle.net/WGCyu/

回答:


360

基本的に、コードに混乱を追加して混乱を引き起こしているため、最初に混乱を取り除き、実際の問題の理解を妨げます。

まず最初に、本当の問題は何かを確認する必要がありますか? その「inline-block」要素が下に押し下げられる理由

今、私たちはそれを理解し始め、最初に混乱を取り除きます。

1 - なぜ、すべての3つのdiv同じ境界線の幅を与えていませんか? あげましょう。

2-フローティングエレメントは、インラインブロックエレメントが押し下げられることと関係がありますか?いいえ、それはそれとは何の関係もありません。

そのため、そのdivを完全に削除しました。また、インラインブロック要素が同じように押し下げられるのと同じ動作が見られます。

ここで、いくつかの文献でラインボックスの概念と、それらが同じ行にどのように並べられるかを理解します。質問の答えがあるため、最後の段落を注意深く読んでください。

「インラインブロック」のベースラインは、インフローラインボックスがないか、「オーバーフロー」プロパティに「可視」以外の計算値がある場合を除き、通常のフローの最後のラインボックスのベースラインです。この場合、ベースラインはマージンの下端です。

ベースラインがわからない場合は、簡単な言葉で簡単に説明します。

'gjpqy'以外のすべての文字はベースラインに書き込まれます。ベースラインと考えることができるのは、これらの「ランダムな文字」のすぐ下に下線を引くのと同じように単純な水平線を描く場合です。ベースラインになりますが、 'gjpqy'を書き込むと同じ行にある文字は、これらの文字の下部が行の下に落ちます。

したがって、「gjpqy」以外のすべての文字はベースラインの上に完全に書き込まれ、これらの文字の一部はベースラインの下に書き込まれていると言えます。

3-ラインのベースラインがどこにあるかを確認してみませんか?ラインのベースラインを示す文字をいくつか追加しました。

4- divにもいくつかの文字を追加して、div内のベースラインを見つけますか?ここでは、ベースラインを明確にするためいくつかの文字がdivに追加されています

ベースラインについて理解したら、インラインブロックのベースラインに関する以下の簡略版をお読みください。

i)問題のインラインブロックのオーバーフロープロパティが可視に設定されている場合(デフォルトで設定されているため、設定する必要はありません)。次に、そのベースラインは、ラインを含むブロックのベースラインになります。

ii)問題のインラインブロックのオーバーフロープロパティがOTHER THANN THANに設定されている場合。次に、その下部マージンは、ボックスを含む行のベースラインになります。

  • 最初のポイントの詳細

今、何が緑のdivで起こっていることを、あなたの概念を明確にするために、再度これを見て。まだ混乱がある場合ここに緑のdivの近くにさらに文字を追加して、包含ブロックのベースラインを確立し、緑のdivベースラインを揃えます。

さて、私は今彼らが同じベースラインを持っていると主張していますか?正しい?

5-次に、それらを重ねて、それらが互いに正しく合っているかどうかを確認しませんか?そこで、3つ目のdiv -left:35pxを使用します。彼らが今同じベースラインを持っているかどうかを確認するには

これで、最初のポイントが証明されました。

  • 2番目のポイントの詳細

さて、最初のポイントの説明の後、2番目のポイントは簡単に消化でき、オーバーフロープロパティが可視(非表示)以外に設定されている最初のdivには、ラインのベースラインの下マージンがあります。

これで、さらに説明するためにいくつかの実験を行うことができます。

  1. 最初のdiv overflow:visibleを設定します(または完全に削除します)
  2. 2番目のdivオーバーフローを設定:visible以外
  3. 両方のdivオーバーフローを設定します:visible以外

今あなたの混乱を取り戻し、すべてがあなたのためにうまく見ているかどうかを確認します。

  1. 持参あなたのFLOATEDのdivをバック(もちろんする必要がある
    身体の一部の幅を広げるには)あなたが、それは効果がありません参照してください。
  2. 同じ奇数のマージンを元に戻します。
  3. セットオーバーフローの緑のdiv:目に見えるあなたは、あなたの質問に設定された(アライメントずれがあればそう5pxのために1ピクセルから境界線の幅の増加によるものであることを否定は左に調整し、あなたが何も問題はありません表示されます)
  4. 次に、理解を助けるために追加した文字を削除します。(もちろん、負の左を削除します)
  5. 幅の広いものは必要なくなったので、最後に本体の幅を減らします。

そして今、私たちは元の場所に戻っています。

うまくいけば、私はあなたの質問に答えました。


1
そのような素晴らしい説明をありがとう、しかし私はあなたのポイントを理解しませんでした。2番目のポイントで明らかにしたように、ラインのベースラインと同じですか?
ショーンテイラー

2
遅い対応。私は同じ問題を指摘したばかりであり、NICEの説明をしてくれたGary Lindahlに感謝したいと思います。
TimSPQR 2014年

+1 ntgCleaner私は良い答えに感謝しますが、Gary Lindahlは読むのがたくさんあるので、「Solution:XY」と書かれている数行だけを見逃しています
Basic Coder

この詳細な説明は非常に有益であると思いました。ありがとうございます。私はしばらくの間、1つの概念に苦労し、他の人に明らかになるように更新されたフィドルを作成しました。
jonsanders101 2018年

@ntgCleanerおかげで男..すべての説明の後でさえ、私はそれを機能させることができませんでした。しかしあなたのコメントはそれをしました:)
supersan

329

vertical-alignCSS ののデフォルト値はbaseline&であり、このルールはinline-blockこのhttp://www.brunildo.org/test/inline-block.htmlを読んでも適用されます

DIVに書き込みvertical-align:topますinline-block

これを確認してくださいhttp://jsfiddle.net/WGCyu/1/


3
私の質問を読みましたか?私は問題を修正するように頼んだことはありません。
ショーンテイラー

23
@ShawnTaylor:質問のタイトルは非常に誤解を招くものです。私たちは本能的にタイトルを読み、コードがある場合はそれを撮影します。実際のテキストはめったに読みません。それは悪い習慣ですが、なぜそれが起こるのかを理解する必要があります。:P
Purag

@sandeep:編集について、次に、firstDivが垂直方向の
Shawn Taylor

@sandeep:提供されたリンクは参考情報ですが、とのdisplay:inline-block組み合わせの動作を説明していないため、この質問には役立ちませんfloat:left/right
ゼータ

2
@ThomasMcCabeほとんどありません。誰かが悪い答えを投稿した場合、その意図にかかわらず、将来の視聴者に何か問題があることを知らせるために反対票を投じる価値があります。とは言っても、この答えが反対票に値することはないと思います。元の形式であっても、受け入れられた答えによって省略されたパズルの重要な部分を提供しました。そのベースラインの配置は、要素が垂直に配置される唯一の方法ではありません。また、vertical-alignプロパティを変更した場合、受け入れられた回答が適用されます。
マークアメリー2014年


9

見るこの変形例を。このような動作の理由は、CSS3モジュールで説明されています:行:3.2。ラインボックスラッピング[1]

一般に、ラインボックスの開始エッジは、その包含ブロックの開始エッジに接触し、終了エッジは、その包含ブロックの終了エッジに接触します。ただし、浮動ボックスは、包含ブロックエッジとラインボックスエッジの間にある場合があります。したがって、同じインラインフォーマットコンテキスト内のラインボックスは、一般に同じインライン進行の進行(包含ブロックの進行進行)を持っていますが、floats [...]により使用可能なインライン進行スペースが減少した場合、変化する可能性があります。

ご覧のとおり、3番目の要素にはoverflowプロパティがありませんが、下に押されています。その理由は、どこかほかの場所にあるはずです。2番目の動作は、カスケードスタイルシートレベル2リビジョン1(CSS 2.1)仕様で説明されています:9.5フロート[2]

フロートはフロート内にないため、フロートボックスの前後に作成された非配置ブロックボックスは、フロートが存在しないかのように垂直にフローします。ただし、フロートの隣に作成された現在のラインボックスと後続のラインボックスは、フロートのマージンボックス用のスペースを確保するために必要に応じて短縮されます。

この場合display:inline-block;、すべてのdivは特別な種類の10.8行の高さの計算を使用しています: 'line-height'および 'vertical-align'プロパティ(一番端)[3]baseline

「インラインブロック」のベースラインは、インフローラインボックスがないか、「オーバーフロー」プロパティに「可視」以外の計算値がある場合を除き、通常のフローの最後のラインボックスのベースラインです。この場合、ベースラインはマージンの下端です。

そのため、フローティング要素とinline-block要素を使用している場合、フローティング要素は横にプッシュされ、インラインフォーマットは1に従って再計算されます。一方、次の要素は、収まらない場合は短縮されます。既に最小限のスペースで作業しているので、要素を変更してからプッシュする方法は他にありません2。この場合、最も高い要素はラッピングdivのサイズを定義し、したがってbaseline 3を定義しますが、一方で、2で述べた位置と幅の変更は、そのような最小間隔の最大高さの要素には適用できません。この場合、私の最初のデモのような動作になります。

最後に、その理由は、あなたがoverflow:hidden防ぐことができます#firstDivあなたの下縁部にプッシュされるように#container私は理由を見つけることができませんでしたが、セクション11を。これがなければoverflow:hidden23で例外として定義されたとおりに機能します。デモ

TL; DR: W3の推奨事項とブラウザーでの実装をよく確認してください。私の控えめな意見では、浮動要素は、周囲の要素に対して行われるすべての変更を知らないと、予期しない動作を示すと判断されます。次に、フロートに関する一般的な問題を示す別のデモを示します。


3
この「標準」は信じられないほどの混乱です。彼らがこのものをブラウザ間で一貫して動作させることができたことは驚くべきことです。ええと、いや、彼らはそれをすることができたことは一度もない。
Triynko 2016年

6

もともとはこの質問への回答を始めましたが、回答が完了する前に重複としてロックされていたため、代わりにここに回答を投稿しました。

まず、何であるかを理解する必要inline-blockがあります。MDN
定義によれば、

要素はブロック要素ボックスを生成し、単一のインラインボックスであるかのように周囲のコンテンツと共に流されます(置き換えられた要素と同じように動作します)。

ここで何が起こっているのかを理解するには、を調べる必要がありvertical-alignますbaseline。これはデフォルト値です。

垂直位置の視覚化
この図には、次のカラーチャートがあります。
青:ベースライン
赤:行の高さ
の上部と下部緑:インラインコンテンツボックスの上部と下部。

#left要素には、ベースラインを制御するテキストコンテンツがあります。これは、内部のテキストが#leftのベースラインを定義することを意味します。
#rightにはコンテンツがないため、ブラウザーにはボックスの下部をベースラインとして使用する以外のオプションがありません。

最初のインラインコンテナーにテキストがあり、次のコンテナーが空である例のベースラインを描画したこのビジュアライゼーションを見てみましょう。

描かれたベースライン

特に1つの要素を上に配置する場合、この要素の上端を行ボックスの上端に配置すると本当に言います。

これは例によって理解しやすいかもしれません。

div {
    display: inline-block;
    width: 100px;
    height: 150px;
    background: gray;
    vertical-align: baseline;
}
div#middle {
    vertical-align: top;
    height: 50px
}
   
div#right {
    font-size: 30px;
    height: 100px
}
<div id="left">
  <span>groovy</span>
</div>
<div id="middle">groovy</div>

<div id="right">groovy</div>

結果はこれです-そして、私は青いベースラインと赤いラインボックスを追加しました: ここで何が起こるかは、ラインボックスの高さがライン全体のコンテンツがどのようにレイアウトされるかに依存していることです。つまり、上部の線形を計算するには、まずベースラインの線形を計算する必要があります。要素が有し、これは、ベースラインの位置決めのために使用されません。ただし、およびは、ベースラインが揃うように垂直に配置されます。これを行うと、フォントサイズが大きくなったために要素が少し押し上げられたため、行ボックスの高さが増加しました。次に、要素の上部の位置を計算できます。これは、線ボックスの上部に沿っています。垂直方向の位置合わせについて説明しました
#middlevertical-align:top#left#right#right#middle


1

問題は、2番目のdivにfloat:leftを適用したためです。これにより、2番目のdivが左側に来るようになり、最初のdivが2番目のdivの後ろに下がります。最初のdivにもfloat:leftを適用すると、問題はなくなります。

overflow:hiddenはレイアウトに問題を引き起こしません。overflow:hiddenはdivの内部要素にのみ影響し、外部にある他の要素とは関係ありません。


フロートされたdivの2番目に来るためにプッシュされた場合、thirdDivが下がらないのはなぜですか?
ショーンテイラー

3番目のdivの前に2番目のdivがあるため、float:leftがありません。
パルシン

しかし、このルールは、フロートされたdivの後にdivが来る場合、それは下に落ちることをどこで述べていますか?w3.orgをチェックしました。
ショーンテイラー

浮動ではない要素はベースラインに下がり、反対票を投じた場合は、それが最も論理的な答えであると言わざるを得ません
パルシン

いいえ、私は反対票を投じなかったし、はいあなたの答えは反対に値しない。ただ上向きに投票した。
ショーンテイラー

0

padding:0;本文に追加して、divのマージンを削除してみてください。

background-color:*any背景とは別に色を追加して*、違いを確認します。


コードをフォーマットするための回答を編集します。コードを開始する前と終了した後に記号 `を追加して、コードをフォーマットできます。code例えば:。background-color:any color
JINO SHAJI 2017

0

すべての要素のすべてのCSSプロパティを同じにしてみてください。

同様の問題があり、これを修正しているときに、Fontプロパティを持つ要素をDiv要素にドロップしていることがわかりました。

Fontプロパティを持つその要素を削除した後、すべてのDIVの配置が乱されました。これを修正するには、Fontプロパティを、ドロップされた要素と同じようにすべてのDIV要素に設定します。

次の例では、font-size:30 pxで定義されたクラス「.dldCuboidButton」のDropped要素。

そのため、DIV要素で使用される.cuboidRecycle、.liCollect、.dldCollectなどの残りのクラスに同じプロパティを追加しました。このようにして、すべてのDIV要素は、要素をそこにドロップする前と後の同じ測定値に従います。

.cuboidRecycle {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.liCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}

.dldCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#009933;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.dldCuboidButton {
    background-color:  #7c6436;
    color: white; /* White text */
    font-size: 30px; /* Set a font-size */
    border-radius: 8px;
    margin-top: 1px;
  }

上記のCSSを使用して動的に作成されたHTMLの例を次に示します。

$("div#tabs").append(
  "<div id='" + newTabId + "'>#" + uniqueId + 
  "<input type=hidden id=hdn_tmsource_" + uniqueId + "  value='" + divTmpfest + "'>" + 
  "<input type=hidden id=leCuboidInfo_" + uniqueId + " value=''>" + 
  "<div id='" + divRecycleCuboid + "' class=cuboidRecycle ondrop='removeDraggedCuboids(event, ui)'  ondragover='allowDrop(event)'><font size='1' color='red'> Trash bin </font></div>" +
  "<div id='" + divDropLeCuboid  + "' class=liCollect ondrop='dropForLinkExport(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Manifest Cuboid here</font></div>" +
  "<div id='" + divDropDwldCuboid  + "' class=dldCollect ondrop='dropForTMEntry(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Cuboids here..</font></div>" +
  "</div>" 
);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.