Fieldset 图例 CSS 渲染行为在最近几个月发生了变化……发生了什么事?
Fieldset legend CSS rendering behavior has changed in recent months... what happened?
我有一个包含各种嵌套 <fieldset>
元素的表单,每个元素都有一个 <legend>
,今天我发现在我检查过的所有浏览器上我的网页都存在错误(Chrome、Firefox、Opera),之前(6-12 个月前)不存在。
有一个 <span class="undo">
元素,它使用 background-image
显示为绿色卷曲箭头。目的是当周围的 <fieldset>
有 class="modified"
时显示它,否则隐藏 --- 这是通过更改跨度的 width
来实现的。
旧行为(仍然出现在我的 Chromebook 运行 Chrome OS 76.0.3809.136 上)与我的意图一致呈现:
新行为(在我的 Windows 10 PC 上的 Chrome 87.0.4280.88 上)出于某种原因将“Foo 配置器”换行成两行。
是否最近浏览器渲染发生了某些变化导致了这种情况?如果是,怎么办?我该如何解决?
HTML:
<!DOCTYPE html>
<head><style type="text/css">
form {
max-width: 500px;
}
body {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
}
fieldset {
padding: 0;
}
fieldset > legend {
font-size: 90%;
margin-left: 0.5em;
}
span.undo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADEklEQVQ4jY2UXSxbYRjHn/ecnm5lLFTbxdIlbENTq0x8JD62RBHRm/lKCBIXJGw3jbhtuCERVy6wyDJEYhLbMuKiDYmwIRITESQNq1LZaFg5ynrannN2ceR1VrT7X53n/f/PL8/7CXxQzdnnGicbg2cESeAW8cD3f+83mo3qSDUPPAJ0W1IQ4nn++ijDMs2W5r7lPp7npaS0VFOqCFNoFBp9nD5BnvC/oAP3QeXHytnd2etpAhHZ6uzWl6158XkBPQaCln8uV4xV2E/swWaBUP3z+u6ibhkluxk0YZ2o/lzt9rqDULD0cfrxqvFwKlwoyba2Nuyp76s1MRqaoffoPY7n8LiMkoVRYQzLiEE7Jzs7rp0STQlCKBBEkZRWqa3V1VY/q5bL5I5Th8vjAgCdSrf5ZjNLnWVz2fbpfZxfd65rFVqtUhs4tQD5Of+sfXZgdWDGPmM32imC8rE+o9nYu9yLM4nyxPXX6xJCEgyE5fK4IqWRJEECAMuxhg8Gy7YFu5YaS+HjQkIofKxvwbGw4dzg4QZu1N0ogQIAJEF26jsJRGDXvG0GAAIAPH5P/nB+9vts3VudacYUssGUBylJMUm4XPm1cgmy/LDM7c4BAMdzXfNdp57TkKxEeSL+Pjw/vASJ//SyXueFMyRIvLLCEScAIDYiVhzacG6EoAC/ebSJS+F3AgCSlckS4uoZGF4bDg5a2l/a+r2Fy7TYtEuQ6p4q42EGNsat41O2qdsoDMu0TLWIp1b8tPgShAA1pjVig+XYqk9V83vz1ykXvou6L3ViS6fS5TzKAXyy/Zw/812msJGCpKS0IbWhPrU+KSaJIqjjP8fmbXPHtw7rkRVnEEKTVZNCR1cne+1wLXcgl2bogC4i7kRQBEUztJ/zB1hNaU09hh5h1/65IuZtc/lY+bn3/LYFEqtMUzZSNiIlpUJJiL2iJ0WjZaOKMEVwBEKoRlcz+GoQUwI7EnTgPmj/2j60OnTmPbuOSI9NN70wGRIMIZ5aLJfHNW2bXnQsOmiHj/VFy6K1Sm1BfEGyMll8Y7H+AvtLjkoh3mWsAAAAAElFTkSuQmCC');
display: inline-block;
height: 13px;
width: 1em;
font-size: 13px;
background-repeat: no-repeat;
background-size: 13px;
margin-top: 2px;
margin-right: -2px;
}
legend > span.undo {
width: 0em;
}
fieldset.modified > legend > span.undo {
width: 1em;
}
div.description {
padding-left: 4px;
font-size: 90%;
}
</style></head>
<body>
<form>
<fieldset class="field">
<legend title="">Foo configurator<span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="foo_type" type="radio" value="123">Foo #1</label> <div class="description">First foo</div>
<span class="field-content">
<label><input name="foo_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
<fieldset class="field modified">
<legend title="">Bar configurator<span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="bar_type" type="radio" value="123">Bar #1</label> <div class="description">First bar</div>
<span class="field-content">
<label><input name="bar_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
</form>
</body>
</html>
至于行为改变的原因是什么,我也说不清楚。
同时,您可以通过添加
来修复此行为
white-space: nowrap;
到您的图例元素,或
legend > span.undo { display: none; }
fieldset.modified > legend > span.undo { display: inline-block; }
似乎也能完成这项工作,以及删除负边距
span.undo { margin-right: 0; }
如果您在 Chrome 76 上可以正确看到它,则可能是通过在 Chrome 77 中打开 LayoutNG 引入了此更改,该版本已于 2019 年发布,但它的某些部分后来出现了。例如,我知道我在文本区域中的布局有些不一致,直到大约去年才不得不修改。
最好用Chrome 77 测试一下,看是否真的是这个东西。
无论如何,这看起来像是 margin-right: -2px
和 width: 0em
之间的相互作用,它以某种方式将布局计算为溢出并添加新行。
通过使用 BrowserStack,我发现它在 Chrome 86 中发生了变化,恰好是 Chrome 实现了 flex and grid for fieldsets 的版本。他们可能也需要细微的改变才能做到这一点。
负边距将 legend
的右边框向左拉 2px,从而将图例的宽度减少 2px。当您在 span.undo
上设置 width:0em
时,负边距仍然起作用。但是现在 legend
的宽度短了 2px 以在同一行上呈现标题文本,因此它会换行。
我们可以模拟这种行为。见代码注释。
* {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
font-size: 16px;
}
/* legend is behaving like a block element with width fit-content */
div {
border: 1px solid;
width: fit-content;
}
/* undo icon is inline-block */
span {
display: inline-block;
}
/* title text */
span:first-child {
color: green;
}
/* undo elements with negative margins */
.negative-margin1 {
margin-right: -20px;
}
.negative-margin2 {
margin-right: -40px;
}
.negative-margin3 {
margin-right: -49px;
}
<div class="one"><span>Foo efg </span> <span>undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin1">undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin2">undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin3">undo</span></div>
随着负边距减小宽度,内联文本开始换行。
根据您的字体大小,输出可能会略有不同,因此这是它的预期外观:
我们可以通过对 padding 做一些调整来避免负边距:
form {
max-width: 500px;
}
body {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
}
fieldset {
padding: 0;
}
fieldset>legend {
font-size: 90%;
margin-left: 0.5em;
/* set padding right to zero */
padding-right: 0;
}
/* but we want 2px margin right for the title text */
span.ttl {
margin-right: 2px;
}
span.undo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADEklEQVQ4jY2UXSxbYRjHn/ecnm5lLFTbxdIlbENTq0x8JD62RBHRm/lKCBIXJGw3jbhtuCERVy6wyDJEYhLbMuKiDYmwIRITESQNq1LZaFg5ynrannN2ceR1VrT7X53n/f/PL8/7CXxQzdnnGicbg2cESeAW8cD3f+83mo3qSDUPPAJ0W1IQ4nn++ijDMs2W5r7lPp7npaS0VFOqCFNoFBp9nD5BnvC/oAP3QeXHytnd2etpAhHZ6uzWl6158XkBPQaCln8uV4xV2E/swWaBUP3z+u6ibhkluxk0YZ2o/lzt9rqDULD0cfrxqvFwKlwoyba2Nuyp76s1MRqaoffoPY7n8LiMkoVRYQzLiEE7Jzs7rp0STQlCKBBEkZRWqa3V1VY/q5bL5I5Th8vjAgCdSrf5ZjNLnWVz2fbpfZxfd65rFVqtUhs4tQD5Of+sfXZgdWDGPmM32imC8rE+o9nYu9yLM4nyxPXX6xJCEgyE5fK4IqWRJEECAMuxhg8Gy7YFu5YaS+HjQkIofKxvwbGw4dzg4QZu1N0ogQIAJEF26jsJRGDXvG0GAAIAPH5P/nB+9vts3VudacYUssGUBylJMUm4XPm1cgmy/LDM7c4BAMdzXfNdp57TkKxEeSL+Pjw/vASJ//SyXueFMyRIvLLCEScAIDYiVhzacG6EoAC/ebSJS+F3AgCSlckS4uoZGF4bDg5a2l/a+r2Fy7TYtEuQ6p4q42EGNsat41O2qdsoDMu0TLWIp1b8tPgShAA1pjVig+XYqk9V83vz1ykXvou6L3ViS6fS5TzKAXyy/Zw/812msJGCpKS0IbWhPrU+KSaJIqjjP8fmbXPHtw7rkRVnEEKTVZNCR1cne+1wLXcgl2bogC4i7kRQBEUztJ/zB1hNaU09hh5h1/65IuZtc/lY+bn3/LYFEqtMUzZSNiIlpUJJiL2iJ0WjZaOKMEVwBEKoRlcz+GoQUwI7EnTgPmj/2j60OnTmPbuOSI9NN70wGRIMIZ5aLJfHNW2bXnQsOmiHj/VFy6K1Sm1BfEGyMll8Y7H+AvtLjkoh3mWsAAAAAElFTkSuQmCC');
display: inline-block;
height: 13px;
width: 1em;
font-size: 13px;
background-repeat: no-repeat;
background-size: 13px;
margin-top: 2px;
/*margin-right: -2px; we don't need this now*/
}
legend>span.undo {
width: 0em;
}
fieldset.modified>legend>span.undo {
width: 1em;
}
div.description {
padding-left: 4px;
font-size: 90%;
}
<form>
<fieldset class="field">
<legend title=""><span class='ttl'>Foo configurator</span><span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="foo_type" type="radio" value="123">Foo #1</label>
<div class="description">First foo</div>
<span class="field-content">
<label><input name="foo_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
<fieldset class="field modified">
<legend title=""><span class='ttl'>Bar configurator</span><span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="bar_type" type="radio" value="123">Bar #1</label>
<div class="description">First bar</div>
<span class="field-content">
<label><input name="bar_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
</form>
因此,我们可以在 parent 元素上设置 0 填充,而不是在 child 上设置负边距。
在当前版本(100.0.4896.88)中,Chrome默认将以下CSS分配给图例元素:
legend {
display: block;
padding-inline-start: 2px;
padding-inline-end: 2px;
border-width: initial;
border-style: none;
border-color: initial;
border-image: initial;
}
我们需要检查它在早期版本中是否不同。
我有一个包含各种嵌套 <fieldset>
元素的表单,每个元素都有一个 <legend>
,今天我发现在我检查过的所有浏览器上我的网页都存在错误(Chrome、Firefox、Opera),之前(6-12 个月前)不存在。
有一个 <span class="undo">
元素,它使用 background-image
显示为绿色卷曲箭头。目的是当周围的 <fieldset>
有 class="modified"
时显示它,否则隐藏 --- 这是通过更改跨度的 width
来实现的。
旧行为(仍然出现在我的 Chromebook 运行 Chrome OS 76.0.3809.136 上)与我的意图一致呈现:
新行为(在我的 Windows 10 PC 上的 Chrome 87.0.4280.88 上)出于某种原因将“Foo 配置器”换行成两行。
是否最近浏览器渲染发生了某些变化导致了这种情况?如果是,怎么办?我该如何解决?
HTML:
<!DOCTYPE html>
<head><style type="text/css">
form {
max-width: 500px;
}
body {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
}
fieldset {
padding: 0;
}
fieldset > legend {
font-size: 90%;
margin-left: 0.5em;
}
span.undo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADEklEQVQ4jY2UXSxbYRjHn/ecnm5lLFTbxdIlbENTq0x8JD62RBHRm/lKCBIXJGw3jbhtuCERVy6wyDJEYhLbMuKiDYmwIRITESQNq1LZaFg5ynrannN2ceR1VrT7X53n/f/PL8/7CXxQzdnnGicbg2cESeAW8cD3f+83mo3qSDUPPAJ0W1IQ4nn++ijDMs2W5r7lPp7npaS0VFOqCFNoFBp9nD5BnvC/oAP3QeXHytnd2etpAhHZ6uzWl6158XkBPQaCln8uV4xV2E/swWaBUP3z+u6ibhkluxk0YZ2o/lzt9rqDULD0cfrxqvFwKlwoyba2Nuyp76s1MRqaoffoPY7n8LiMkoVRYQzLiEE7Jzs7rp0STQlCKBBEkZRWqa3V1VY/q5bL5I5Th8vjAgCdSrf5ZjNLnWVz2fbpfZxfd65rFVqtUhs4tQD5Of+sfXZgdWDGPmM32imC8rE+o9nYu9yLM4nyxPXX6xJCEgyE5fK4IqWRJEECAMuxhg8Gy7YFu5YaS+HjQkIofKxvwbGw4dzg4QZu1N0ogQIAJEF26jsJRGDXvG0GAAIAPH5P/nB+9vts3VudacYUssGUBylJMUm4XPm1cgmy/LDM7c4BAMdzXfNdp57TkKxEeSL+Pjw/vASJ//SyXueFMyRIvLLCEScAIDYiVhzacG6EoAC/ebSJS+F3AgCSlckS4uoZGF4bDg5a2l/a+r2Fy7TYtEuQ6p4q42EGNsat41O2qdsoDMu0TLWIp1b8tPgShAA1pjVig+XYqk9V83vz1ykXvou6L3ViS6fS5TzKAXyy/Zw/812msJGCpKS0IbWhPrU+KSaJIqjjP8fmbXPHtw7rkRVnEEKTVZNCR1cne+1wLXcgl2bogC4i7kRQBEUztJ/zB1hNaU09hh5h1/65IuZtc/lY+bn3/LYFEqtMUzZSNiIlpUJJiL2iJ0WjZaOKMEVwBEKoRlcz+GoQUwI7EnTgPmj/2j60OnTmPbuOSI9NN70wGRIMIZ5aLJfHNW2bXnQsOmiHj/VFy6K1Sm1BfEGyMll8Y7H+AvtLjkoh3mWsAAAAAElFTkSuQmCC');
display: inline-block;
height: 13px;
width: 1em;
font-size: 13px;
background-repeat: no-repeat;
background-size: 13px;
margin-top: 2px;
margin-right: -2px;
}
legend > span.undo {
width: 0em;
}
fieldset.modified > legend > span.undo {
width: 1em;
}
div.description {
padding-left: 4px;
font-size: 90%;
}
</style></head>
<body>
<form>
<fieldset class="field">
<legend title="">Foo configurator<span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="foo_type" type="radio" value="123">Foo #1</label> <div class="description">First foo</div>
<span class="field-content">
<label><input name="foo_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
<fieldset class="field modified">
<legend title="">Bar configurator<span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="bar_type" type="radio" value="123">Bar #1</label> <div class="description">First bar</div>
<span class="field-content">
<label><input name="bar_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
</form>
</body>
</html>
至于行为改变的原因是什么,我也说不清楚。
同时,您可以通过添加
来修复此行为white-space: nowrap;
到您的图例元素,或
legend > span.undo { display: none; }
fieldset.modified > legend > span.undo { display: inline-block; }
似乎也能完成这项工作,以及删除负边距
span.undo { margin-right: 0; }
如果您在 Chrome 76 上可以正确看到它,则可能是通过在 Chrome 77 中打开 LayoutNG 引入了此更改,该版本已于 2019 年发布,但它的某些部分后来出现了。例如,我知道我在文本区域中的布局有些不一致,直到大约去年才不得不修改。
最好用Chrome 77 测试一下,看是否真的是这个东西。
无论如何,这看起来像是 margin-right: -2px
和 width: 0em
之间的相互作用,它以某种方式将布局计算为溢出并添加新行。
通过使用 BrowserStack,我发现它在 Chrome 86 中发生了变化,恰好是 Chrome 实现了 flex and grid for fieldsets 的版本。他们可能也需要细微的改变才能做到这一点。
负边距将 legend
的右边框向左拉 2px,从而将图例的宽度减少 2px。当您在 span.undo
上设置 width:0em
时,负边距仍然起作用。但是现在 legend
的宽度短了 2px 以在同一行上呈现标题文本,因此它会换行。
我们可以模拟这种行为。见代码注释。
* {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
font-size: 16px;
}
/* legend is behaving like a block element with width fit-content */
div {
border: 1px solid;
width: fit-content;
}
/* undo icon is inline-block */
span {
display: inline-block;
}
/* title text */
span:first-child {
color: green;
}
/* undo elements with negative margins */
.negative-margin1 {
margin-right: -20px;
}
.negative-margin2 {
margin-right: -40px;
}
.negative-margin3 {
margin-right: -49px;
}
<div class="one"><span>Foo efg </span> <span>undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin1">undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin2">undo</span></div>
<div class="two"><span>Foo efg </span> <span class="negative-margin3">undo</span></div>
根据您的字体大小,输出可能会略有不同,因此这是它的预期外观:
我们可以通过对 padding 做一些调整来避免负边距:
form {
max-width: 500px;
}
body {
font-family: "Segoe UI", "Lucida Grande", Arial, sans-serif;
}
fieldset {
padding: 0;
}
fieldset>legend {
font-size: 90%;
margin-left: 0.5em;
/* set padding right to zero */
padding-right: 0;
}
/* but we want 2px margin right for the title text */
span.ttl {
margin-right: 2px;
}
span.undo {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAAsTAAALEwEAmpwYAAADEklEQVQ4jY2UXSxbYRjHn/ecnm5lLFTbxdIlbENTq0x8JD62RBHRm/lKCBIXJGw3jbhtuCERVy6wyDJEYhLbMuKiDYmwIRITESQNq1LZaFg5ynrannN2ceR1VrT7X53n/f/PL8/7CXxQzdnnGicbg2cESeAW8cD3f+83mo3qSDUPPAJ0W1IQ4nn++ijDMs2W5r7lPp7npaS0VFOqCFNoFBp9nD5BnvC/oAP3QeXHytnd2etpAhHZ6uzWl6158XkBPQaCln8uV4xV2E/swWaBUP3z+u6ibhkluxk0YZ2o/lzt9rqDULD0cfrxqvFwKlwoyba2Nuyp76s1MRqaoffoPY7n8LiMkoVRYQzLiEE7Jzs7rp0STQlCKBBEkZRWqa3V1VY/q5bL5I5Th8vjAgCdSrf5ZjNLnWVz2fbpfZxfd65rFVqtUhs4tQD5Of+sfXZgdWDGPmM32imC8rE+o9nYu9yLM4nyxPXX6xJCEgyE5fK4IqWRJEECAMuxhg8Gy7YFu5YaS+HjQkIofKxvwbGw4dzg4QZu1N0ogQIAJEF26jsJRGDXvG0GAAIAPH5P/nB+9vts3VudacYUssGUBylJMUm4XPm1cgmy/LDM7c4BAMdzXfNdp57TkKxEeSL+Pjw/vASJ//SyXueFMyRIvLLCEScAIDYiVhzacG6EoAC/ebSJS+F3AgCSlckS4uoZGF4bDg5a2l/a+r2Fy7TYtEuQ6p4q42EGNsat41O2qdsoDMu0TLWIp1b8tPgShAA1pjVig+XYqk9V83vz1ykXvou6L3ViS6fS5TzKAXyy/Zw/812msJGCpKS0IbWhPrU+KSaJIqjjP8fmbXPHtw7rkRVnEEKTVZNCR1cne+1wLXcgl2bogC4i7kRQBEUztJ/zB1hNaU09hh5h1/65IuZtc/lY+bn3/LYFEqtMUzZSNiIlpUJJiL2iJ0WjZaOKMEVwBEKoRlcz+GoQUwI7EnTgPmj/2j60OnTmPbuOSI9NN70wGRIMIZ5aLJfHNW2bXnQsOmiHj/VFy6K1Sm1BfEGyMll8Y7H+AvtLjkoh3mWsAAAAAElFTkSuQmCC');
display: inline-block;
height: 13px;
width: 1em;
font-size: 13px;
background-repeat: no-repeat;
background-size: 13px;
margin-top: 2px;
/*margin-right: -2px; we don't need this now*/
}
legend>span.undo {
width: 0em;
}
fieldset.modified>legend>span.undo {
width: 1em;
}
div.description {
padding-left: 4px;
font-size: 90%;
}
<form>
<fieldset class="field">
<legend title=""><span class='ttl'>Foo configurator</span><span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="foo_type" type="radio" value="123">Foo #1</label>
<div class="description">First foo</div>
<span class="field-content">
<label><input name="foo_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
<fieldset class="field modified">
<legend title=""><span class='ttl'>Bar configurator</span><span class="undo" title="Restore default"></span></legend>
<label title="">
<input name="bar_type" type="radio" value="123">Bar #1</label>
<div class="description">First bar</div>
<span class="field-content">
<label><input name="bar_enable" type="checkbox" value="value">Enable</label>
<span class="undo" title="Restore default"></span>
<div class="description">Zoppity</div>
</span>
</fieldset>
</form>
因此,我们可以在 parent 元素上设置 0 填充,而不是在 child 上设置负边距。
在当前版本(100.0.4896.88)中,Chrome默认将以下CSS分配给图例元素:
legend {
display: block;
padding-inline-start: 2px;
padding-inline-end: 2px;
border-width: initial;
border-style: none;
border-color: initial;
border-image: initial;
}
我们需要检查它在早期版本中是否不同。