Warum kann <fieldset> kein Flex-Container sein?

200

Ich habe versucht, ein fieldsetElement mit display: flexund zu stylen display: inline-flex.

Es hat jedoch nicht funktioniert: flexbenahm sich wie blockund inline-flexbenahm sich wie inline-block.

Dies geschieht sowohl unter Firefox als auch unter Chrome, funktioniert aber seltsamerweise unter IE.

Ist es ein Fehler? Ich konnte nicht feststellen, dass fieldsetdies ein spezielles Verhalten haben sollte, weder in HTML5 noch in CSS Flexible Box Layout- Spezifikationen.

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

Oriol
quelle
2
Ja, das ist ein Fehler. Einfache Lösung: Verwenden Sie ein anderes Element. code.google.com/p/chromium/issues/detail?id=262679
Adam

Antworten:

145

Laut Bug 984869 - display: flexfunktioniert nicht für Schaltflächenelemente ,

<button>ist (von Browsern) nicht in reinem CSS implementierbar, daher sind sie aus Sicht von CSS eine Art Black Box. Dies bedeutet, dass sie nicht unbedingt so reagieren, wie z <div>. B. a .

Dies ist nicht spezifisch für Flexbox - z. B. rendern wir keine Bildlaufleisten, wenn Sie overflow:scrolleine Schaltfläche anlegen , und wir rendern sie nicht als Tabelle, wenn Sie sie anbringen display:table.

Wenn Sie noch weiter zurücktreten, ist dies nicht spezifisch für <button>. Erwägen <fieldset> und <table> die auch spezielles Renderverhalten haben:

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

In diesen Fällen stimmt Chrome uns zu und ignoriert den flex Anzeigemodus. (wie aus der Tatsache hervorgeht, dass "abc" und "def" vertikal gestapelt werden). Die Tatsache, dass sie zufällig das tun, was Sie erwarten, <button style="display:flex">ist wahrscheinlich nur auf ein Implementierungsdetail zurückzuführen.

In Gecko der Schaltfläche Implementierung, codieren wir <button>(und <fieldset>,und <table>) unabhängig von der displayEigenschaft eine bestimmte Rahmenklasse (und damit eine bestimmte Art der Anordnung der untergeordneten Elemente) aufweisen .

Wenn Sie möchten, dass die Kinder in einem bestimmten Layoutmodus zuverlässig und browserübergreifend angeordnet werden, verwenden Sie am besten ein Wrapper-Div innerhalb der Schaltfläche, genau wie Sie es innerhalb von benötigen würden a <table>odera <fieldset>.

Daher wurde dieser Fehler als "ungültig behoben" markiert.

Es gibt auch Bug 1047590 - display: flex;funktioniert nicht<fieldset> , derzeit "unbestätigt".


Gute Nachrichten : Firefox 46+ implementiert Flexbox für <fieldset>. Siehe Fehler 1230207 .

Oriol
quelle
In Anbetracht der Tatsache, dass Flexbox seit 8 Jahren in der Schwebe ist, finde ich "bemerkenswert" etwas übertrieben. Wenn überhaupt, bin ich überrascht, dass es in Firefox so schnell funktioniert hat. Vielleicht würden Sie zu helfen Kick Dinge in Gang über bei Google mögen (heh, bekommt es ?).
BoltClock
3
<button> is not implementable (by browsers) in pure CSS-- Das ist einfach falsch. Es steht einem Browser frei, eine zu implementieren, wie er <button>möchte. Sie sind nicht "vertraglich verpflichtet", sie mithilfe von System-Widget-Bibliotheken oder was auch immer zu rendern, was die Fähigkeit beeinträchtigt, diese mit CSS oder anderen benutzerdefinierten Verhaltensweisen zu formatieren. Gleiches gilt für jedes andere Element.
Amn
4
@BoltClock Ich bin mir nicht sicher, was du mit Schwebe meinst. Alle gängigen Browser unterstützen die dritte und letzte Überarbeitung der Syntax seit 2015; Interoperabilität ist ziemlich gut, denke ich. Wir haben jetzt sogar breite Unterstützung für Grid! 🎉
Šime Vidas
@ Šime Vidas: Ich sehe, es sieht so aus, als wäre es seit einem Jahr CR. Meinetwegen. Ich dachte, es würde nie kommen.
BoltClock
9
2017 in der Tat. Wo zeige ich meine Wut? Jahre des Wartens auf die sichere Implementierung von Flexbox, unzähligen Artikeln, Tutes, Versuchen / Fehlern, ich bekomme 98% dort und ... Feldsätze. Es ist, als würde ein Elektriker mein Haus verkabeln, nur um festzustellen, dass eine Steckdose nicht geerdet ist. "Übertreibe nicht" Ich höre Leute denken, übertreibe ich nicht. Ich muss mich morgen buchstäblich dafür verantworten. Flex war die Antwort auf einige ältere Tabellenfehler, die ich beheben musste. Flex ist jetzt die Ursache für eine kleinere Handvoll nicht älterer Fehler. Wo zeige ich meine Wut?
Danjah
20

Ich finde heraus , dies könnte ein Fehler in Chrome und Firefox, wo legendund fieldsetsind Elemente ersetzt .

Gemeldete Fehler:

Bug Chrome (noch offen)
Bug Firefox (behoben seit v46)

Eine mögliche Problemumgehung:

Eine mögliche Problemumgehung wäre die Verwendung <div role="group">in HTML und die Anwendung in CSS div[role='group']als Selektor.


AKTUALISIEREN

In Chrome kann Version 83 button mit dem arbeiten display: inline-grid/grid/inline-flex/flex, Sie können die Demo unten sehen:

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">

Dippas
quelle
11

Bitte markieren Sie den Chrome-Fehler, um die Fehlerpriorität zu erhöhen

Dies ist ein Fehler in Chrome. Bitte fügen Sie diesem Problem einen Stern hinzu, um die zu behebende Priorität zu erhöhen: https://bugs.chromium.org/p/chromium/issues/detail?id=375693

In der Zwischenzeit habe ich diese drei Code Pen-Beispiele erstellt, um zu zeigen, wie das Problem umgangen werden kann. Sie werden für die Beispiele mit CSS Grid erstellt, aber für Flexbox können dieselben Techniken verwendet werden.

Verwenden von Aria-Labelledby anstelle von Legende

Dies ist der bessere Weg, um mit dem Problem umzugehen. Der Nachteil ist, dass Sie sich mit der Generierung eindeutiger IDs befassen müssen, die auf jedes gefälschte Legendenelement angewendet werden.

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>

Verwenden Sie role = "group" und aria-labelledby anstelle von fieldset und legend

Wenn Sie den Flex-Container benötigen, um sich auf die Höhe eines Geschwisterelements dehnen zu können, und diese Dehnung dann auch an seine Kinder weitergeben, müssen Sie role="group"stattdessen verwenden<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>

Erstellen einer gefälschten doppelten Legende für Stylingzwecke

Dies ist ein weitaus hackigerer Weg, dies zu tun. Es ist immer noch genauso zugänglich, aber Sie müssen sich auf diese Weise nicht mit IDs befassen. Der Hauptnachteil ist, dass zwischen dem realen Legendenelement und dem gefälschten Legendenelement doppelter Inhalt vorhanden sein wird.

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>

Die Legende MUSS ein direkter Nachkomme sein

Wenn Sie zum ersten Mal versuchen, dies selbst zu beheben, werden Sie wahrscheinlich Folgendes versuchen:

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

        ...

    </div>
</fieldset>

Sie werden feststellen, dass es funktioniert, und dann werden Sie wahrscheinlich weitermachen, ohne darüber nachzudenken.

Das Problem besteht darin, dass durch das Einfügen eines Div-Wrappers zwischen dem Feldsatz und der Legende die Beziehung zwischen den beiden Elementen unterbrochen wird. Dies bricht die Semantik von Feldmenge / Legende.

Auf diese Weise haben Sie den gesamten Zweck der Verwendung von Feldsatz / Legende besiegt.

Es macht auch nicht viel Sinn, ein Feldset zu verwenden, wenn Sie diesem Feldset keine Legende geben.

Daniel Tonon
quelle
9

Nach meiner Erfahrung habe ich festgestellt, dass weder <fieldset>noch <button>noch Eigenschaften <textarea>ordnungsgemäß verwendet display:flexoder geerbt werden können.

Wie andere bereits erwähnt haben, wurden Fehler gemeldet. Wenn Sie Flexbox verwenden möchten, um die Reihenfolge zu steuern (z. B. order:2), müssen Sie das Element in ein div einschließen. Wenn Sie möchten, dass die Flexbox das tatsächliche Layout und die Abmessungen steuert, sollten Sie anstelle der Eingabesteuerung ein div verwenden (was stinkt, weiß ich).

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

Möglicherweise muss eine Rollengruppe verwendet werden, da Firefox, Chrome und ich denke, dass Safari anscheinend einen Fehler mit Feldsätzen hat. Dann wäre der Selektor im CSS einfach

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

Bearbeiten: Hier sind einige Probleme, die auch andere Leute haben.

Ausgabe 375693

Ausgabe 262679

SharpCode
quelle
Dies ist immer noch ein Problem in Chrome 60.
evolutionxbox
Immer noch hier in Chrome 66.
Brad
Chrome 72 einchecken.
Danemacmillan
Chrome 73 einchecken
Michael Draper
Chrome 75 einchecken
xaddict
3

<fieldset>Mit den folgenden Requisiten können Sie zusätzliche Divs hinzufügen:

flex-inner-wrapper {
  display: inherit;
  flex-flow: inherit;
  justify-content: inherit;
  align-items: inherit;
}
Jemy
quelle
1
Ich verstehe die Abstimmungen nicht. Das ist eigentlich richtig. Denken Sie jedoch daran, das <legend>Element (falls verwendet) in der obersten Ebene des <fieldset>Elements zu Permitted content: An optional <legend> element, followed by flow content.
belassen, damit es
2
Ich war es nicht, aber ich sollte mir vorstellen, dass die Ablehnung etwas damit zu tun hat, die Frage nicht zu beantworten. Es ging nicht darum, eine Problemumgehung zu finden, sondern um das Verhalten des fieldsetSelbst.
Manngo
Ja, kann die Frage nicht direkt beantworten (was ein bisschen philosophisch war), aber dies ist eine mögliche Lösung für diesen lächerlichen Fehler.
Eric S. Bullington
Down stimmte ab, weil es dazu anregt, die Semantik des <legend>Elements zu brechen . Dies macht den Zweck der Verwendung von Feldsatz / Legende in erster Linie zunichte. Siehe meine Antwort hier: stackoverflow.com/a/59425373/1611058
Daniel Tonon
3

Um die ursprüngliche Frage zu beantworten: Ja, es ist ein Fehler, aber er war zum Zeitpunkt der Frage nicht genau definiert.

Jetzt ist das Rendering für Fieldset besser definiert: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

In Firefox und Safari funktioniert flexboxon fieldsetjetzt. Es ist noch nicht in Chrom. (Siehe https://bugs.chromium.org/p/chromium/issues/detail?id=375693 )

Unter https://blog.whatwg.org/the-state-of-fieldset-interoperability finden Sie auch Verbesserungen in der Spezifikation von 2018.

zcorpan
quelle