Tại sao <fieldset> không thể là container container?


201

Tôi đã cố gắng tạo kiểu cho một fieldsetyếu tố với display: flexdisplay: inline-flex.

Tuy nhiên, nó không hoạt động: flexcư xử như thế block, và inline-flexcư xử như thế nào inline-block.

Điều này xảy ra cả trên Firefox và Chrome, nhưng kỳ lạ là nó hoạt động trên IE.

Có phải là một lỗi? Tôi không thể thấy rằng fieldsetnên có bất kỳ hành vi đặc biệt nào, trong HTML5 cũng như trong thông số kỹ thuật Bố cục hộp linh hoạt 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
Vâng, đó là một lỗi. Khắc phục đơn giản: sử dụng một yếu tố khác. code.google.com/p/chromium/issues/detail?id=262679
Adam

Câu trả lời:


145

Theo Bug 984869 - display: flexkhông hoạt động đối với các thành phần nút ,

<button>không thể triển khai (bằng trình duyệt) trong CSS thuần, vì vậy chúng là một phần của hộp đen, từ quan điểm của CSS. Điều này có nghĩa là họ không nhất thiết phải phản ứng theo cùng một cách, ví dụ như <div>vậy.

Điều này không cụ thể đối với flexbox - ví dụ: chúng tôi không kết xuất thanh cuộn nếu bạn đặt overflow:scrollnút và chúng tôi không kết xuất nó dưới dạng bảng nếu bạn đặt display:tablenó vào bảng .

Bước lùi hơn nữa, điều này không cụ thể <button>. Xem xét <fieldset> <table> cũng có hành vi kết xuất đặc biệt:

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

Trong những trường hợp này, Chrome đồng ý với chúng tôi và bỏ qua flex chế độ hiển thị. (như được tiết lộ bởi thực tế là "abc" và "def" cuối cùng được xếp chồng lên nhau theo chiều dọc). Việc họ tình cờ làm những gì bạn mong đợi <button style="display:flex">có lẽ chỉ là do một chi tiết triển khai.

Khi thực hiện nút Gecko, chúng tôi mã hóa cứng <button>(và <fieldset>,<table>) như có một lớp khung cụ thể (và do đó, một cách cụ thể để đặt các phần tử con), bất kể thuộc displaytính.

Nếu bạn muốn cho trẻ em được sắp xếp một cách đáng tin cậy trong một chế độ bố trí cụ thể theo kiểu trình duyệt chéo, cách tốt nhất của bạn là sử dụng trình bao bọc-div bên trong nút, giống như bạn cần vào bên trong một <table>hoặca <fieldset>.

Do đó, lỗi đó được đánh dấu là "đã giải quyết không hợp lệ".

Ngoài ra còn có Bug 1048590 - display: flex;không hoạt động<fieldset> , hiện tại "chưa được xác nhận".


Tin tốt : Firefox 46+ triển khai Flexbox cho <fieldset>. Xem lỗi 1230207 .


Xem xét flexbox đã ở trong tình trạng lấp lửng trong 8 năm nay, tôi thấy "đáng chú ý" một chút quá mức. Nếu bất cứ điều gì, tôi ngạc nhiên khi họ làm cho nó hoạt động nhanh chóng trong Firefox. Có lẽ bạn muốn giúp mọi thứ phát triển hơn tại Google (heh, hiểu không?).
BoltClock

3
<button> is not implementable (by browsers) in pure CSS-- thật tồi tệ. Một trình duyệt có thể tự do thực hiện theo cách <button>họ muốn, họ không "bắt buộc theo hợp đồng" để kết xuất nó bằng thư viện widget hệ thống hoặc bất cứ điều gì, làm giảm khả năng tạo kiểu này bằng CSS hoặc các hành vi tùy chỉnh khác. Tương tự như vậy đối với bất kỳ yếu tố khác, thực sự.
amn

4
@BoltClock Không chắc ý của bạn là limbo. Tất cả các trình duyệt chính đều hỗ trợ sửa đổi cú pháp thứ ba và cuối cùng kể từ năm 2015; khả năng tương tác là khá tốt, tôi nghĩ vậy. Chúng tôi thậm chí còn nhận được sự hỗ trợ rộng rãi cho Grid ngay bây giờ! 🎉
Šime Vidas

@ Šime Vidas: Tôi thấy, có vẻ như nó đã là CR trong một năm nay. Đủ công bằng. Tôi nghĩ rằng nó sẽ không bao giờ làm cho nó.
BoltClock

9
2017 thực sự. Tôi chỉ ra cơn thịnh nộ của mình ở đâu? Nhiều năm chờ đợi để thực hiện một cách an toàn flexbox, vô số bài báo, tutes, dùng thử / lỗi, tôi nhận được 98% ở đó và ... các trường. Nó giống như để một thợ điện nối dây nhà tôi, chỉ để thấy rằng một jack cắm điện không được nối đất. "Đừng phóng đại" Tôi nghe mọi người nghĩ, phóng đại tôi không. Tôi thực sự phải trả lời cho điều này vào ngày mai. Flex là câu trả lời cho một số lỗi bảng kế thừa tôi cần giải quyết. Flex bây giờ là nguyên nhân của một số lỗi nhỏ không phải là di sản. Tôi chỉ ra cơn thịnh nộ của mình ở đâu?
danjah

20

Tôi phát hiện ra đây có thể là một lỗi trên Chrome và Firefox legendcác yếu tốfieldset được thay thế .

Lỗi báo cáo:

Bug Chrome (vẫn mở)
Bug Firefox (đã sửa từ v46)

Một cách giải quyết có thể:

Một cách giải quyết khác có thể sẽ được sử dụng <div role="group">trong HTML và áp dụng trong CSS div[role='group']làm bộ chọn.


CẬP NHẬT

Trong Chrome phiên bản 83 button có thể hoạt động với display: inline-grid/grid/inline-flex/flex, bạn có thể xem bản demo bên dưới:

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

Vui lòng gắn dấu sao cho lỗi Chrome để tăng mức độ ưu tiên của lỗi

Đây là một lỗi trong Chrome. Vui lòng thêm một ngôi sao cho vấn đề này để tăng mức độ ưu tiên cần khắc phục: https://bugs.chromium.org/p/chromium/issues/detail?id=375693

Đồng thời, tôi đã tạo ra ba ví dụ về Code Pen này để chỉ ra cách khắc phục vấn đề. Chúng được xây dựng bằng CSS Grid cho các ví dụ nhưng các kỹ thuật tương tự có thể được sử dụng cho flexbox.

Sử dụng aria-labellingby thay vì truyền thuyết

Đây là cách propper hơn để giải quyết vấn đề. Nhược điểm là bạn phải đối phó với việc tạo ID duy nhất được áp dụng cho mọi yếu tố huyền thoại giả.

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>

Sử dụng vai trò = "nhóm" và aria-labellingby thay vì fieldset và huyền thoại

Nếu bạn cần hộp chứa flex để có thể kéo dài theo chiều cao của phần tử anh chị em và sau đó truyền lại phần đó cho con của nó, bạn sẽ cần sử dụng role="group"thay vì<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>

Tạo một huyền thoại trùng lặp giả cho mục đích tạo kiểu

Đây là một cách khó khăn hơn nhiều để làm điều đó. Nó vẫn có thể truy cập được nhưng bạn không phải đối phó với ID khi thực hiện theo cách này. Mặt trái chính là sẽ có nội dung trùng lặp giữa yếu tố truyền thuyết thực và yếu tố huyền thoại giả.

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>

Truyền thuyết PHẢI là người phụ thuộc trực tiếp

Khi bạn lần đầu tiên cố gắng tự sửa lỗi này, có lẽ bạn sẽ thử làm điều này:

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

        ...

    </div>
</fieldset>

Bạn sẽ khám phá ra nó hoạt động, và sau đó bạn có thể sẽ tiếp tục mà không cho nó một ý nghĩ thứ hai.

Vấn đề là việc đặt một trình bao bọc div giữa trường và huyền thoại phá vỡ mối quan hệ giữa hai yếu tố. Điều này phá vỡ ngữ nghĩa của lĩnh vực / huyền thoại.

Vì vậy, bằng cách này, bạn đã đánh bại toàn bộ mục đích sử dụng fieldset / huyền thoại ngay từ đầu.

Ngoài ra, không có nhiều điểm trong việc sử dụng một bộ trường nếu bạn không cho huyền thoại đó.


9

Theo kinh nghiệm của tôi, tôi đã thấy rằng không <fieldset>, cũng không <button>, cũng không <textarea>thể sử dụng đúng display:flexhoặc các thuộc tính được thừa kế.

Như những người khác đã đề cập, lỗi đã được báo cáo. Nếu bạn muốn sử dụng flexbox để kiểm soát thứ tự (ví dụ order:2), thì bạn cần phải bọc phần tử trong div. Nếu bạn muốn flexbox kiểm soát bố cục và kích thước thực tế, thì bạn có thể muốn xem xét sử dụng div, thay vì điều khiển đầu vào (Tôi hôi thối, tôi biết).


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

Có thể cần phải sử dụng nhóm vai trò vì firefox, chrome và tôi nghĩ safari có lỗi với các trường rõ ràng. Sau đó, bộ chọn trong CSS sẽ chỉ đơn giản là

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

Chỉnh sửa: Đây là một số vấn đề mà những người khác cũng đang gặp phải.

Số 375693

Số 262679


Đây vẫn là một vấn đề trong Chrome 60.
Evolutionxbox

Vẫn ở đây trong Chrome 66.
Brad

Đăng ký Chrome 72.
danemacmillan 22/03/19

Đăng ký Chrome 73
Michael Draper

Đăng ký Chrome 75
xaddict

3

bạn có thể đặt div bổ sung <fieldset>với các đạo cụ sau:

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

1
Tôi không hiểu các downvote. Điều này thực sự chính xác. Nhưng hãy nhớ giữ <legend>phần tử (nếu được sử dụng) ở mức cao nhất của <fieldset>phần tử để giữ mức sử dụng của nó như dự định ( Permitted content: An optional <legend> element, followed by flow content.- xem developer.mozilla.org/en-US/docs/Web/HTML/Euity/
trộm

2
Đó không phải là tôi, nhưng tôi nên tưởng tượng downvote có liên quan đến việc không trả lời câu hỏi. Đó không phải là tìm cách giải quyết, mà là hành vi của fieldsetchính nó.
Manngo

Vâng, có thể không trả lời trực tiếp câu hỏi (đó là một chút triết lý), nhưng đây là một sửa chữa có thể cho lỗi vô lý này.
Eric S. Bullington

Bỏ phiếu vì nó khuyến khích phá vỡ ngữ nghĩa của <legend>yếu tố này. Điều này đánh bại mục đích sử dụng fieldset / huyền thoại ở nơi đầu tiên. Xem câu trả lời của tôi ở đây: stackoverflow.com/a/59425373/1611058
Daniel Tonon

3

Để trả lời câu hỏi ban đầu: có, đó là một lỗi, nhưng nó không được xác định rõ tại thời điểm câu hỏi được hỏi.

Bây giờ, kết xuất cho fieldset được xác định rõ hơn: https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements

Trong Firefox và Safari, flexboxtrênfieldset hiện đang làm việc. Nó chưa có trong Chromium. (Xem https://bugs.chromium.org/p/chromium/issues/detail?id=375693 )

Đồng thời xem https://blog.whatwg.org/the-state-of-fieldset-interoperability để biết các cải tiến được thực hiện trong thông số kỹ thuật năm 2018.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.