table 和 table-cell 上具有百分比宽度的奇怪行为
Strange behavior on table and table-cell with percentage width
我最近在这里偶然发现了一个问题,有人试图在他们的 headers 上获得适当的 line-behind 行为。像这样:
他们的实施在不同的 headers 中产生了不同的结果,因此产生了这个问题。通过对元素使用 table
而对 :before
和 :after
使用 table-cell
,实现非常奇怪。由此产生的行为对我来说非常令人惊讶。我在jsfiddle上做了个测试,你看看
你会看到我有两个类; a
和 b
,其中前者的宽度为 25%,后者的宽度为 40%。尽管如此,b
还是比 a
宽近 5 倍。将它们分别设置为 40% 和 45% 会使 b
是 a
的两倍。这是完全出乎意料的行为,仅相差 5%。文本的长度似乎也会影响这一点。
我知道这个实现很糟糕,它会 "break"。但是,我想知道 为什么 它打破了它的工作方式。这对我来说毫无意义。
div {
display: table;
background: grey;
margin: 10px 0;
}
div:before,
div:after {
width: 25%;
position: relative;
content: '';
border-top: 2px solid black;
display: table-cell;
}
div.b:before,
div.b:after {
width: 45%;
}
<div class="a">text</div>
<div class="a">some more text</div>
<div class="b">text</div>
<div class="b">some more text</div>
标准未指定自动表格布局,因此我建议不要使用这种百分比技巧,这可能会在某些浏览器上崩溃。
然而,大多数浏览器的行为似乎是这样的:
::before
和 ::after
伪元素将占 table 的指定百分比。
- 文本被包裹在一个具有文本宽度的匿名单元格中。那将代表伪元素留下的剩余百分比。
- table 的宽度将由上述约束决定。
因此,如果您有 width: 25%
,则文本将占用剩余的 50%
。
tablewidth = textwidth / 50% = 2 * textwidth
pseudowidth = 25% * tablewidth = 0.5 * textwidth
如果你有width: 40%
,正文就拿剩下的20%
。
tablewidth = textwidth / 20% = 5 * textwidth
pseudowidth = 40% * tablewidth = 2 * textwidth
如果你有width: 45%
,正文就拿剩下的10%
。也就是说,如果文本相同,table 将相对于前一种情况加倍宽度。
tablewidth = textwidth / 10% = 10 * textwidth
pseudowidth = 45% * tablewidth = 4.5 * textwidth
当然,如果按上述计算的所需 table 宽度超过包含块,事情就会开始变得棘手。然后
- table 将与包含块一样宽
文本单元格将具有解析伪元素剩余百分比的结果宽度。这将小于文本的首选宽度,因此文本将换行。
但是,文本单元格不会比文本所需的最小宽度窄。这通常是最长单词的宽度,但可能会因例如word-break: break-all
或 white-space: nowrap
.
文本剩余的space将平均分配给伪元素
如果剩余的 space 为负数,伪元素的宽度将为 0,并且 table 将增长(溢出包含块)以补偿它。
我最近在这里偶然发现了一个问题,有人试图在他们的 headers 上获得适当的 line-behind 行为。像这样:
他们的实施在不同的 headers 中产生了不同的结果,因此产生了这个问题。通过对元素使用 table
而对 :before
和 :after
使用 table-cell
,实现非常奇怪。由此产生的行为对我来说非常令人惊讶。我在jsfiddle上做了个测试,你看看
你会看到我有两个类; a
和 b
,其中前者的宽度为 25%,后者的宽度为 40%。尽管如此,b
还是比 a
宽近 5 倍。将它们分别设置为 40% 和 45% 会使 b
是 a
的两倍。这是完全出乎意料的行为,仅相差 5%。文本的长度似乎也会影响这一点。
我知道这个实现很糟糕,它会 "break"。但是,我想知道 为什么 它打破了它的工作方式。这对我来说毫无意义。
div {
display: table;
background: grey;
margin: 10px 0;
}
div:before,
div:after {
width: 25%;
position: relative;
content: '';
border-top: 2px solid black;
display: table-cell;
}
div.b:before,
div.b:after {
width: 45%;
}
<div class="a">text</div>
<div class="a">some more text</div>
<div class="b">text</div>
<div class="b">some more text</div>
标准未指定自动表格布局,因此我建议不要使用这种百分比技巧,这可能会在某些浏览器上崩溃。
然而,大多数浏览器的行为似乎是这样的:
::before
和::after
伪元素将占 table 的指定百分比。- 文本被包裹在一个具有文本宽度的匿名单元格中。那将代表伪元素留下的剩余百分比。
- table 的宽度将由上述约束决定。
因此,如果您有 width: 25%
,则文本将占用剩余的 50%
。
tablewidth = textwidth / 50% = 2 * textwidth
pseudowidth = 25% * tablewidth = 0.5 * textwidth
如果你有width: 40%
,正文就拿剩下的20%
。
tablewidth = textwidth / 20% = 5 * textwidth
pseudowidth = 40% * tablewidth = 2 * textwidth
如果你有width: 45%
,正文就拿剩下的10%
。也就是说,如果文本相同,table 将相对于前一种情况加倍宽度。
tablewidth = textwidth / 10% = 10 * textwidth
pseudowidth = 45% * tablewidth = 4.5 * textwidth
当然,如果按上述计算的所需 table 宽度超过包含块,事情就会开始变得棘手。然后
- table 将与包含块一样宽
文本单元格将具有解析伪元素剩余百分比的结果宽度。这将小于文本的首选宽度,因此文本将换行。
但是,文本单元格不会比文本所需的最小宽度窄。这通常是最长单词的宽度,但可能会因例如
word-break: break-all
或white-space: nowrap
.文本剩余的space将平均分配给伪元素
如果剩余的 space 为负数,伪元素的宽度将为 0,并且 table 将增长(溢出包含块)以补偿它。