在 table-cell 元素中使用 float 属性可以向下滑动先前的内容

Posted

技术标签:

【中文标题】在 table-cell 元素中使用 float 属性可以向下滑动先前的内容【英文标题】:Using float property inside table-cell element slides previous content down 【发布时间】:2016-03-26 05:53:44 【问题描述】:

我正在尝试在具有 display:table-cell 属性的元素内使用浮动 div,但遇到了意外行为。

为什么第一列的元素会受到第二列的元素的影响(第一列的a突然下移了)?有什么办法可以防止这种行为吗?

.table 
    display: table;

.cell 
    display: table-cell;

.cell a 
    padding: .5em;
    border: .1em solid black;

.cell+.cell a 
    float: left;
<div class='table'>
    <div class='cell'>
        <a>cell1</a>
    </div>
    <div class='cell'>
        <a>cell2</a>
        <a>cell2</a>
    </div>
</div>

【问题讨论】:

请始终在您的问题中发布完整的代码示例。 我很想给你一个不同的解决方案(使用不同的方法),但首先,你会编辑你的问题,说明你为什么使用 display: table-cell 吗?这是一种非常具体的展示形式。我猜你已经习惯了旧的 布局形式并尝试了 布局,但是你很难跨越到好的一面哈哈
【参考方案1】:

迷人的行为。我有几个理论。虽然我同意使用display: table-cell 似乎是随机的,但它偶尔会用到它,所以我将把它留在那里等待我的回答。如果我的回答过于复杂,我很抱歉;我会尽量简化:

首先

要理解为什么元素被下推,需要理解垂直对齐对于table-cells 的工作原理:

应该用于table-cells 的唯一vertical-align 属性值是topmiddlebottom(请参阅this excellent css-tricks article)。其他任何事情都是未定义的行为——这意味着浏览器可以为所欲为,不同的浏览器可能会做不同的事情。这可能不是 [永远...] 我们想要的。

默认情况下,浏览器将给所有td 元素vertical-align: middle。因此,当您创建普通的 html table 时,您不必担心 vertical-align 属性。

另一方面,默认情况下,所有普通元素都有vertical-align: baseline。带有display: table-cell 的元素上的这个值会导致我们可怕的未定义行为。

您正在使用默认情况下不会像表格那样表现的元素手动构建表格(这就是为什么当您不完全确定自己在做什么时,您可能不应该使用display: table-cell) .因此,您必须自己设置 all 表格的默认样式。这包括为您的 .cells 指定 vertical-align: top|middle|bottom 属性。

那为什么我只在一个单元格中浮动元素时才会下推呢?

同样,这是未定义的行为。当您不浮动时,这似乎不会引起问题;元素仍然能够智能地找到内部文本的基线并垂直对齐它们,以便它们出现在您期望的位置。飘到这里,有两点需要注意:

1) 请记住,浮动会从 DOM 的正常流程中移除一个元素。这意味着其他元素,包括元素的父元素,无法像往常一样与该元素交互。

2) 记住table-cells 很聪明;他们可以动态地垂直定位他们的孩子

结合这两个让我想到当你浮动这些元素时:

1) 他们的.cell 父级正在丢失文本在其中的位置。

2) 它无法与基线所在的相邻单元正确通信——它只使用其底部边缘。

3) 相邻单元格正确地将其内容垂直对齐到该基线,从而导致向下移动。

解决办法?

负责任地将vertical-align: middle 放在您的.cells 上:

.cell 
    display: table-cell;
    vertical-align: middle;

a 标签也应该是display: inline-block)。这是更新的JSFiddle。问候。

【讨论】:

太棒了!唯一需要注意的是:a 标签应该是display: block。这样,所有“允许的”vertical-align 模式(顶部、中间、底部)都可以正常工作。不知道为什么 =) 谢谢。 你知道,bowheart,句子后面的两个空格是打字机需要的保留。在计算机上从来没有必要,并且无论如何在标记渲染中都会忽略第二个空格。 @TylerH 你提出来真是太有趣了。我实际上并不知道它起源于任何地方。所以谢谢。我向您保证,我完全清楚浏览器会将 HTML 中所有未转义的空白序列减少为单个空格字符。我从来没有(嗯,因为我很小)使用过打字机。这只是我作为作家/剧作家在所有写作中使用的个人偏好。每次看到句子拼凑在一起时,我都会有点烦。 @bowheart 是的,打字机对所有字符都使用单音间距,因为它们是纯机械的,因此有必要在句子之间创建两个空格,以便人们一眼就知道它们在哪里结束! (PS,很好的答案)【参考方案2】:

您在该规则 .cell+.cell a 中有一个加号(即:adjacent siblings selector),删除它会按预期工作:

.cell a 
  float: left;

http://jsfiddle.net/vg5j7xgc/5/

【讨论】:

如果操作真的需要表格单元格,这是一个很好的答案。但是 mu gut 告诉我,他可能不需要 table-cell。在我 10 多年的时间里,我认为我需要这个几次。 (y) 你能解释一下为什么元素被下推吗? 是的,但我只需要 cell2 中的 float:left 效果。我的问题主要是关于 CSS 机制的,因为我不明白为什么它会以这种方式工作。致 LOTUSMS:没有table-cell,我不知道达到所需行为的简单方法 @alirezasafian 如果删除 .css+.css a 规则,您将看到所有 3 个保持对齐,发生的情况是这样的规则将 float 元素应用于第二个和第三个单元格,因为两个 .cell 共享相同的父级,并且第一个 .css 紧接在第二个 .css 之前 @Razial 你试过 .cell:nth-child(2) background-color:red; jsfiddle.net/vg5j7xgc/9【参考方案3】:

CSS 2.1 says

单元格的基线是第一个流入线框的基线 在单元格中,或在单元格中的第一个流入表行中,以两者为准 先来。如果没有这样的行框或表格行,基线 是单元格框内容边缘的底部。

这是理解行为的关键。这是非常技术性的,所以我会试着把它分开。

第一个单元格有一个流入线框,由文本“cell1”组成。它的基线是文本的基线。

对于第二个单元格,所有非空白文本都通过 `float:left' 从流中移除,所有空白都通过普通空白规则移除。因此,它没有任何流入线框。它也不包含任何流入表行,因此单元格的基线位于单元格框内容边缘的底部。

由于表格单元格形成block formatting context,单元格的内容包括浮动,因此底部内容边缘是浮动的底部。

默认情况下,第一个单元格的垂直对齐值为baseline。因此,它必须与第二个单元格的基线对齐,即浮动的底部。

现在,第一个单元格中的 a 元素是不可替换的内联元素。 Its height rules说

内联非替换框的垂直内边距、边框和边距 从内容区的顶部和底部开始,和无关 与“线高”。但仅使用“行高”时 计算线框的高度。

...第一个表格单元格的高度是它的行框堆栈的高度,在这种情况下,它是它包含的唯一一行的行高。所以a元素填充和边框不会影响表格单元格的高度,实际上是转义了第一个表格单元格,如果添加background-color to the cells就可以看到

正如已经指出的那样,解决方案是add vertical-align:middle to the first cell。

【讨论】:

以上是关于在 table-cell 元素中使用 float 属性可以向下滑动先前的内容的主要内容,如果未能解决你的问题,请参考以下文章

display:table-cell; --布局神器

display:table-cell

布局神器display:table-cell

display,float,position的关系以及display=table,table-row,table-cell等属性的使用

float属性

如何让设置浮动的元素垂直居中