Why can't <fieldset> be flex containers?
Asked Answered
T

7

239

I tried to style a fieldset element with display: flex and display: inline-flex.

However, it didn't work: flex behaved like block, and inline-flex behaved like inline-block.

This happens both on Firefox and Chrome, but strangely it works on IE.

Is it a bug? I couldn't find that fieldset should have any special behavior, neither in HTML5 nor in CSS Flexible Box Layout specs.

fieldset, div {
    display: flex;
    border: 1px solid;
}
<fieldset>
    <p>foo</p>
    <p>bar</p>
</fieldset>
<div>
    <p>foo</p>
    <p>bar</p>
</div>
Trimetric answered 21/1, 2015 at 23:16 Comment(2)
Yes, it's a bug. Simple fix: use another element. code.google.com/p/chromium/issues/detail?id=262679Ichnology
Similar issue: Flexbox not working on <button> element in some browsersTrimetric
T
157

According to Bug 984869 - display: flex doesn't work for button elements,

<button> is not implementable (by browsers) in pure CSS, so they are a bit of a black box, from the perspective of CSS. This means that they don't necessarily react in the same way that e.g. a <div> would.

This isn't specific to flexbox -- e.g. we don't render scrollbars if you put overflow:scroll on a button, and we don't render it as a table if you put display:table on it.

Stepping back even further, this isn't specific to <button>. Consider <fieldset> and <table> which also have special rendering behavior:

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

In these cases, Chrome agrees with us and disregards the flex display mode. (as revealed by the fact that "abc" and "def" end up being stacked vertically). The fact that they happen to do what you're expecting on <button style="display:flex"> is likely just due to an implementation detail.

In Gecko's button implementation, we hardcode <button> (and <fieldset>, and <table>) as having a specific frame class (and hence, a specific way of laying out the child elements), regardless of the display property.

If you want to reliably have the children reliably arranged in a particular layout mode in a cross-browser fashion, your best bet is to use a wrapper-div inside the button, just as you would need to inside of a <table> or a <fieldset>.

Therefore, that bug was marked as "resolved invalid".

There is also Bug 1047590 - display: flex; doesn't work in <fieldset>, currently "unconfirmed".


Good news: Firefox 46+ implements Flexbox for <fieldset>. See bug 1230207.

Trimetric answered 21/1, 2015 at 23:39 Comment(9)
Considering flexbox has been in limbo for 8 years now, I find "remarkably" a bit of an overstatement. If anything, I'm surprised they got it working in Firefox so quickly. Maybe you'd like to help kick things into gear over at Google (heh, get it?).Norsworthy
<button> is not implementable (by browsers) in pure CSS -- that's just wrong. A browser is free to implement a <button> however they want, they are not "contractually obliged" to render it using system widget libraries or whatever, which impair ability to style these with CSS or other custom behaviors. Same goes for any other element, really.Carmelinacarmelita
@Norsworthy Not sure what you mean by limbo. All major browsers support the third and final revision of the syntax since 2015; interoperability is pretty good, I think. We even got broad support for Grid now! 🎉Hypogeum
@Šime Vidas: I see, looks like it's been CR for a year now. Fair enough. I thought it was never gonna make it.Norsworthy
2017 indeed. Where do I point my rage? Years of waiting to safely implement flexbox, countless articles, tutes, trial/errors, I get 98% there and... fieldsets. It's like getting an electrician to wire up my house, only to find that one power jack is not earthed. "Don't exaggerate" I hear people think, exaggerate I don't. I literally have to answer for this tomorrow. Flex was the answer to several legacy table bugs I needed to solve. Flex is now the cause of a smaller handful of non-legacy bugs. Where do I point my rage?Carberry
Since this answer, the bug referenced here has been "reopened" and then "resolved fixed". The new consensus of the browser vendors is that even "special" elements with some rendering "magic" should react to display property.Pavlov
The fieldset element is usually replaceable by a div if all you want to do is put a box around things. I my case, I was just using it for layout, so the div is probably better semantically. Where the fieldset is more useful is if (a) you also need a legend, (b) you want to take advantage of the disabled attribute of the fieldset.Cynewulf
seems the bug is back again at least in chrome :<Rheotropism
I think you guys may be confusing Chromium and Chrome. Unfortunately they diverge a bit, as in, closing the bug in the former codebase doesn't magically get fixed in the latter. The bug in Chromium was fixed years ago (from what I gather from their bug tracker), while the bug in Chrome was fixed on August 19th this year, and the fix made it into the 86th version of Chrome. Congratulations to us all, the CSS gods have heeded our prayers /sCarmelinacarmelita
A
29

I find out this might be a bug on Chrome and Firefox where legend and fieldset are replaced elements.

Bugs Reported:

Bug Chrome (fixed since v86)
Bug Firefox (fixed since v46)

A possible Workaround:

A possible workaround would be using <div role="group"> in HTML, and applying in CSS div[role='group'] as selector.


UPDATE

In Chrome version 83 button can work with the display: inline-grid/grid/inline-flex/flex, you can see the demo below:

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">
Albertson answered 21/1, 2015 at 23:32 Comment(1)
It looks like this has been fixed for fieldsets since Chrome 86 (bugs.chromium.org/p/chromium/issues/detail?id=375693#c88)Ayn
L
21

Please star the Chrome bug to increase bug priority

This is a bug in Chrome. Please add a star to this issue to increase it's priority to be fixed: https://bugs.chromium.org/p/chromium/issues/detail?id=375693

In the mean time, I created these three Code Pen examples to show how to work around the issue. They are built using CSS Grid for the examples but the same techniques can be used for flexbox.

Using aria-labelledby instead of legend

This is the more propper way to deal with the problem. The downside is that you have to deal with generating unique IDs applied to every fake legend element.

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>

Using role="group" and aria-labelledby instead of fieldset and legend

If you need the flex-container to be able to stretch to the height of a sibling element and then also pass that stretch onto its children, you will need to use role="group" instead of <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>

Creating a fake duplicate legend for styling purposes

This is a far more hacky way to do it. It is still just as accessible but you don't have to deal with IDs when doing it this way. The main down side is that there is going to be duplicate content between the real legend element and the fake legend element.

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>

Legend MUST be a direct decendent

When you are first trying to fix this yourself, you will probably try doing this:

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

        ...

    </div>
</fieldset>

You will discover it works, and then you will probably move on without giving it a second thought.

The problem is that putting a div wrapper between the fieldset and the legend breaks the relationship between the two elements. This breaks the semantics of fieldset/legend.

So by doing this, you have defeated the whole purpose of using fieldset/legend in the first place.

Also, there isn't much point in using a fieldset if you don't give that fieldset a legend.

Lecherous answered 20/12, 2019 at 12:35 Comment(0)
X
9

In my experience, I've found that neither <fieldset>, nor <button>, nor <textarea> can properly use display:flex or inherited properties.

As others have already mentioned, bugs have been reported. If you want to use flexbox to control ordering (e.g. order:2), then you'd need to wrap the element in a div. If you want flexbox to control actual layout and dimensions, then you may want to consider using a div, instead of the input control (Which stinks, I know).

Xebec answered 22/1, 2015 at 16:8 Comment(0)
G
4
<div role="group">
    <p>foo</p>
    <p>bar</p>
</div>
<div>
    <p>foo</p>
    <p>bar</p>
</div>

Might need to use role-group because firefox, chrome and i think safari have a bug with fieldsets apparently. Then the selector in the CSS would simply be

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

Edit: Here are some issues that other people are experiencing as well.

Issue 375693

Issue 262679

Grizelda answered 21/1, 2015 at 23:24 Comment(10)
This is still an issue in Chrome 60.Splat
Still here in Chrome 66.Bautzen
Chrome 72 checking in.Octahedral
Chrome 73 checking inQuartas
Chrome 75 checking inShoup
Version 78 checking inUlm
Version 79 still checking inSynthiasyntonic
Version 83 checking inStrudel
Chrome 89 checking inKordofanian
Chrome 110 checking in. <fieldset> now works with display: flex/inline-flex;Swisher
A
4

you can put additional div in <fieldset> with the following props:

flex-inner-wrapper {
  display: inherit;
  flex-flow: inherit;
  justify-content: inherit;
  align-items: inherit;
}
Aussie answered 6/9, 2017 at 22:46 Comment(4)
I don't understand the downvotes. This is actually correct. But remember to keep the <legend> element (if used) in the top level of the <fieldset> element to keep its usage as intended (Permitted content: An optional <legend> element, followed by flow content. – see developer.mozilla.org/en-US/docs/Web/HTML/Element/…)Trug
It wasn’t me, but I should imagine the downvote has something to do with not answering the question. It wasn’t about finding a workaround, but the behaviour of the fieldset itself.Cynewulf
Yes, may not directly answer the question (which was a bit philosophical), but this is a possible fix for this ridiculous bug.Kelson
Down voted because it encourages breaking the semantics of the <legend> element. This defeats the purpose of using fieldset/legend in the first place. See my answer here: https://mcmap.net/q/37027/-why-can-39-t-lt-fieldset-gt-be-flex-containersLecherous
G
4

To answer the original question: yes, it is a bug, but it wasn't well-defined at the time the question was asked.

Now the rendering for fieldset is better defined: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

In Firefox and Safari, flexbox on fieldset now works. It doesn't yet in Chromium. (See https://bugs.chromium.org/p/chromium/issues/detail?id=375693 )

Also see https://blog.whatwg.org/the-state-of-fieldset-interoperability for improvements made in the specification in 2018.

Gregorygregrory answered 20/12, 2019 at 11:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.