为什么将内联块元素向下推?


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/

Answers:


361

基本上,您已在代码中添加了更多混乱的代码,这造成了更多混乱,因此首先,我尝试消除阻碍理解真正问题的混乱情况。

首先,我们必须确定真正的问题是什么? 其“ inline-block”元素为何被向下推。

现在我们开始理解它,并先消除混乱。

1- 为什么不给所有三个div相同的边框宽度? 让我们给它。

2-浮动元素与向下插入的内嵌块元素有什么关系吗?不,与它无关。

因此,我们完全删除了该div。您还看到了内联块元素被向下推的相同行为。

接下来是一些文献资料,以了解线框的概念以及如何将它们排列在同一行中,特别是仔细阅读最后一段,因为这是您问题的答案。

“ inline-block”的基线是正常流中其最后一个线框的基线,除非它没有流入流线框,或者如果其“ overflow”属性的计算值不是“ visible”,则在这种情况下,基线是下边距。

如果您不确定基准,那么这里是简单的简短解释。

除了'gjpqy'以外的所有字符都写在基线上,您可以认为基线就像您在这些“随机字符”下方绘制一条与下划线相同的简单水平线一样,它将成为基线,但现在如果您编写任何“ gjpqy”同一行上的一个或多个字符,则这些字符的下部将落在该行下方。

因此,可以说除“ gjpqy”以外的所有字符都完全写在基线之上,而这些字符的某些部分则写在基线之下。

3-为什么不检查生产线的基线在哪里?我添加了一些字符来显示该的基线

4-为什么不在我们的div中添加一些字符以在div中找到它们的基线?此处,在div中添加了一些字符以阐明基线

现在,当您了解基线时,请阅读以下有关内联块基线的简化版本。

i)如果有问题的内联块的溢出属性设置为可见(默认情况下,因此无需设置)。然后,其基线将是该行包含块的基线。

ii)如果所讨论的内联块的溢出属性设置为“其他可见”。然后其底边距将在包含框的线的基线上。

  • 第一点详细

现在再来看一看,以澄清您的概念green div发生了什么。如果仍然有任何困惑,则在此处添加更多靠近绿色div的字符以建立包含块的基线,并对齐绿色div基线。

好吧,我现在声称它们具有相同的基准?对?

5-那么为什么不重叠它们,看看它们是否彼此合适?因此,我带来了第三个div -left:35px; 检查他们现在是否具有相同的基准

现在,我们已经证明了我们的第一点。

  • 第二点详细

好了,在解释了第一点之后,第二点很容易理解,您会看到将溢出属性设置为可见(隐藏)以外的第一格的底边在该线的基线上。

现在,您可以做一些实验以进一步说明。

  1. 设置first div溢出:可见(或将其完全删除)
  2. 设置第二个div溢出:除了visible
  3. 设置两个div溢出:除了visible

现在,带回您的混乱状况,看看一切是否都适合您。

  1. 回来的液浮格(当然有必要
    增加身体的某些宽度)你看它有没有效果。
  2. 恢复相同的奇数边距
  3. 绿色div设置为溢出:在您设置问题时可见(未对齐是由于边框宽度从1像素增加到5像素,因此如果向左调整负数,您将发现没有问题)
  4. 现在删除我添加的有助于理解的其他字符。(当然也要删除负数)
  5. 最后减小身体的宽度,因为我们不再需要更宽的身体

现在我们回到了起点。

希望我已经回答了你的问题。


1
感谢您提供如此出色的解释,但我没有明白您的意思:“那么它的基线就是该行包含块的基线。” 您在第二点明确指出的那条线是否与基线相同?
肖恩·泰勒

2
反应迟到。我只是注意到了同样的问题,我只想感谢Gary Lindahl对NICE的解释。
TimSPQR 2014年

+1 ntgCleaner即使我很欣赏好的答案,加里·林达希尔(Gary Lindahl)的阅读量还是很多,而我却只错过了几行写着“解决方案:XY”的内容
基本编码器,2016年

我发现这个详细的说明非常有用,谢谢。我为一个概念苦苦挣扎了一段时间,并做了一个更新的小提琴,可能会为其他概念弄清楚。
jonsanders101 '18

@ntgCleaner谢谢男人..即使经过所有解释,我也无法使它起作用。但您的评论确实是这样的:)
supersan

329

vertical-alignCSS中的默认值为baseline&,此规则也适用于inline-block阅读以下http://www.brunildo.org/test/inline-block.html

vertical-align:top在你的inline-blockDIV。

检查此http://jsfiddle.net/WGCyu/1/


3
你看过我的问题吗?我从来没有要求纠正这个问题。
肖恩·泰勒

23
@ShawnTaylor:问题标题很容易让人误解。我们本能地阅读标题,然后拍摄代码(如果有)。我们很少阅读实际的文本。这是一个坏习惯,但您可能应该了解为什么会发生。:P
Purag

@sandeep:关于您的编辑,然后为何即使从中删除了垂直对齐也将
Shawn Taylor

@sandeep:您提供的链接是有用的,但是由于它没有描述display:inline-block结合的行为,因此对这个问题没有帮助float:left/right
Zeta 2012年

2
@ThomasMcCabe几乎没有;如果有人发布了错误的答案,则不值得一票,以告知未来的观众,不管他们的好意是什么。就是说,我认为这个答案永远不会被否决。即使以其原始形式,它也提供了一个谜题的关键部分,被公认的答案所省略-基线对齐并不是元素垂直对齐的唯一方式,并且如果您更改vertical-align属性,则不会出现任何复杂性。接受的答案适用。
Mark Amery 2014年


9

查看替代示例。CSS3模块中描述了这种行为的原因:第3.2行。线盒包装[1]

通常,线盒的起始边缘接触其包含块的起始边缘,而末端边缘接触其包含块的终止边缘。但是,浮动框可能会位于包含块的边和线框边之间。因此,尽管相同内联格式上下文中的行框通常具有相同的内联进度(包含块的内联进度),但是如果由于浮动而减少了可用的内联进度,则它们可能会有所不同[...]

如您所见,尽管第三个元素没有overflow属性,但它被向下推。原因必须在其他地方。您注意到的第二种行为在层叠样式表2级修订1(CSS 2.1)规范:9.5 Floats [2]中进行了描述

由于浮动中没有浮动,因此在浮动框之前和之后创建的未定位块框将垂直流动,就好像浮动不存在一样。但是,根据需要缩短在浮点数旁边创建的当前和后续行框,以便为浮点数的边距框腾出空间。

在这种情况下,您所有的display:inline-block;div都使用一种特殊的10.8线高计算:'line-height'和'vertical-align'属性(两端)[3]baseline

“ inline-block”的基线是正常流中其最后一个线框的基线,除非它没有流入流线框,或者如果其“ overflow”属性的计算值不是“ visible”,则在这种情况下,基线是下边距。

因此,当您使用浮动元素和inline-block元素时,浮动元素将被推到一边,并且内联格式将根据1重新计算。另一方面,如果下一个元素不合适,则会缩短它们。由于您已经使用了最小的空间,因此没有其他方法可以修改元素然后将其压入2。在这种情况下,最高元素将定义包装div的大小,从而定义baseline 3,而另一方面,2中所述的位置和宽度的修改不能应用于这种最小间距的最大高度元素。在这种情况下,将产生我第一个演示中的行为。

最后,尽管我无法在第11节中找到原因,但您overflow:hidden将阻止#firstDiv被推到您的较低边缘的#container原因。没有它,则按23的定义和例外进行工作。演示版overflow:hidden

TL; DR:非常仔细地了解W3建议和浏览器中的实现。以我的拙见,如果您不知道浮动元素对周围元素所做的所有更改,它们就会决定表现出意外的行为。这是另一个演示,显示了浮点数的常见问题。


3
这个“标准”真是令人难以置信。令人惊奇的是,他们能够使这些内容在不同浏览器之间表现出一致性。哦,等等,不,他们从来没有能够做到这一点。
Triynko

6

我最初是从回答这个问题开始的,但是在完成之前它被锁定为dupe,所以我将答案发布在这里。

首先,我们需要了解什么inline-blockMDN中
定义说:

该元素生成一个块元素框,该框将随周围的内容一起流动,就好像它是单个内联框一样(与被替换的元素非常相似)

要了解这里发生的情况,我们需要查看vertical-align,它是默认值baseline

垂直位置可视化
在此图中,您具有以下颜色图表:
蓝色:基线
红色:行高
的顶部和底部绿色:内联内容框的顶部和底部。

在#left元素中,您确实具有一些控制基线的文本内容。这意味着其中的文本定义了#left的基线。
在#right中,没有任何内容,因此浏览器除了使用框底部作为基准外没有其他选择。

在这个可视化文件中,我在第一个内联容器包含一些文本,下一个为空的示例上绘制了基线:

绘制基线

如果您专门将一个元素与顶部对齐,则实际上是说您将该元素的顶部与行框的顶部对齐。

通过示例可能更容易理解。

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

问题是因为您在第二个div上应用了float:left。这会使第二个div出现在左侧,而您的第一个div下降并位于第二个div之后。如果您也在第一个div上应用float:left,您的问题将消失。

溢出:隐藏不会对您的布局造成任何问题,溢出:隐藏仅影响div的内部元素,与外部的其他元素无关。


好吧,如果它被推送是因为它在div浮动之后排第二,那么为什么thirdDiv不会向下移动?
肖恩·泰勒

因为第三div之前有第二个div,而第二个div没有float:left;
Pal Singh '02

但是在哪条规则中提到,如果某个div在浮动div之后出现,那么它将向下下降?我检查了w3.org。
肖恩·泰勒

不浮动的要素下降到基线,如果您进行了否决,我必须说这是最合乎逻辑的答案
Pal Singh 2012年

不,我没有投反对票,是的,您的答案不应该投反对票。刚刚投了赞成票。
肖恩·泰勒

0

尝试添加padding:0;到主体并删除div的边距。

background-color:*any除了背景*以外添加颜色以检查差异。


编辑答案以格式化代码,可以在开始代码之前和结束代码之后添加符号`来格式化代码。作为code例如:。background-color:any color
吉诺·沙吉

0

尝试使所有Elements的所有CSS属性相同。

我有类似的问题,并且在解决此问题时,我发现我将具有Font属性的Element放到Div Element中。

在删除具有Font属性的Element之后,所有DIV的对齐方式都受到干扰。要解决此问题,我将所有DIV元素的Font属性设置为与放入其中的元素相同。

在以下示例中,使用字体大小:30像素定义了类“ .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>" 
);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.