เมื่อไอเท็ม flexbox ห่อในโหมดคอลัมน์คอนเทนเนอร์จะไม่เพิ่มความกว้าง


168

ฉันกำลังทำงานกับโครงร่าง flexbox ที่ซ้อนกันซึ่งควรทำงานดังนี้:

ระดับนอกสุด ( ul#main) เป็นรายการแนวนอนที่ต้องขยายไปทางขวาเมื่อมีการเพิ่มรายการเข้าไปในรายการเพิ่มเติม ถ้ามันใหญ่เกินไปมันควรจะมีแถบเลื่อนแนวนอน

#main {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* ...and more... */
}

แต่ละรายการในรายการนี้ ( ul#main > li) มีส่วนหัว ( ul#main > li > h2) และรายการภายใน ( ul#main > li > ul.tasks) รายการด้านในนี้เป็นแนวตั้งและควรตัดเข้าไปในคอลัมน์เมื่อจำเป็น เมื่อตัดเป็นคอลัมน์เพิ่มเติมความกว้างควรเพิ่มเพื่อให้มีที่ว่างสำหรับรายการเพิ่มเติม การเพิ่มความกว้างนี้ควรใช้กับรายการที่มีของรายการด้านนอกด้วย

.tasks {
    flex-direction: column;
    flex-wrap: wrap;
    /* ...and more... */
}

ปัญหาของฉันคือรายการภายในไม่ห่อเมื่อความสูงของหน้าต่างเล็กเกินไป ฉันได้ลองยุ่งเกี่ยวกับคุณสมบัติยืดหยุ่นทั้งหมดพยายามทำตามแนวทางที่CSS-Tricksอย่างพิถีพิถัน แต่ไม่มีโชค

JSFiddleนี้แสดงสิ่งที่ฉันมีจนถึงตอนนี้

ผลลัพธ์ที่คาดหวัง (สิ่งที่ฉันต้องการ) :

ผลลัพธ์ที่ฉันต้องการ

ผลลัพธ์ที่แท้จริง (สิ่งที่ฉันได้รับ) :

เอาท์พุทปัจจุบันของฉัน

ผลลัพธ์ที่เก่ากว่า (สิ่งที่ฉันได้ในปี 2558) :

ผลลัพธ์เก่าของฉัน

UPDATE

หลังจากการตรวจสอบบางอย่างนี้เริ่มดูเหมือนเป็นปัญหาใหญ่ เบราว์เซอร์หลักทั้งหมดทำงานในลักษณะเดียวกันและไม่เกี่ยวข้องกับการออกแบบ flexbox ของฉัน แม้แต่โครงร่างคอลัมน์ flexbox ที่ง่ายกว่าปฏิเสธที่จะเพิ่มความกว้างของรายการเมื่อรายการถูกตัด

JSFiddle อื่นนี้แสดงให้เห็นถึงปัญหาอย่างชัดเจน ใน Chrome เวอร์ชันปัจจุบัน, Firefox และ IE11 รายการทั้งหมดจะถูกห่ออย่างถูกต้อง; ความสูงของรายการจะเพิ่มขึ้นในrowโหมด แต่ความกว้างของรายการจะไม่เพิ่มขึ้นในcolumnโหมด นอกจากนี้ยังไม่มีองค์ประกอบ reflow ทันทีเมื่อเปลี่ยนความสูงของcolumnโหมด แต่มีในrowโหมด

อย่างไรก็ตามสเป็คอย่างเป็นทางการ(ดูเฉพาะตัวอย่างที่ 5)ดูเหมือนจะระบุว่าสิ่งที่ฉันต้องการจะทำควรจะเป็นไปได้

บางคนสามารถแก้ไขปัญหานี้ได้หรือไม่

อัพเดท 2

หลังจากการทดลองใช้ JavaScript เพื่ออัปเดตความสูงและความกว้างขององค์ประกอบต่างๆในระหว่างการปรับขนาดเหตุการณ์ฉันได้ข้อสรุปว่ามันซับซ้อนเกินไปและมีปัญหามากเกินไปที่จะพยายามแก้ไขด้วยวิธีนี้ นอกจากนี้การเพิ่มจาวาสคริปต์จะทำให้แตกรุ่น flexbox อย่างแน่นอนซึ่งควรรักษาให้สะอาดที่สุดเท่าที่จะทำได้

สำหรับตอนนี้ฉันกลับไปoverflow-y: autoแทนflex-wrap: wrapเพื่อให้ภาชนะด้านในเลื่อนตามแนวตั้งเมื่อจำเป็น มันไม่ได้สวย แต่เป็นหนทางข้างหน้าอย่างน้อยก็ไม่ทำลายการใช้งานมากเกินไป


2
เพียง sidenote แต่มีข้อผิดพลาดใน Chrome ที่ทำให้ภาชนะที่มีการไหลตั้งค่าเป็นcolumn wrapไม่ขยายความกว้างเมื่อห่อ ดูcode.google.com/p/chromium/issues/detail?id=247963สำหรับข้อมูลเพิ่มเติม
Gerrit Bertier

ฉันไม่สามารถใช้งานได้ใน IE11 เช่นกัน ที่นั่นรายการภายในสุดห่อ แต่รายการด้านในและคอนเทนเนอร์ (รายการด้านนอก) จะไม่เพิ่มความกว้าง ขณะนี้ฉันกลับไปที่การเลื่อนรายการด้านใน แต่ก็ไม่ใช่วิธีแก้ปัญหาระยะยาวที่ดีและฉันอยากหลีกเลี่ยงการเพิ่ม JavaScript สำหรับสิ่งนี้
Anders Tornblad

คำตอบ:


171

ปัญหา

ดูเหมือนว่าข้อบกพร่องพื้นฐานในรูปแบบเฟล็กซ์

คอนเทนเนอร์แบบยืดหยุ่นในทิศทางคอลัมน์จะไม่ขยายเพื่อรองรับคอลัมน์เพิ่มเติม (นี่ไม่ใช่ปัญหาflex-direction: rowค่ะ)

คำถามนี้ถูกถามหลายครั้ง (ดูรายการด้านล่าง) โดยไม่มีคำตอบที่ชัดเจนใน CSS

เป็นการยากที่จะระบุว่านี่เป็นข้อผิดพลาดเนื่องจากปัญหาเกิดขึ้นกับเบราว์เซอร์หลักทั้งหมด แต่มันทำให้เกิดคำถาม:

เป็นไปได้อย่างไรที่เบราว์เซอร์หลักทั้งหมดจะมีเฟล็กซ์คอนเทนเนอร์เพื่อขยายแบบ wrap ในทิศทางแถว แต่ไม่ได้อยู่ในทิศทางคอลัมน์?

คุณจะคิดว่าอย่างน้อยหนึ่งในนั้นจะทำให้ถูกต้อง ฉันสามารถเก็งกำไรในเหตุผลเท่านั้น อาจเป็นการใช้งานที่ยากลำบากทางเทคนิคและถูกระงับการทำซ้ำ

UPDATE:ปัญหานี้ดูเหมือนจะได้รับการแก้ไขใน Edge v16


ภาพประกอบของปัญหา

OP สร้างตัวอย่างที่มีประโยชน์ซึ่งแสดงให้เห็นถึงปัญหา ฉันกำลังคัดลอกมาที่นี่: http://jsfiddle.net/nwccdwLw/1/


ตัวเลือกการแก้ปัญหา

โซลูชันแฮ็คจากชุมชน Stack Overflow:


การวิเคราะห์เพิ่มเติม


บทความอื่น ๆ ที่อธิบายถึงปัญหาเดียวกัน


2
ตามความคิดเห็นรายงานข้อผิดพลาดปัญหานี้จะไม่ได้รับการแก้ไขจนกว่าพวกเขาจะเปิดตัวเครื่องมือเค้าโครงใหม่ของพวกเขาLayoutNG
Ben.12

5
จำนวนลิงค์ที่คุณให้และจัดหมวดหมู่มันยอดเยี่ยมมาก ฉันหวังว่าคนส่วนใหญ่จะเขียนคำตอบด้วยวิธีนี้ คำตอบที่ดี
Vignesh

4
นี่คือรายการซื้อคืนที่มีประโยชน์ซึ่งแสดงรายการข้อผิดพลาด
Ben.12

เราสามารถแก้ไขปัญหานี้โดยใช้ตาราง CSS ได้หรือไม่
Ismail Farooq

อีกหนึ่งตัวเลือกวิธีแก้ปัญหา: codepen.io/_mc2/pen/PoPmJRPสำหรับบางแง่มุมฉันพบว่าวิธีการเขียนโหมดดีกว่า
michalczerwinski

38

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

display: grid;
grid-auto-flow: column;
grid-template-rows: repeat(6, auto);

ฉันมีตัวอย่างใน CodePen ที่สลับระหว่างปัญหา flexbox กับการแก้ไขกริด: https://codepen.io/MandeeD/pen/JVLdLd


1
นั่นเป็นวิธีแก้ปัญหาที่สง่างามหากฉันเคยเห็นมา! ฉันเพิ่งเข้าสู่กริดและฉันรักทางออกของคุณขอบคุณสำหรับสิ่งนี้
อัลเบิร์ต

จับได้เห็นชัดตรงเผง! แก้ไขปัญหาของฉัน
Celestin Bochis

ยังคงพบปัญหานี้ใน Chrome ฉันหวังว่าจะหลีกเลี่ยงการใช้วิธีแก้ปัญหาแบบกริด เป็นการดีที่รู้ว่าคนอื่นใช้วิธีนี้!
trukvl

ชีวิตประหยัด นอกจากนี้คุณยังสามารถใช้grid-row-end: span X;หากคุณต้องการบางรายการในการเพิ่มแถว
Meirion Hughes

0

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

    element.style.flexBasis = "auto";
    element.style.flexBasis = `${element.scrollWidth}px`;

0

ฉันเพิ่งพบวิธีแก้ปัญหา CSS ที่ยอดเยี่ยมจริงๆที่นี่

https://jsfiddle.net/gcob492x/3/

The หากิน: ตั้งค่าwriting-mode: vertical-lrในรายการ div แล้วwriting-mode: horizontal-tbในรายการ ฉันต้องปรับแต่งสไตล์ใน JSFiddle (ลบสไตล์การจัดตำแหน่งจำนวนมากซึ่งไม่จำเป็นสำหรับการแก้ปัญหา)

หมายเหตุ: ความคิดเห็นกล่าวว่าใช้งานได้เฉพาะในเบราว์เซอร์ที่ใช้ Chromium ไม่ใช่ Firefox ฉันทดสอบด้วยตนเองใน Chrome เท่านั้น เป็นไปได้ว่าอาจมีวิธีการแก้ไขเพื่อให้สามารถทำงานในเบราว์เซอร์อื่นหรือมีการอัปเดตสำหรับเบราว์เซอร์ที่กล่าวมาซึ่งทำให้การทำงานนี้

บิ๊ก shoutout ความคิดเห็นนี้: เมื่อห่อรายการ flexbox ในโหมดคอลัมน์ภาชนะไม่เติบโตกว้าง การขุดผ่านหัวข้อปัญหานั้นทำให้ฉันไปที่https://bugs.chromium.org/p/chromium/issues/detail?id=507397#c39ซึ่งทำให้ฉันไปที่ JSFiddle นี้


-1

เนื่องจากยังไม่มีวิธีการแก้ปัญหาหรือวิธีแก้ปัญหาที่เหมาะสมฉันจึงจัดการเพื่อรับพฤติกรรมที่ร้องขอด้วยวิธีการที่แตกต่างกันเล็กน้อย แทนที่จะแยกเลย์เอาต์ออกเป็น 3 divs ที่แตกต่างกันฉันจะเพิ่มไอเท็มทั้งหมดลงใน 1 div และสร้างการแยกโดยใช้ div อื่น ๆ

วิธีแก้ปัญหาที่เสนอนั้นเขียนโค้ดแบบยากโดยสมมติว่าเรามี 3 ส่วน แต่สามารถขยายไปยังส่วนทั่วไปได้ แนวคิดหลักคือการอธิบายวิธีที่เราสามารถบรรลุเค้าโครงนี้

  1. เพิ่มรายการทั้งหมดลงใน 1 คอนเทนเนอร์ div ที่ใช้ flex เพื่อตัดรายการ
  2. รายการแรกของ "ตู้คอนเทนเนอร์ด้านใน" (ฉันจะเรียกมันว่าส่วน) จะมีชั้นเรียนซึ่งจะช่วยให้เราทำกิจวัตรที่สร้างการแยกและจัดแต่งทรงผมของแต่ละส่วน
  3. :beforeเมื่อใช้กับรายการแรกเราสามารถค้นหาชื่อของแต่ละส่วนได้
  4. การใช้spaceสร้างช่องว่างระหว่างส่วน
  5. เนื่องจากspaceจะไม่ครอบคลุมความสูงเต็มของส่วนฉันยังเพิ่ม:afterไปยังส่วนดังนั้นการวางตำแหน่งด้วยตำแหน่งที่แน่นอนและพื้นหลังสีขาว
  6. หากต้องการจัดสไตล์สีพื้นหลังของแต่ละส่วนฉันจะเพิ่ม div อื่นในรายการแรกของแต่ละส่วน ฉันจะได้ตำแหน่งที่แน่นอนเช่นกันและจะมีz-index: -1ฉันจะเป็นตำแหน่งที่มีแน่นอนเป็นอย่างดีและจะมี
  7. เพื่อให้ได้ความกว้างที่ถูกต้องของแต่ละพื้นหลังฉันใช้ JS ตั้งค่าความกว้างที่ถูกต้องและเพิ่มตัวฟังเพื่อปรับขนาด

function calcWidth() {
  var size = $(document).width();
  var end = $(".end").offset().left;

  var todoWidth = $(".doing-first").offset().left;
  $(".bg-todo").css("width", todoWidth);

  var doingWidth = $(".done-first").offset().left - todoWidth;
  $(".bg-doing").css("width", doingWidth);

  var doneWidth = $(".end").offset().left - $(".done-first").offset().left;
  $(".bg-done").css("width", doneWidth + 20);

}

calcWidth();

$(window).resize(function() {
  calcWidth();
});
.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  height: 120px;
  align-content: flex-start;
  padding-top: 30px;
  overflow-x: auto;
  overflow-y: hidden;
}

.item {
  width: 200px;
  background-color: #e5e5e5;
  border-radius: 5px;
  height: 20px;
  margin: 5px;
  position: relative;
  box-shadow: 1px 1px 5px 0px rgba(0, 0, 0, 0.75);
  padding: 5px;
}

.space {
  height: 150px;
  width: 10px;
  background-color: #fff;
  margin: 10px;
}

.todo-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "To Do (2)";
  font-weight: bold;
}

.doing-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Doing (5)";
  font-weight: bold;
}

.doing-first:after,
.done-first:after {
  position: absolute;
  top: -35px;
  left: -25px;
  width: 10px;
  height: 180px;
  z-index: 10;
  background-color: #fff;
  content: "";
}

.done-first:before {
  position: absolute;
  top: -30px;
  height: 30px;
  content: "Done (3)";
  font-weight: bold;
}

.bg-todo {
  position: absolute;
  background-color: #FFEFD3;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -10px;
  z-index: -1;
}

.bg-doing {
  position: absolute;
  background-color: #EFDCFF;
  width: 100vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.bg-done {
  position: absolute;
  background-color: #DCFFEE;
  width: 10vw;
  height: 150px;
  top: -30px;
  left: -15px;
  z-index: -1;
}

.end {
  height: 150px;
  width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">

  <div class="item todo-first">
    <div class="bg-todo"></div>
    Drink coffee
  </div>
  <div class="item">Go to work</div>

  <div class="space"></div>

  <div class="item doing-first">
    <div class="bg-doing"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>

  <div class="space"></div>

  <div class="item done-first">
    <div class="bg-done"></div>
    1
  </div>
  <div class="item">2</div>
  <div class="item">3</div>

  <div class="end"></div>

</div>


-2

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

var ul = $("ul.ul-to-fix");

if(ul.find("li").length>{max_possible_rows)){
    if(!ul.hasClass("width-calculated")){
        ul.width(ul.find("li").eq(0).width()*ul.css("columns"));
        ul.addClass("width-calculated");
     }
}

น่าเสียดายที่มันไม่ได้ช่วยอะไรเพราะความสูงของแต่ละองค์ประกอบอาจแตกต่างกันไป ดังนั้นจำนวนองค์ประกอบจึงไม่น่าสนใจ ... แต่การใช้columnsคุณสมบัติรูปแบบอาจเป็นจุดเริ่มต้นสำหรับวิธีการทำงาน อาจปรับจำนวนคอลัมน์และความกว้างของ ul
Anders Tornblad

1
ฉันก็ลงเอยด้วยการแก้ปัญหา JS สำหรับปัญหานี้สำหรับแอปพลิเคชันตอบโต้ที่ฉันทำงานอยู่ มันถูกออกแบบมาเพื่อทำงานกับองค์ประกอบใด ๆ และขนาดที่แตกต่างกัน ตัวอย่างที่นี่: djskinner.github.io/react-column-wrap ซอร์สโค้ดที่นี่: github.com/djskinner/react-column-wrap
djskinner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.