Чому не можна <fieldset> бути гнучкими контейнерами?


200

Я намагався стилізувати fieldsetелемент з display: flexі display: inline-flex.

Однак не вийшло: flexповодився так block, як і inline-flexповодився inline-block.

Це трапляється як у Firefox, так і в Chrome, але дивно це працює на IE.

Це помилка? Я не міг знайти, що fieldsetповинно мати особливу поведінку, ні в специфікаціях HTML5, ні в специфікаціях CSS 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/isissue/detail?id=262679
Адам

Відповіді:


145

Згідно з програмою Bug 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властивості.

Якщо ви хочете, щоб діти надійно розташовувались у певному режимі компонування в крос-браузерному режимі, найкраще скористатися обгорткою-дівом всередині кнопки, так, як вам потрібно було б а <table>чиа <fieldset>.

Тому ця помилка була позначена як "вирішена недійсна".

Також є помилка 1047590 - display: flex;не працює<fieldset> , наразі "непідтверджено".


Гарні новини : Firefox 46+ реалізує Flexbox для <fieldset>. Дивіться про помилку 1230207 .


Зважаючи на те, що флексбокс перебуває в лімбо вже 8 років, я вважаю "надзвичайно" трохи завищенням. Якщо що, я здивований, що вони так швидко працюють у Firefox. Може бути , ви хотіли б, щоб допомогти штовхнути речі в передачі через в Google (хех, отримати його ?).
BoltClock

3
<button> is not implementable (by browsers) in pure CSS- це просто неправильно. Веб-браузер може реалізовувати <button>все, що завгодно, вони не «зобов’язані за контрактом» надавати це за допомогою бібліотек системних віджетів або будь-якого іншого, що погіршує здатність їх стилювати за допомогою CSS або іншої користувацької поведінки. Те саме стосується і будь-якого іншого елемента.
amn

4
@BoltClock Не впевнений, що ти маєш на увазі під кінцівкою. Усі основні браузери підтримують третій і остаточний перегляд синтаксису з 2015 року; Оперативна сумісність досить гарна, я думаю. Зараз ми навіть отримали широку підтримку Grid! 🎉
Šime

@ Šime Vidas: Я бачу, схоже, що це вже рік CR. Досить справедливо. Я думав, що це ніколи не вдасться.
BoltClock

9
2017 справді. Де я вказую свою лють? Роки очікування, щоб безпечно реалізувати flexbox, незліченну кількість статей, підказок, проб / помилок, я отримую там 98% і ... набори полей. Це як домовитись електрика, щоб підключити будинок додому, лише щоб виявити, що один гніздо живлення не заземлений. "Не перебільшуйте" Я чую, що люди думають, перебільшую, ні. Я буквально маю відповісти за це завтра. Flex був відповіддю на кілька застарілих помилок таблиці, які мені потрібно було вирішити. Тепер Flex є причиною меншої кількості непогашених помилок. Де я вказую свою лють?
danjah

20

Я дізнаюся, що це може бути помилка в Chrome і Firefox де legendі fieldsetбудуть замінені елементи .

Повідомлено про помилки:

Помилка 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/isissue/detail?id=375693

Тим часом я створив ці три приклади Code Pen, щоб показати, як вирішити проблему. Вони побудовані за допомогою CSS Grid для прикладів, але ті ж самі методи можна використовувати і для flexbox.

Використання aria-labelledby замість легенди

Це більш простірний спосіб вирішення проблеми. Мінус у тому, що вам доведеться мати справу з створенням унікальних ідентифікаторів, застосованих до кожного елемента підробленої легенди.

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 замість набору полей та легенди

Якщо вам потрібен флекс-контейнер, щоб можна було розтягнутись до висоти рідного елемента, а потім також пройти цей натяг на його дітей, вам потрібно буде використовувати 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>

Створення фальшивої дублюючої легенди для стилістичних цілей

Це набагато більш хакітний спосіб зробити це. Він все ще такий же доступний, але вам не доведеться мати справу з ідентифікаторами, роблячи це таким чином. Основна сторона полягає в тому, що між реальним елементом легенди та підробленим елементом легенди буде дублювати вміст.

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>

Ви виявите, що це працює, і тоді ви, ймовірно, рухатиметесь далі, не замислюючись над цим.

Проблема полягає в тому, що, якщо помістити оболонку діва між набором поля та легендою, розривається зв'язок між двома елементами. Це порушує семантику набору поля / легенди.

Таким чином, зробивши це, ви перемогли в першу чергу ціль використання поля / легенди.

Крім того, немає великого сенсу використовувати набір полів, якщо ви не даєте цьому набору поля легендою.


9

На моєму досвіді я виявив, що ні <fieldset>, ні <button>, ні вони не <textarea>можуть належним чином використовувати display:flexабо успадковувати властивості.

Як уже згадували інші, повідомлялося про помилки. Якщо ви хочете використовувати flexbox для контролю замовлень (наприклад, order:2), вам знадобиться загортати елемент у div. Якщо ви хочете, щоб флексбокс керував фактичним компонуванням та розмірами, то, можливо, ви захочете розглянути можливість використання div, а не управління введенням (Що смердить, я знаю).


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

Можливо, потрібно використовувати рольову групу, тому що у Firefox, chrome, і я думаю, що сафарі, мабуть, має помилку з набором польових даних. Тоді селектор у CSS був би просто

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

Редагувати: Ось деякі проблеми, які виникають і інші люди.

Випуск 375693

Випуск 262679


Це все ще проблема в Chrome 60.
evolutionxbox

Ще тут, у Chrome 66.
Бред

Chrome 72 реєстрація.
danemacmillan


Chrome 75 реєстрація
xaddict

3

ви можете додати додатковий div у <fieldset>наступному реквізиті:

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себе.
Мангго

Так, може не відповісти безпосередньо на питання (яке було трохи філософським), але це можливе виправлення цієї смішної помилки.
Ерік С. Булінгтон

Даун проголосував, тому що це заохочує порушити семантику <legend>елемента. Це перемагає мету використання поля поля / легенди в першу чергу. Дивіться мою відповідь тут: stackoverflow.com/a/59425373/1611058
Даніель Тонон

3

Щоб відповісти на початкове запитання: так, це помилка, але вона не була чітко визначена на той момент.

Тепер рендеринг для набору полів краще визначити: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

У Firefox і Safari, flexboxв fieldsetданий час працює. Ще не в Chromium. (Побачити Https://bugs.chromium.org/p/chromium/isissue/detail?id=375693 )

Також див. Https://blog.whatwg.org/the-state-of-fieldset-interoperability щодо вдосконалень, внесених у специфікацію у 2018 році.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.