Mengapa <fieldset> tidak bisa menjadi wadah fleksibel?


201

Saya mencoba gaya a fieldset elemen dengan display: flexdan display: inline-flex.

Namun, itu tidak berhasil: flexberperilaku seperti block, daninline-flex berperilaku seperti inline-block.

Ini terjadi pada Firefox dan Chrome, tetapi anehnya itu bekerja pada IE.

Apakah ini bug? Saya tidak dapat menemukan bahwa fieldsetseharusnya memiliki perilaku khusus, baik dalam HTML5 maupun dalam spesifikasi Layout Kotak Fleksibel CSS .

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


2
Ya, itu adalah bug. Perbaikan sederhana: gunakan elemen lain. code.google.com/p/chromium/issues/detail?id=262679
Adam

Jawaban:


145

Menurut Bug 984869 - display: flextidak berfungsi untuk elemen tombol ,

<button>tidak dapat diterapkan (oleh browser) di CSS murni, jadi mereka sedikit kotak hitam, dari perspektif CSS. Ini berarti bahwa mereka tidak perlu bereaksi dengan cara yang sama seperti misalnya a<div> .

Ini tidak khusus untuk flexbox - mis. Kami tidak membuat bilah gulir jika Anda overflow:scrollmenekan tombol, dan kami tidak menjadikannya sebagai tabel jika Anda memasangnya display:table.

Melangkah mundur lebih jauh, ini tidak khusus untuk <button>. Mempertimbangkan <fieldset> dan <table> yang juga memiliki perilaku rendering khusus:

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

Dalam kasus ini, Chrome setuju dengan kami dan mengabaikan flex mode tampilan. (seperti yang diungkapkan oleh fakta bahwa "abc" dan "def" pada akhirnya ditumpuk secara vertikal). Fakta bahwa mereka melakukan apa yang Anda harapkan <button style="display:flex">kemungkinan besar hanya karena detail implementasi.

Dalam implementasi tombol Gecko, kita melakukan hardcode <button>(dan <fieldset>,dan <table>) memiliki kelas bingkai tertentu (dan karenanya, cara spesifik untuk meletakkan elemen anak), terlepas dari displayproperti.

Jika Anda ingin agar anak-anak secara andal diatur dalam mode tata letak tertentu dalam mode lintas-peramban, cara terbaik Anda adalah menggunakan pembungkus-div di dalam tombol, sama seperti yang Anda perlukan di dalam Sebuah <table> ataua <fieldset>.

Karenanya, bug itu ditandai sebagai "diselesaikan tidak valid".

Ada juga Bug 1047590 - display: flex;tidak berfungsi<fieldset> , saat ini "belum dikonfirmasi".


Berita baik : Firefox 46+ mengimplementasikan Flexbox for <fieldset>. Lihat bug 1230207 .


Mempertimbangkan flexbox telah dalam limbo selama 8 tahun sekarang, saya menemukan "sangat" sedikit berlebihan. Jika ada, saya terkejut mereka membuatnya bekerja di Firefox dengan sangat cepat. Mungkin Anda ingin membantu memulai sesuatu di Google (heh, mengerti ?).
BoltClock

3
<button> is not implementable (by browsers) in pure CSS- itu salah. Sebuah browser bebas untuk mengimplementasikan apa pun yang <button>mereka inginkan, mereka tidak "diwajibkan secara kontrak" untuk merendernya menggunakan pustaka widget sistem atau apa pun, yang mengganggu kemampuan untuk mendesainnya dengan CSS atau perilaku khusus lainnya. Sama berlaku untuk elemen lain, sungguh.
amn

4
@BoltClock Tidak yakin apa yang Anda maksud dengan limbo. Semua browser utama mendukung revisi ketiga dan terakhir dari sintaks sejak 2015; interoperabilitas cukup bagus, saya pikir. Kami bahkan mendapat dukungan luas untuk Grid sekarang! 🎉
Šime Vidas

@ Šime Vidas: Begitu ya, sepertinya sudah CR selama satu tahun sekarang. Cukup adil. Saya pikir itu tidak akan berhasil.
BoltClock

9
2017 memang. Di mana saya mengarahkan kemarahan saya? Bertahun-tahun menunggu untuk mengimplementasikan flexbox dengan aman, artikel yang tak terhitung jumlahnya, tutes, percobaan / kesalahan, saya mendapatkan 98% di sana dan ... fieldets. Ini seperti mendapatkan tukang listrik untuk memasang kabel di rumah saya, hanya untuk menemukan bahwa satu colokan listrik tidak dibumikan. "Jangan melebih-lebihkan" Aku mendengar orang berpikir, melebih-lebihkan tidak. Saya benar-benar harus menjawab untuk ini besok. Flex adalah jawaban untuk beberapa bug tabel lama yang harus saya selesaikan. Flex sekarang menjadi penyebab sejumlah kecil bug non-legacy. Di mana saya mengarahkan kemarahan saya?
danjah

20

Saya mencari tahu mungkin ini bug pada Chrome dan Firefox mana legenddan fieldsetyang diganti elemen .

Bug yang Dilaporkan:

Bug Chrome (masih terbuka)
Bug Firefox (diperbaiki sejak v46)

Solusi yang mungkin:

Solusi yang mungkin akan digunakan <div role="group">dalam HTML, dan menerapkan dalam CSS div[role='group']sebagai pemilih.


MEMPERBARUI

Di Chrome versi 83 button dapat bekerja dengan display: inline-grid/grid/inline-flex/flex, Anda dapat melihat demo di bawah ini:

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

Beri bintang pada bug Chrome untuk meningkatkan prioritas bug

Ini adalah bug di Chrome. Harap tambahkan bintang pada masalah ini untuk meningkatkan prioritasnya untuk diperbaiki: https://bugs.chromium.org/p/chromium/issues/detail?id=375693

Sementara itu, saya membuat tiga contoh Pena Kode ini untuk menunjukkan cara mengatasi masalah ini. Mereka dibuat menggunakan CSS Grid untuk contoh tetapi teknik yang sama dapat digunakan untuk flexbox.

Menggunakan aria-labelled oleh bukan legenda

Ini adalah cara yang lebih tepat untuk mengatasi masalah tersebut. Kelemahannya adalah Anda harus berurusan dengan menghasilkan ID unik yang diterapkan untuk setiap elemen legenda palsu.

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>

Menggunakan role = "group" dan aria-labelled oleh bukannya fieldset dan legenda

Jika Anda membutuhkan wadah fleksibel untuk dapat meregangkan hingga setinggi elemen saudara dan kemudian juga merentangkannya ke anak-anaknya, Anda harus menggunakan role="group"alih-alih<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>

Membuat legenda duplikat palsu untuk keperluan penataan

Ini adalah cara yang jauh lebih sulit untuk melakukannya. Itu masih dapat diakses tetapi Anda tidak harus berurusan dengan ID ketika melakukannya dengan cara ini. Sisi bawah utama adalah bahwa akan ada duplikat konten antara elemen legenda nyata dan elemen legenda palsu.

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>

Legenda HARUS menjadi keturunan langsung

Ketika Anda pertama kali mencoba untuk memperbaiki ini sendiri, Anda mungkin akan mencoba melakukan ini:

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

        ...

    </div>
</fieldset>

Anda akan menemukan bahwa itu berfungsi, dan kemudian Anda mungkin akan melanjutkan tanpa memikirkannya lagi.

Masalahnya adalah bahwa menempatkan pembungkus div antara fieldset dan legenda memutus hubungan antara dua elemen. Ini mematahkan semantik fieldset / legenda.

Jadi dengan melakukan ini, Anda telah mengalahkan seluruh tujuan menggunakan fieldset / legenda di tempat pertama.

Selain itu, tidak ada gunanya menggunakan fieldset jika Anda tidak memberikan legenda tersebut.


9

Dalam pengalaman saya, saya telah menemukan bahwa keduanya <fieldset>, atau <button>, juga tidak <textarea>dapat menggunakan display:flexatau mewarisi properti dengan benar.

Seperti yang telah disebutkan orang lain, bug telah dilaporkan. Jika Anda ingin menggunakan flexbox untuk mengontrol pemesanan (mis. order:2), Maka Anda harus membungkus elemen dalam div. Jika Anda ingin flexbox mengontrol tata letak dan dimensi aktual, maka Anda mungkin ingin mempertimbangkan untuk menggunakan div, alih-alih kontrol input (Yang berbau busuk, saya tahu).


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

Mungkin perlu menggunakan role-group karena firefox, chrome dan saya pikir safari memiliki bug dengan fieldset rupanya. Maka pemilih dalam CSS akan sederhana

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

Edit: Berikut adalah beberapa masalah yang dialami orang lain juga.

Masalah 375693

Edisi 262679


Ini masih menjadi masalah di Chrome 60.
evolutionxbox

Masih di sini di Chrome 66.
Brad

Chrome 72 check in.
danemacmillan

Pengecekan Chrome 73
Michael Draper

Chrome 75 check in
xaddict

3

Anda dapat menambahkan div tambahan <fieldset>dengan properti berikut:

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

1
Saya tidak mengerti downvotes. Ini sebenarnya benar. Tapi ingat untuk menjaga <legend>elemen (jika digunakan) di tingkat atas <fieldset>elemen untuk menjaga penggunaannya sebagaimana dimaksud ( Permitted content: An optional <legend> element, followed by flow content.- lihat developer.mozilla.org/en-US/docs/Web/HTML/Element/… )
Froxx

2
Itu bukan saya, tetapi saya harus membayangkan downvote ada hubungannya dengan tidak menjawab pertanyaan. Itu bukan tentang menemukan solusi, tetapi perilaku fieldsetitu sendiri.
Manngo

Ya, mungkin tidak langsung menjawab pertanyaan (yang agak filosofis), tetapi ini adalah kemungkinan perbaikan untuk bug konyol ini.
Eric S. Bullington

Turut memilih karena mendorong pemutusan semantik <legend>elemen. Ini mengalahkan tujuan menggunakan fieldset / legenda di tempat pertama. Lihat jawaban saya di sini: stackoverflow.com/a/59425373/1611058
Daniel Tonon

3

Untuk menjawab pertanyaan awal: ya, ini adalah bug, tetapi tidak didefinisikan dengan baik pada saat pertanyaan itu diajukan.

Sekarang rendering untuk fieldset didefinisikan dengan lebih baik: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

Di Firefox dan Safari, flexboxpada fieldsetsaat bekerja. Itu belum di Chromium. (Lihat https://bugs.chromium.org/p/chromium/issues/detail?id=375693 )

Lihat juga https://blog.whatwg.org/the-state-of-fieldset-interoperability untuk peningkatan yang dibuat dalam spesifikasi pada 2018.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.