【问题标题】:Fieldset legend CSS rendering behavior has changed in recent months... what happened?Fieldset 图例 CSS 渲染行为在最近几个月发生了变化……发生了什么?
【发布时间】:2022-04-21 01:52:51
【问题描述】:

我有一个包含各种嵌套<fieldset> 元素的表单,每个元素都有一个<legend>,今天我注意到我检查过的所有浏览器(Chrome、Firefox、Opera)上的网页都出现错误,这不是较早出现(6-12 个月前)。

有一个<span class="undo"> 元素,它使用background-image 显示为一个绿色卷曲箭头。目的是当周围的 <fieldset> 具有 class="modified" 时显示它,否则隐藏 --- 这是通过更改跨度的 width 来实现的。

与我的意图一致呈现的旧行为(仍然显示在运行 Chrome OS 76.0.3809.136 的 Chromebook 上):

新行为(在我的 Windows 10 PC 上的 Chrome 87.0.4280.88 上)由于某种原因将“Foo configurator”包装成两行。

最近浏览器渲染有什么变化导致了这个吗?如果是这样,我该如何解决?

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>

【问题讨论】:

  • 请不要编辑我的 HTML;我的代码可以保存为单个文件并在 PC 上试用。将其拆分为 SO 形式的 CSS 和 HTML 片段会抵消这种优势。
  • 在 FireFox 上也发生在我身上!我不明白大赏金,你对杰森有什么期望?

标签: html css fieldset


【解决方案1】:

如果您在 Chrome 76 上可以正确看到它,则很可能是通过在 Chrome 77 中打开 LayoutNG 引入了此更改,该更改已于 2019 年发布,但其中部分内容稍后发布。例如,我知道我在 textareas 中的布局有些不一致,并且直到大约去年才进行修改。

最好用 Chrome 77 进行测试,看看它是否真的是这个东西。

无论如何,这看起来像是 margin-right: -2pxwidth: 0em 之间的相互作用,它以某种方式将布局计算为溢出并添加新行。

通过使用 BrowserStack,我发现它在 Chrome 86 中发生了变化,这恰好是 Chrome 实现 flex and grid for fieldsets 的版本。他们可能也需要进行细微的更改才能实现这一点。

【讨论】:

    【解决方案2】:

    负边距将legend 的右边框向左拉2px,从而将图例的宽度减少2px。当您在span.undo 上设置width:0em 时,负边距仍然起作用。但是现在legend 的宽度短了 2px,以便在同一行上呈现标题文本,因此它可以换行。

    我们可以模拟行为。见代码 cmets。

    * {
      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>
    随着负边距减小宽度,内联文本开始换行。
    根据您的字体大小,输出可能会略有不同,因此它的外观如下:


    我们可以通过对填充做一点调整来避免负边距:

    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>

    因此,我们可以在父元素上设置 0 填充,而不是在子元素上设置负边距。


    在当前版本 (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;
    }
    

    我们需要检查它是否与之前的版本不同。

    【讨论】:

      【解决方案3】:

      至于行为改变的原因是什么,我不知道。

      同时,您可以通过添加来解决此问题

      white-space: nowrap;
      

      到您的图例元素,或

      legend > span.undo { display: none; }
      fieldset.modified > legend > span.undo { display: inline-block; }
      

      似乎也可以完成这项工作,以及去除负边距

      span.undo { margin-right: 0; }
      

      【讨论】:

      • 耶,解决了!你能帮我理解它为什么会包装吗?大概某处有空白,但我不明白为什么会这样。
      • 是的,我宁愿采用display:none; 方法。这是一个由 JavaFX 糟糕的 WebView 组件共享的 UI 模型,如果我这样做,IIRC 会在 WebView 上出现一些问题。
      • 负边距似乎也有效,不妨看看
      猜你喜欢
      • 2014-05-13
      • 1970-01-01
      • 2012-12-18
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多