Почему <fieldset> не может быть гибким контейнером?

201

Я пытался стилизовать 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/issues/detail?id=262679
Адам

Ответы:

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свойства.

Если вы хотите надежно расположить дочерние элементы в определенном режиме макета кросс-браузерным способом, лучше всего использовать оболочку-div внутри кнопки, точно так же, как вам нужно внутри <table>илиа <fieldset>.

Следовательно, эта ошибка была помечена как «исправлена ​​как недействительная».

Существует также ошибка 1047590 - display: flex;не работает, в<fieldset> настоящее время "неподтвержденный".


Хорошие новости : Firefox 46+ реализует Flexbox для <fieldset>. Смотрите ошибку 1230207 .

Ориоль
источник
Учитывая, что flexbox находился в подвешенном состоянии уже 8 лет, я нахожу «удивительно» немного преувеличенным. Во всяком случае, я удивлен, что они так быстро заработали в Firefox. Может быть, вы хотели бы помочь запустить вещи в Google (хе, получить ?).
BoltClock
3
<button> is not implementable (by browsers) in pure CSS- это просто неправильно. Браузер может свободно реализовывать то, что <button>они хотят, они не «обязаны по контракту» отображать его с использованием системных библиотек виджетов или чего-либо еще, что ухудшает их способность стилизовать их с помощью CSS или другого пользовательского поведения. То же самое относится и к любому другому элементу.
атп
4
@BoltClock Не уверен, что вы подразумеваете под неопределенностью. Все основные браузеры поддерживают третью и последнюю редакцию синтаксиса с 2015 года; совместимость довольно хорошая, я думаю. Мы даже получили широкую поддержку Grid сейчас! Ime
Шиме Видас
@ Шиме Видас: Я вижу, похоже, что это был ЧР в течение года. Справедливо. Я думал, что это никогда не получится.
BoltClock
9
2017 действительно. Где я могу указать свою ярость? Годы ожидания безопасного внедрения flexbox, бесчисленных статей, разговоров, проб / ошибок, я получил 98% и ... наборы полей. Это все равно что заставить электрика подключить мой дом к сети, только чтобы обнаружить, что один разъем питания не заземлен. «Не преувеличивай» Я слышу, как люди думают, преувеличивать, я не. Я буквально должен ответить за это завтра. Flex был ответом на несколько старых ошибок в таблицах, которые мне нужно было решить. Flex теперь является причиной небольшого числа несущественных ошибок. Где я могу указать свою ярость?
Данджа
20

Я узнаю, что это может быть ошибка в Chrome и Firefox где legendи fieldsetбудут заменены элементы .

Сообщения об ошибках:

Ошибка Chrome (все еще открыт)
Ошибка Firefox (исправлено начиная с v46)

Возможный обходной путь:

Возможный обходной путь будет использовать <div role="group"> в HTML и применять в div[role='group']качестве селектора в CSS .


ОБНОВИТЬ

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

dippas
источник
11

Пожалуйста, пометьте ошибку Chrome, чтобы увеличить приоритет ошибки

Это ошибка в Chrome. Пожалуйста, добавьте звездочку к этой проблеме, чтобы повысить ее приоритетность: https://bugs.chromium.org/p/chromium/issues/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 вместо fieldset и legend

Если вам нужен 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>

Создание фальшивой дублирующей легенды для стилизации

Это гораздо более хакерский способ сделать это. Это все еще так же доступно, но вам не нужно иметь дело с идентификаторами при этом. Основным недостатком является то, что между элементом настоящей легенды и элементом поддельной легенды будет дублироваться контент.

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 между набором полей и легендой нарушает отношения между этими двумя элементами. Это нарушает семантику набора полей / легенды.

Таким образом, тем самым вы победили всю цель использования fieldset / legend.

Кроме того, нет смысла использовать набор полей, если вы не зададите этому набору легенду.

Даниэль Тонон
источник
9

По своему опыту я обнаружил, что ни <fieldset>, ни <button>, ни не <textarea>можем должным образом использовать display:flexили наследовать свойства.

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

paceaux
источник
3
<div role="group">
    <p>foo</p>
    <p>bar</p>
</div>
<div>
    <p>foo</p>
    <p>bar</p>
</div>

Возможно, нужно использовать группу ролей, потому что Firefox, Chrome и я думаю, что Safari, по-видимому, имеет ошибку с fieldsets. Тогда селектор в CSS будет просто

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

Изменить: Вот некоторые проблемы, с которыми сталкиваются и другие люди.

Выпуск 375693

Выпуск 262679

SharpCode
источник
Это все еще проблема в Chrome 60.
evolutionxbox
Все еще здесь, в Chrome 66.
Брэд,
danemacmillan,
Майкл Дрейпер
Регистрация
3

Вы можете добавить дополнительный div <fieldset>с помощью следующих реквизитов:

flex-inner-wrapper {
  display: inherit;
  flex-flow: inherit;
  justify-content: inherit;
  align-items: inherit;
}
Jemy
источник
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.
Manngo
Да, возможно, нет прямого ответа на вопрос (который был немного философским), но это возможное исправление этой нелепой ошибки.
Эрик С. Буллингтон
Голосовали против, потому что это поощряет нарушение семантики <legend>элемента. Это побеждает цель использования fieldset / legend в первую очередь. Смотрите мой ответ здесь: stackoverflow.com/a/59425373/1611058
Даниэль Тонон
3

Чтобы ответить на первоначальный вопрос: да, это ошибка, но она не была четко определена во время вопроса.

Теперь рендеринг для fieldset лучше определен: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

В Firefox и Safari, flexboxв fieldsetнастоящее время работает. Это еще не в Chromium. (См. Https://bugs.chromium.org/p/chromium/issues/detail?id=375693 ).

Также см. Https://blog.whatwg.org/the-state-of-fieldset-interoperability для улучшений, сделанных в спецификации в 2018 году.

zcorpan
источник