为什么<fieldset>不能是flex容器?


200

我尝试fieldset使用display: flex和设置元素的样式display: inline-flex

然而,它没有工作:flex表现得像block,并inline-flex表现得像个inline-block

这种情况在Firefox和Chrome上均会发生,但奇怪的是,它在IE上有效。

是虫子吗?fieldsetHTML5CSS Flexible Box Layout规范中,我都找不到应该有的特殊行为。

fieldset, div {
    display: flex;
    border: 1px solid;
}
<fieldset>
    <p>foo</p>
    <p>bar</p>
</fieldset>
<div>
    <p>foo</p>
    <p>bar</p>
</div>


2
是的,这是一个错误。简单修复:使用其他元素。code.google.com/p/chromium/issues/detail?id=262679
亚当(Adam)

Answers:


145

根据错误984869- display: flex对按钮元素不起作用

<button>不能在纯CSS中实现(由浏览器实现),因此从CSS的角度来看,它们有点黑盒子。这意味着它们不一定以与例如a <div>。相同的方式做出反应。

这不是特定于flexbox的-例如,如果您放置overflow:scroll按钮,则不会渲染滚动条,如果您放置按钮,则不会渲染为表格display:table

向后退一步,这并非特定于<button>。考虑 <fieldset> <table> 也具有特殊的渲染行为:

data:text/html,<fieldset style="display:flex"><div>abc</div><div>def</div>

在这种情况下,Chrome同意我们的意见,而忽略了flex 显示模式。(如“ abc”和“ def”最终垂直堆叠的事实所揭示)。它们恰好可以实现您期望的事实,<button style="display:flex">可能仅是由于实现细节。

在Gecko的按钮实现中,我们对<button>(和 <fieldset><table>),因为它具有特定的框架类(因此,具有布置子元素的特定方式),而与display属性无关 。

如果要以跨浏览器的方式可靠地将孩子可靠地安排在特定的布局模式下,最好的选择是在按钮内部使用wrapper-div,就像您需要在内部 一个<table>一个<fieldset>

因此,该错误被标记为“已解决无效”。

还存在错误1047590- display: flex;<fieldset> “未确认”中不起作用


好消息:Firefox 46+实现了Flexbox for <fieldset>。见错误1230207


考虑到flexbox已经陷入僵局已有8年了,我发现“明显”有点夸大其词。如果有的话,我很惊讶他们在Firefox中如此迅速地工作。也许您想帮助Google做好准备(嘿,明白吗?)。
BoltClock

3
<button> is not implementable (by browsers) in pure CSS-那是错误的。浏览器可以自由地实现<button>他们想要的功能,他们没有“合约上的义务”使用系统窗口小部件库或其他任何东西来渲染它,这削弱了使用CSS或其他自定义行为对它们进行样式设置的能力。确实,其他任何元素也是如此。
7

4
@BoltClock不确定您是什么意思。自2015年以来,所有主流浏览器均支持该语法的第三个也是最后一个修订版;我认为互操作性非常好。现在我们甚至获得了对Grid的广泛支持!🎉
ŠimeVidas

@ŠimeVidas:我知道,好像已经CR一年了。很公平。我以为它永远都做不到。
BoltClock

9
确实是2017年。我在哪里指出我的愤怒?多年安全地实现flexbox的等待,无数的文章,tutes,试验/错误,我在那里获得了98%的收益。这就像让电工为我的房屋接线,只是发现一个电源插孔未接地。“不要夸大”,我听到人们在想,夸大了我没有。我明天真的要为此回答。Flex是我需要解决的几个遗留表错误的答案。现在,Flex导致了少数非传统错误。我在哪里指出我的愤怒?
danjah

20

我发现这可能是在Chrome和Firefox上的bug,其中legendfieldset替换为元素

错误报告:

Bug Chrome(仍处于打开状态)
Bug Firefox(自v46起已修复)

可能的解决方法:

可能的解决方法是<div role="group">在HTML中使用,然后在CSS中div[role='group']作为选择器应用。


更新

Chrome版本83中 button可以使用display: inline-grid/grid/inline-flex/flex,您可以看到以下演示:

button {
  display: inline-flex;
  height: 2rem;
  align-items: flex-end;
  width: 4rem;
  -webkit-appearance: none;
  justify-content: flex-end;
}
<!-- 

The align-items keyword should fail in Chrome 81 or earlier, but work in Chrome 83 or later. To see the error, the button needs styles that make it more of an extrinsic container. In other words, it needs a height or width set. 
 
-->
<button>Hi</button>
<input type="button" value="Hi">


11

请加注Chrome错误以提高错误优先级

这是Chrome中的错误。请在此问题上加一个星号,以增加其优先级:https//bugs.chromium.org/p/chromium/issues/detail?id = 375693

同时,我创建了这三个Code Pen示例,以展示如何解决此问题。对于示例,它们使用CSS Grid构建,但是可以将相同的技术用于flexbox。

使用aria-labelledby而不是图例

这是处理问题的更合适的方法。缺点是您必须处理生成应用于每个假图例元素的唯一ID。

https://codepen.io/daniel-tonon/pen/vaaGzZ

<style>
.flex-container {
    display: flex;
}
</style>

<fieldset aria-labelledby="fake-legend">
    <div class="flex-container">
        <div class="flex-child" id="fake-legend">
            I am as good accessibilty wise as a real legend
        </div>

        ...

    </div>
</fieldset>

使用role =“ group”和aria-labelledby代替字段集和图例

如果您需要flex容器能够拉伸到同级元素的高度,然后又将该拉伸传递到其子元素上,则需要使用role="group"而不是<fieldset>

https://codepen.io/daniel-tonon/pen/BayRjGz

<style>
.flex-container {
    display: flex;
}
</style>

<div role="group" class="flex-container" aria-labelledby="fake-legend">
    <div class="flex-child" id="fake-legend">
        I am as good accessibilty wise as a real legend
    </div>

    ...

</div>

创建用于样式目的的伪造重复图例

这是一种更简单的方法。它仍然可以访问,但是用这种方法不必处理ID。主要的缺点是,真实图例元素和假图例元素之间将有重复的内容。

https://codepen.io/daniel-tonon/pen/zLLqjY

<style>
.screen-reader-only {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.flex-container {
    display: flex;
}
</style>

<fieldset>
    <legend class="screen-reader-only">
        I am a real screen-reader accessible legend element
    </legend>

    <div class="flex-container">
        <div class="flex-child" aria-hidden="true">
            I am a fake legend purely for styling purposes
        </div>

        ...

    </div>
</fieldset>

图例必须是直接下属

当您首次尝试自己修复此问题时,您可能会尝试执行以下操作:

<!-- DO NOT DO THIS! -->
<fieldset>
    <div class="flex-container">
        <legend class="flex-child">
            Broken semantics legend text
        </legend>

        ...

    </div>
</fieldset>

您会发现它起作用,然后您可能会继续前进而无需再三思。

问题在于,在字段集和图例之间放置div包装器会破坏两个元素之间的关系。这破坏了字段集/传奇的语义。

因此,这样做首先就使您无法使用字段集/图例的整个目的。

另外,如果不给该字段集一个图例,那么使用该字段集也没有多大意义。


9

根据我的经验,我发现,无论是<fieldset>,也不是<button>,也<textarea>可以正常使用display:flex或继承的属性。

正如其他人已经提到的那样,已经报告了错误。如果您想使用flexbox来控制排序(例如order:2),则需要将元素包装在div中。如果您希望flexbox控制实际的布局和尺寸,那么您可能要考虑使用div而不是输入控件(我知道这很臭)。


3
<div role="group">
    <p>foo</p>
    <p>bar</p>
</div>
<div>
    <p>foo</p>
    <p>bar</p>
</div>

可能需要使用角色组,因为Firefox,chrome和我认为Safari显然存在fieldset的错误。然后,CSS中的选择器就是

div[role='group'], div {
    display: flex;
    border: 1px solid;
}

编辑:这是其他人也遇到的一些问题。

发行375693

发行262679


这仍然是在Chrome 60的问题
evolutionxbox

仍在Chrome 66
Brad

Chrome 72签入
。– danemacmillan

Chrome 73签到
Michael Draper

Chrome 75
签到

3

您可以<fieldset>使用以下道具添加额外的div :

flex-inner-wrapper {
  display: inherit;
  flex-flow: inherit;
  justify-content: inherit;
  align-items: inherit;
}

1
我不明白反对票。这实际上是正确的。但要记住,保持<legend>元件(如果使用)中的顶级<fieldset>元素,以保持它的用法如预期(Permitted content: An optional <legend> element, followed by flow content.-见developer.mozilla.org/en-US/docs/Web/HTML/Element/...
Froxx

2
不是我,但我应该想像一下,投票否决与不回答问题有关。不是要找到解决方法,而是要解决fieldset自身的问题。
芒果

是的,可能无法直接回答问题(这有点哲学性),但这可能是针对此可笑错误的解决方案。
Eric S. Bullington

投反对票,因为它鼓励破坏<legend>元素的语义。首先,这违反了使用字段集/图例的目的。在这里查看我的答案:stackoverflow.com/a/59425373/1611058
Daniel Tonon

3

要回答最初的问题:是的,这是一个错误,但是在提出问题时并没有明确定义。

现在,可以更好地定义字段集的呈现方式:https : //html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

在Firefox和Safari,flexboxfieldset现在的作品。Chromium中还没有。(请参阅https://bugs.chromium.org/p/chromium/issues/detail?id=375693

另请参阅https://blog.whatwg.org/the-state-of-fieldset-interoperability以了解2018年规范中所做的改进。

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.