เหตุใด <fieldset> จึงไม่สามารถยืดหยุ่นได้


204

ผมพยายามที่จะสไตล์fieldsetองค์ประกอบด้วยและdisplay: flexdisplay: inline-flex

แต่ก็ไม่ได้ทำงาน: flexทำตัวเหมือนblockและทำตัวเหมือนinline-flexinline-block

สิ่งนี้เกิดขึ้นทั้งบน Firefox และ Chrome แต่ใช้งานกับ IE ได้อย่างแปลกประหลาด

มันเป็นข้อบกพร่องหรือไม่? ฉันไม่พบที่fieldsetควรมีพฤติกรรมพิเศษใด ๆ ทั้งในHTML5หรือในรายละเอียด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
ใช่มันเป็นข้อผิดพลาด แก้ไขง่าย ๆ : ใช้องค์ประกอบอื่น code.google.com/p/chromium/issues/detail?id=262679
Adam

คำตอบ:


146

ตามที่Bug 984,869 - 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 เรา hardcode <button>(และ <fieldset>,และ <table>) เช่นเดียวกับการมีคลาสเฟรมเฉพาะ (และดังนั้นจึงเป็นวิธีเฉพาะในการจัดวางองค์ประกอบย่อย) โดยไม่คำนึงถึง displayคุณสมบัติ

หากคุณต้องการให้เด็ก ๆ จัดเรียงอย่างน่าเชื่อถือในโหมดเลย์เอาต์ในแบบข้ามเบราว์เซอร์วิธีที่ดีที่สุดของคุณคือใช้ wrapper-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>พวกเขาต้องการพวกเขาไม่ได้ "บังคับตามสัญญา" เพื่อแสดงผลโดยใช้ไลบรารีวิดเจ็ตระบบหรืออะไรก็ตาม กันไปสำหรับองค์ประกอบอื่น ๆ จริงๆ
พฤศจิกายน

4
@BoltClock ไม่แน่ใจว่าสิ่งที่คุณหมายถึงโดย Limbo เบราว์เซอร์หลักทั้งหมดรองรับการแก้ไขไวยากรณ์ครั้งที่สามและครั้งสุดท้ายนับตั้งแต่ปี 2558 ฉันคิดว่าการทำงานร่วมกันเป็นเรื่องที่ดี เราได้รับการสนับสนุนอย่างกว้างขวางสำหรับ Grid ในตอนนี้! 🎉
Šime Vidas

@ Šime Vidas: เข้าใจแล้วดูเหมือนว่ามันจะเป็น CR มาหนึ่งปีแล้ว ยุติธรรมพอสมควร ฉันคิดว่ามันจะไม่ทำ
BoltClock

9
2017 แน่นอน ฉันจะชี้ความโกรธของฉันที่ไหน? ปีแห่งการรอคอยที่จะใช้ flexbox อย่างปลอดภัยบทความที่นับไม่ถ้วนข้อตกลงการทดลองใช้ / ข้อผิดพลาดฉันได้รับ 98% ที่นั่นและ ... ชุดข้อมูล มันเหมือนกับการให้ช่างไฟฟ้าเดินสายไฟบ้านของฉันเพียงเพื่อจะพบว่าแจ็คกำลังหนึ่งไม่ได้ต่อสายดิน "อย่าพูดเกินจริง" ฉันได้ยินคนคิดว่าพูดเกินจริงฉันไม่ ฉันต้องตอบอย่างแท้จริงในวันพรุ่งนี้ Flex คือคำตอบของข้อบกพร่องตารางดั้งเดิมที่ฉันต้องแก้ Flex เป็นสาเหตุของข้อบกพร่องเล็ก ๆ น้อย ๆ ที่ไม่ได้รับมรดก ฉันจะชี้ความโกรธของฉันที่ไหน?
danjah

22

ฉันพบนี้อาจจะมีข้อผิดพลาดบน Chrome และ Firefox ที่legendและfieldsetจะถูกแทนที่องค์ประกอบ

รายงานข้อบกพร่องแล้ว:

Bug Chrome (ยังเปิดอยู่)
Bug Firefox (แก้ไขตั้งแต่ v46)

วิธีแก้ปัญหาที่เป็นไปได้:

วิธีแก้ปัญหาที่เป็นไปได้คือใช้<div role="group">ใน HTML และใช้ใน CSS div[role='group']เป็นตัวเลือก


UPDATE

ใน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/issues/detail?id=375693

ในเวลานั้นฉันได้สร้างตัวอย่างโค้ดสำหรับปากกาทั้งสามนี้เพื่อแสดงวิธีแก้ไขปัญหา พวกเขาสร้างขึ้นโดยใช้ 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-container เพื่อให้สามารถยืดความสูงขององค์ประกอบพี่น้องและจากนั้นส่งผ่านไปยังลูกของคุณคุณจะต้องใช้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>

การสร้างตำนานที่ซ้ำกันปลอมเพื่อการจัดแต่งทรงผม

นี่เป็นวิธีแฮ็กที่จะทำ ยังคงสามารถเข้าถึงได้ แต่คุณไม่ต้องจัดการกับ ID เมื่อทำเช่นนี้ ข้อเสียเปรียบหลักคือจะมีการทำซ้ำเนื้อหาระหว่างองค์ประกอบตำนานจริงและองค์ประกอบตำนานปลอม

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>

คุณจะค้นพบว่ามันใช้งานได้และจากนั้นคุณอาจจะดำเนินต่อไปโดยไม่ให้ความคิดที่สอง

ปัญหาคือการวาง wrapper div ระหว่าง fieldset และ legend ทำให้ความสัมพันธ์ระหว่างทั้งสององค์ประกอบแตกหัก สิ่งนี้จะแบ่งความหมายของ fieldset / legend

ดังนั้นในการทำเช่นนี้คุณได้เอาชนะวัตถุประสงค์ทั้งหมดของการใช้ fieldset / legend ในตอนแรก

นอกจากนี้ยังมีจุดไม่มากในการใช้ fieldset ถ้าคุณไม่ให้ fieldset ที่เป็นตำนาน


9

ในประสบการณ์ของฉันฉันพบว่าค่า<fieldset>หรือ<button>ไม่<textarea>สามารถใช้อย่างถูกต้องdisplay:flexหรือได้รับการถ่ายทอดคุณสมบัติ

ตามที่คนอื่น ๆ พูดถึงแล้วมีการรายงานข้อผิดพลาด หากคุณต้องการใช้ flexbox เพื่อควบคุมการสั่งซื้อ (เช่นorder:2) คุณจะต้องล้อมองค์ประกอบใน div หากคุณต้องการให้ flexbox ควบคุมรูปแบบและขนาดจริงคุณอาจต้องการใช้ div แทนการควบคุมอินพุต


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

อาจต้องใช้กลุ่มบทบาทเพราะ firefox, chrome และฉันคิดว่าซาฟารีมีข้อผิดพลาดกับ fieldets จากนั้นตัวเลือกใน CSS ก็จะเป็น

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

แก้ไข:นี่คือปัญหาบางอย่างที่คนอื่นกำลังประสบเช่นกัน

ปัญหา 375693

ปัญหา 262679


สิ่งนี้ยังคงเป็นปัญหาใน Chrome 60
evolutionxbox

ยังอยู่ที่นี่ใน Chrome 66
แบรด

Chrome 72 กำลังเช็คอิน
danemacmillan

การเช็คอินของ Chrome 73
Michael Draper

Chrome 75 กำลังเช็คอิน
xaddict

3

คุณสามารถใส่ div เพิ่มเติม<fieldset>ด้วยอุปกรณ์ประกอบฉากต่อไปนี้:

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

1
ฉันไม่เข้าใจ downvotes สิ่งนี้ถูกต้องจริง แต่อย่าลืมเก็บ<legend>องค์ประกอบ (ถ้าใช้) ในระดับบนสุดของ<fieldset>องค์ประกอบเพื่อให้การใช้งานตามที่ตั้งใจไว้ ( Permitted content: An optional <legend> element, followed by flow content.- ดูdeveloper.mozilla.org/en-US/docs/Web/HTML/Element/ … )
Froxx

2
ไม่ใช่ฉัน แต่ฉันควรจินตนาการว่า downvote มีบางอย่างเกี่ยวข้องกับการไม่ตอบคำถาม มันไม่ได้เกี่ยวกับการหาวิธีการแก้ปัญหา แต่พฤติกรรมของfieldsetตัวเอง
Manngo

ใช่อาจไม่ตอบคำถามโดยตรง (ซึ่งเป็นปรัชญาเล็กน้อย) แต่นี่เป็นการแก้ไขที่เป็นไปได้สำหรับข้อผิดพลาดที่ไร้สาระนี้
Eric S. Bullington

โหวตน้อยลงเพราะส่งเสริมให้ทำลายความหมายของ<legend>องค์ประกอบ สิ่งนี้เอาชนะวัตถุประสงค์ของการใช้ fieldset / legend ในตอนแรก ดูคำตอบของฉันที่นี่: stackoverflow.com/a/59425373/1611058
Daniel Tonon

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.