Почему <fieldset> не может быть гибким контейнером?
Я пытался стилизовать 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>
5 ответов
В соответствии с ошибкой 984869 - display: flex
не работает для элементов кнопки,
<button>
не может быть реализовано (браузерами) в чистом CSS, поэтому с точки зрения CSS они представляют собой нечто вроде черного ящика. Это означает, что они не обязательно реагируют так же, как, например,<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.
Я обнаружил, что это может быть ошибка в Chrome и Firefox, где legend
а также fieldset
заменены элементы.
Сообщения об ошибках:
Возможный обходной путь:
Возможный обходной путь будет использовать <div role="group">
в HTML и применение в CSS div[role='group']
как селектор.
Пожалуйста, пометьте ошибку 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
Если вам нужно, чтобы гибкий контейнер мог растягиваться до высоты родственного элемента, а затем также передавать это растяжение его дочерним элементам, вам нужно будет использовать 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.
Кроме того, нет особого смысла в использовании набора полей, если вы не дадите этому набору полей легенду.
По своему опыту я обнаружил, что ни <fieldset>
ни <button>
ни <textarea>
может правильно использовать display:flex
или унаследованные свойства.
Как уже упоминали другие, сообщалось об ошибках. Если вы хотите использовать flexbox для управления заказами (например, order:2
), тогда вам нужно будет обернуть элемент в div. Если вы хотите, чтобы flexbox управлял фактической компоновкой и размерами, то вы можете рассмотреть возможность использования div вместо элемента управления вводом (который, я знаю, воняет).
Чтобы ответить на исходный вопрос: да, это ошибка, но она не была четко определена в то время, когда был задан вопрос.
Теперь рендеринг для набора полей лучше определен: https://html.spec.whatwg.org/multipage/rendering.html
В 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 году.
<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;
}
Изменить: Вот некоторые проблемы, с которыми сталкиваются и другие люди.
Вы можете добавить дополнительный div в <fieldset>
со следующими реквизитами:
flex-inner-wrapper {
display: inherit;
flex-flow: inherit;
justify-content: inherit;
align-items: inherit;
}