Flex-box: จัดแถวสุดท้ายให้กับตาราง


378

ฉันมีเลย์เอาต์แบบเฟล็กซ์บ็อกซ์ที่เรียบง่ายพร้อมคอนเทนเนอร์เช่น:

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

ตอนนี้ฉันต้องการให้รายการในแถวสุดท้ายสอดคล้องกับอีกรายการ justify-content: space-between;ควรใช้เนื่องจากความกว้างและความสูงของตารางสามารถปรับได้

ขณะนี้ดูเหมือนว่า

รายการที่ด้านล่างขวาควรอยู่ตรงกลาง

ที่นี่ฉันต้องการให้รายการที่ด้านล่างขวาเป็น "คอลัมน์กลาง" อะไรคือวิธีที่ง่ายที่สุดในการบรรลุเป้าหมายนั้น? นี่คือjsfiddleขนาดเล็กที่แสดงพฤติกรรมนี้

.exposegrid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.exposetab {
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>



ตรวจสอบทางออกของฉันที่นี่ฉันคิดว่ามันใช้งานได้ดีโดยไม่ต้องแฮ็คแค่คณิตศาสตร์: stackoverflow.com/questions/18744164/…
Sebastien Lorber

5
อีกทางเลือกหนึ่งคือการใช้งานสามารถใช้โมดูล css grid ที่ใหม่กว่าซึ่งไม่มีปัญหานี้
Danield


1
ฉันได้เพิ่มวิธีการแก้ปัญหา JS ทั่วไปสำหรับกรณีที่ความกว้างของเด็กเป็นตัวแปรทำให้จำนวนรายการในตัวแปรแถวเช่นกัน
เทา

คำตอบ:


416

เพิ่ม::afterช่องว่างที่ป้อนอัตโนมัติ ไม่จำเป็นต้องทำให้ HTML ของคุณสกปรก นี่คือ codepen แสดงมัน: http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid::after {
  content: "";
  flex: auto;
}

17
เป็นไปได้ไหมที่จะทำให้มันใช้งานได้กับพื้นที่รอบ ๆ
Tom

60
@DanAndreasson มีสองประเด็นคือไม่เริ่มจากด้านซ้าย (เช่นเว้นวรรคระหว่าง) และช่องว่างระหว่างรายการของแถวสุดท้ายนั้นแตกต่างจากในแถวก่อนหน้า (จำลองรายการความกว้างคงที่บางรายการใน "ขนาดใดก็ได้" grid - เกี่ยวข้องกับทั้งคู่) ... codepen.io/anon/pen/gPoYZEสิ่งที่ฉันต้องการคือการรักษา "กลยุทธ์" (ช่องว่างรอบหรือช่องว่างระหว่าง) แต่เริ่มจากทางซ้ายเหมือนในบรรทัดก่อนหน้า ... ฉัน อยากรู้ว่าถ้าเป็นไปได้ที่จะสรุปวิธีการแก้ปัญหาที่น่าตื่นตาตื่นใจของคุณ
Tom

44
ใช้งานได้เพียงเพราะไอเท็มมีช่องว่างภายในเพื่อเว้นระยะห่างและความกว้างของเปอร์เซ็นต์รวมกันเท่ากับ 100% สำหรับแต่ละชุด 4 ใน codepen นี้ฉันลบออกjustify-content: space-between;จาก.gridและลบออก.grid:afterและใช้งานได้เหมือนกัน ตอนนี้ถ้าคุณพยายามที่บางสิ่งบางอย่างเช่นนี้มันแบ่งกันโดยสิ้นเชิง สังเกตุความกว้างสำหรับชุด 4 ชุดแต่ละชุดจะไม่เกิน 100% ในซอของ OPความกว้างถูกตั้งค่าเป็น px ดังนั้นโซลูชันของคุณจะไม่ทำงานในสถานการณ์นี้
Jacob Alvarez

22
space-betweenพยายามแก้ปัญหานี้ต้นรายการมันก็สั้นในแถวสุดท้ายไม่ได้แพร่กระจายไปอย่างถูกต้องกับ แต่เมื่อฉันตั้งค่าflex-basisของ.grid:afterการปรับขนาดเช่นเดียวกับรายการอื่น ๆ ในตาราง (ต่อเบรกพอยต์เอาชนะรหัสเริ่มต้นดังกล่าวข้างต้น / โมดูลฐาน), การแพร่กระจายแถวสุดท้ายออกมาได้อย่างถูกต้อง ดูเหมือนว่าจะทำงานกับ Safari, iOS, Firefox, Chrome (ต้องทดสอบ IE) และขนาดแถวที่ใหญ่ที่สุดของฉันคือ 3 เมื่อเริ่มต้นใช้งาน
webbower

8
สำหรับความต้องการของฉันสิ่งนี้ใช้ได้กับการปรับเปลี่ยนต่อไปนี้: { content: "";flex: 0 0 32%;max-width: 480px;}และฉันเปลี่ยนความกว้างสูงสุดด้วยการเปลี่ยนแปลงการสืบค้นสื่อเพื่อให้กริดนั้นสมบูรณ์แบบทุกความกว้าง
โคลินผู้วิเศษ

160

เทคนิคหนึ่งจะแทรกจำนวนขององค์ประกอบพิเศษ (มากที่สุดเท่าที่จำนวนสูงสุดขององค์ประกอบที่คุณเคยคาดว่าจะมีในแถว) ที่ได้รับความสูงเป็นศูนย์ ช่องว่างยังคงถูกแบ่ง แต่แถวฟุ่มเฟือยยุบลงเป็นอะไร

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

ในอนาคตสิ่งนี้อาจเกิดขึ้นได้จากการใช้หลาย::after(n)อย่าง


11
โชคไม่ดีที่สิ่งนี้ปนเปื้อนมาร์กอัปในลักษณะที่ไม่ใช้ความหมาย แต่ใช้งานได้ทั้งหมด : SI หวังว่าฉันจะรู้วิธีอื่นในการทำซ้ำพฤติกรรมนี้ flexbox หรืออื่น ๆ ที่ไม่ต้องการองค์ประกอบที่ไม่ใช่ความหมาย
Ryan Norbauer

33
ตกลงมันสกปรก แต่ใช้งานได้และแฮ็กน้อยกว่าแฮ็คจำนวนมาก ทำเครื่องหมายฉันใช้มันจนกระทั่ง :: หลัง (12) ได้รับการสนับสนุนหรือเพิ่มตัวเลือกปรับเพิ่มเติม มันเป็นความอัปยศอย่างแท้จริงเนื่องจากเฟล็กบ็อกซ์แสดงให้เห็นถึงการทำงานในขณะนี้ว่าผิดธรรมดา! หากคุณจัดชิดข้อความในย่อหน้าคุณจะไม่พยายามพิสูจน์ความถูกต้องของบรรทัดสุดท้าย ควรเป็นตัวเลือกอย่างแน่นอนฉันไม่อยากเชื่อเลยว่าพวกเขาจะพลาดสิ่งนี้
Codemonkey

4
ฉันมากับวิธีแก้ปัญหา CSS เท่านั้น .. ข้อแม้นั้นสามารถอธิบายถึงรายการที่หายไปสองรายการเท่านั้นดังนั้นจะทำงานได้อย่างปลอดภัยในตารางแบบยืดหยุ่นที่มีสูงสุดสามรายการต่อแถวที่ห่อ การสาธิต: codepen.io/lukejacksonn/pen/dozqVqหลักการที่นี่คือการใช้องค์ประกอบหลอกเป็นเด็กพิเศษและให้พวกเขามีคุณสมบัติยืดหยุ่นเช่นเดียวกับรายการในภาชนะ
ลุคแจ็คสัน

8
@Codemonkey พระเยซู ฉันเพิ่งเริ่มใช้ flexbox โดยคิดว่าฉันจะกำจัดแฮ็กเหล่านี้ทั้งหมดเพื่อจัดแนวบล็อกอินไลน์ภายในตารางและตอนนี้มันกลับกลายเป็นว่ามันเป็นไปไม่ได้! ฉันได้กดบล็อกนั้นทันทีถึงขีด จำกัด ซึ่งฉันคิดว่าฉันแทบจะไม่เคยเข้าถึงอย่างมีความสุขในการแก้ปัญหา CSS เก่าทั้งหมดที่แก้ไม่ตกเหล่านี้ ไม่เร็วฉันเดา ใช้เวลาเพียง 20 ปีกว่าจะได้จุดศูนย์กลางแนวตั้งที่เหมาะสม - เราสามารถรอได้อย่างแน่นอน ดูเหมือนว่าพระเยซูจะเป็นงานง่าย ๆ ...
Andrey

3
@dellard ฉันไม่คิดอย่างนั้น ดูความคิดเห็นของฉัน
Jacob Alvarez

108

ดังที่ผู้โพสต์คนอื่นพูดถึง - ไม่มีทางที่สะอาดในการจัดเรียงแถวสุดท้ายด้วย flexbox (อย่างน้อยตามสเป็คปัจจุบัน)

อย่างไรก็ตามสำหรับสิ่งที่มีค่า: ด้วยCSS Grid Layout Moduleทำให้สามารถสร้างได้ง่าย:

โดยทั่วไปโค้ดที่เกี่ยวข้องจะลดลงไปถึงสิ่งนี้:

ul {
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */
}

1) ทำให้องค์ประกอบภาชนะเป็นภาชนะตาราง

2) ตั้งค่ากริดด้วยคอลัมน์อัตโนมัติที่มีความกว้าง 100px (สังเกตการใช้การป้อนอัตโนมัติ (ตามที่กำหนดauto-fit- ซึ่ง (สำหรับเค้าโครง 1 แถว) ยุบแทร็กที่ว่างเปล่าเป็น 0) ทำให้รายการขยายเพื่อใช้พื้นที่ที่เหลืออยู่ซึ่งจะทำให้ช่องว่างระหว่าง 'เลย์เอาต์เมื่อกริดมีเพียงแถวเดียวซึ่งในกรณีของเราไม่ใช่สิ่งที่เราต้องการ (ดูตัวอย่างนี้เพื่อดูความแตกต่างระหว่างพวกเขา))

3) ตั้งค่าช่องว่าง / รางสำหรับแถวและคอลัมน์กริด - ที่นี่เนื่องจากต้องการเลย์เอาต์ 'ช่องว่างระหว่าง' - ช่องว่างจะเป็นช่องว่างขั้นต่ำเพราะมันจะเติบโตตามความจำเป็น

4) คล้ายกับ flexbox

การสาธิต Codepen (ปรับขนาดเพื่อดูผลกระทบ)


4
ทางออกที่ดี ปัญหาเดียวคือมันไม่ทำงานกับ IE10 / 11
zendu

1
เกี่ยวกับการauto-fitมีข้อผิดพลาดใน Chrome 57-60 (และเบราว์เซอร์บนพื้นฐานของเครื่องยนต์เช่นซัมซุงอินเทอร์เน็ต 6.0) เพราะสเป็คเป็นบิตคลุมเครือในเวลานั้น ตอนนี้ข้อมูลจำเพาะได้รับการชี้แจงแล้วและ Chrome รุ่นใหม่แสดงauto-fitอย่างถูกต้อง แต่เบราว์เซอร์ที่มีเอ็นจิ้นเก่ายังคงใช้งานอยู่ดังนั้นโปรดใช้ความระมัดระวังกับค่านี้
Ilya Streltsyn

4
ในแง่ของความเป็นไปได้ในปัจจุบันนี้ควรเป็นคำตอบที่ยอมรับได้ การใช้:afterองค์ประกอบหลอกอาจทำให้เกิดผลลัพธ์ที่ไม่พึงประสงค์ในกรณีขอบ
พอล

2
@ Danield ข้อเสนอแนะนี้ช่วยฉันออกมามากขอบคุณ!
Krys

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

27

หากไม่มีมาร์กอัพพิเศษใด ๆ เพียงเพิ่มการ::afterทำงานให้ฉันเพื่อระบุความกว้างของคอลัมน์

.grid {
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
}
.grid::after{
  content: '';
  width: 10em // Same width of .grid__element
}
.grid__element{
  width:10em;
}

ด้วย HTML เช่นนี้

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>

8
นี่เป็นเรื่องที่น่าสนใจ แต่ไม่ค่อยถูกต้องนัก ปัญหาเกิดขึ้นเมื่อคุณติดต่อกับองค์ประกอบมากกว่าสองรายการในแถวล่าง - การเว้นวรรคที่ปรากฏระหว่างองค์ประกอบบนแถวด้านบนจะไม่เกิดขึ้นในช่วงสุดท้าย รายการจะถูกบรรจุเข้าด้วยกันโดยไม่สนใจอรรถประโยชน์ดั้งเดิมของช่องว่างระหว่าง
John Haugeland

ดียิ่งขึ้นถ้าคุณใช้flex-basis: 10emแทนความกว้าง
beytarovski

14

คุณทำไม่ได้ Flexbox ไม่ใช่ระบบกริด justify-content: space-betweenแต่ไม่ได้มีโครงสร้างภาษาที่จะทำในสิ่งที่คุณขออย่างน้อยไม่ว่าคุณกำลังใช้ สิ่งที่ใกล้เคียงที่สุดที่คุณจะได้รับจาก Flexbox คือการใช้การวางแนวคอลัมน์ซึ่งต้องการการตั้งค่าความสูงที่ชัดเจน:

http://cssdeck.com/labs/pvsn6t4z (หมายเหตุ: ไม่รวมคำนำหน้า)

ul {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;
}

อย่างไรก็ตามมันจะง่ายกว่าหากใช้คอลัมน์ที่รองรับได้ดีกว่าและไม่ต้องการตั้งค่าความสูงเฉพาะ:

http://cssdeck.com/labs/dwq3x6vr (หมายเหตุ: ไม่รวมคำนำหน้า)

ul {
  columns: 15em;
}

2
มีวิธีคือ; เห็นคำตอบของฉัน
dalgard

@dellard คำตอบของคุณเป็นวิธีแก้ปัญหาไม่ใช่ทางออกที่แท้จริง คำตอบของ cimmanon นั้นถูกต้อง
Jonah

1
@Jonah ฉันคิดว่า "เทคนิค" เป็นคำอธิบายที่ยุติธรรมสำหรับคำตอบของฉัน มันได้ทำงานเป็นทางออกสำหรับผู้คนจำนวนมากอย่างแน่นอนรวมถึงผู้ถามด้วย
dalgard

2
@dellard มันไม่ได้เปลี่ยนความจริงที่ว่า Flexbox ไม่มีโครงสร้างภาษาเพื่อทำสิ่งที่ถูกถาม นอกจากนี้ฉันจะยืนยันว่าการเพิ่มองค์ประกอบปลอมเป็นวิธีปฏิบัติที่สกปรกอย่างยิ่งโดยการใช้ตารางสำหรับการจัดวาง
# # cimmanon

4
มันไม่สวย แต่การพัฒนาส่วนหน้าเป็นศิลปะของความเป็นไปได้ การปฏิบัตินิยมเป็นหลักฐานพื้นฐาน ฉันคิดว่าคำนี้ถูกวางผิดที่อย่างมากเนื่องจากมีการใช้องค์ประกอบเพิ่มเติมเพื่อจัดแต่งทรงผมใน 99.9% ของเว็บไซต์ในโลกแห่งความเป็นจริง (เช่นองค์ประกอบองค์ประกอบ Bootstrap คอนเทนเนอร์)
dalgard

12

วิธีแก้ปัญหาที่เป็นไปได้คือใช้justify-content: flex-start;บน.gridภาชนะข้อ จำกัด ขนาดของลูกและระยะขอบบนองค์ประกอบลูกที่เหมาะสม - ขึ้นอยู่กับจำนวนคอลัมน์ที่ต้องการ

สำหรับกริดแบบ 3 คอลัมน์ CSS พื้นฐานจะเป็นดังนี้:

.grid {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}

.grid > * {
    flex: 0 0 32%;
    margin: 1% 0;
}

.grid > :nth-child(3n-1) {
    margin-left: 2%;
    margin-right: 2%;
}

มันเป็นอีกวิธีที่ไม่สมบูรณ์ แต่ก็ใช้งานได้

http://codepen.io/tuxsudo/pen/VYERQJ


11

ฉันรู้ว่ามีคำตอบมากมายที่นี่ แต่ .. วิธีที่ง่ายที่สุดในการทำเช่นนี้คือgridแทนที่flexและgrid template columnsด้วยrepeatและauto fillsโดยที่คุณต้องกำหนดจำนวนพิกเซลที่คุณให้กับแต่ละองค์ประกอบ100pxจากโค้ดของคุณ

.exposegrid {
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;
}
 .exposetab {
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
}
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>


2
นี่เป็นทางออกที่เหมาะสมในการจัดแนวรายการสุดท้ายให้อยู่ในแนวเดียวกัน
a.barbieri

ฉันเห็นด้วยวิธีที่เหมาะสมคือการใช้กริด สามารถทำได้ด้วย flexbox แต่สะอาดกว่าการใช้กริด
nbarth

6

ใช่.! เราสามารถ แต่มีบางคำสั่งสื่อและสูงสุดไม่คอลัมน์กำหนดไว้ล่วงหน้า

นี่คือการใช้ 4 คอลัมน์ ตรวจสอบรหัสของฉัน:

.container {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -moz-flex-flow: row wrap;
}

.container .item {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  justify-content: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
}

.container .item .item-child {
  width: 130px;
  height: 180px;
  background: red;
  margin: 10px;
}

@media (max-width: 360px) {
  .container .item {
    flex-basis: 100%;
  }
}

@media (min-width:360px) and (max-width: 520px) {
  .container .item {
    flex-basis: 50%;
  }
}

@media (min-width:520px) and (max-width: 680px) {
  .container .item {
    flex-basis: 33.33%;
  }
}
<div class="container">

  <div class="item">
    <div class="item-child">1</div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>

</div>

หมายเหตุ
1) ไม่จำเป็นต้องสร้าง div ลูก มันอาจเป็นแท็กอื่น ๆ เช่น 'img' สิ่งที่คุณต้องการ ..
2) ถ้าคุณต้องการคอลัมน์เพิ่มเติมให้ปรับคิวรีสื่อและคอลัมน์จำนวนสูงสุด


สิ่งนี้สร้างเพียง 3 ใน IE ล่าสุด
Akxe

6

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

.grid {
    display: flex;
    flex-flow: row wrap;
    margin: 0 -5px; // remove the inital 5px space
    width: auto;
}
.grid__item {
    width: 25%;
    padding: 0 5px; // should be same as the negative margin above.
}

หากคุณต้องการช่องว่างเริ่มต้น 5px เพียงแค่ลบระยะห่างเชิงลบ :) ง่าย ๆ

https://jsfiddle.net/b97ewrno/2/

คำตอบที่ได้รับการยอมรับในขณะที่ดีมันทำให้ไม่มีช่องว่างระหว่างองค์ประกอบในแถวที่สอง ..


1
ประหลาดใจที่ไม่มีคะแนนโหวตเพิ่มขึ้นอีก นี่เป็นวิธีการที่สวยงามที่เป็นของพิพิธภัณฑ์ Flex
Eduardo La Hoz Miranda

1
@EduardoLaHozMiranda ขอบคุณ! แต่ทำไม "พิพิธภัณฑ์"? IE11 ไม่รองรับ css grid และเว็บไซต์ส่วนใหญ่ยังคงต้องการการสนับสนุนดังกล่าว + ตัวจับเวลาขนาดใหญ่ในการพัฒนาส่วนหน้ายังคงอ้างว่ามีกรณีการใช้งานที่แตกต่างกันสำหรับกริดกับ flexbox แต่บางทีคุณแค่ตั้งใจว่านี่ควรเป็นส่วนสำคัญของประวัติเว็บ: D
OZZIE

1
ฮ่า ๆ ๆ ฉันตื่นเต้นในเวลานั้น แค่หมายความว่ามันเป็นปัญหาใหญ่และยอดเยี่ยม
Eduardo La Hoz Miranda

@dencey คุณไม่จำเป็นต้องรู้ว่าสำหรับวิธีนี้มัน 25% ดังนั้นสูงสุด 4 ต่อแถว แต่คุณสามารถใช้เปอร์เซ็นต์ที่คุณต้องการ
OZZIE

@OZZIE ฉันหมายถึงความกว้างของรายการได้รับการแก้ไข (เช่น 100px) แต่ความกว้างของคอนเทนเนอร์เป็นแบบไดนามิกดังนั้นรายการต่อแถวจึงเป็นแบบไดนามิก
Dencey

4

หากคุณต้องการจัดตำแหน่งรายการสุดท้ายให้กับตารางใช้รหัสต่อไปนี้:

ตู้คอนเทนเนอร์แบบกริด

.card-grid {
  box-sizing: border-box;
  max-height: 100%;
  display: flex;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  justify-content: space-between;
  align-items: stretch;
  align-content: stretch;
  -webkit-box-align: stretch;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
}

.card-grid:after {
  content: "";
  flex: 1 1 100%;
  max-width: 32%;
}

รายการในตาราง

.card {
  flex: 1 1 100%;
  box-sizing: border-box;
  -webkit-box-flex: 1;
  max-width: 32%;
  display: block;
  position: relative;

}

เคล็ดลับคือการตั้งค่าความกว้างสูงสุดของรายการเท่ากับความกว้างสูงสุดของ. card-grid: after

การสาธิตสดบน Codepen


cthulu อวยพรคุณและคอมพิวเตอร์ของคุณ
L422Y

3
วิธีการนี้ใช้ไม่ได้เมื่อขนาดของการ์ดคงที่และไม่ทราบจำนวนการ์ดในแต่ละแถว codepen.io/zendu/pen/WXNGvo
zendu

3

เป็นไปได้ที่จะใช้ "เริ่มโค้ง" และเพื่อเพิ่มระยะขอบด้วยตนเอง มันต้องใช้การแฮ็คคณิตศาสตร์ แต่ก็ง่ายที่จะทำและทำให้ใช้งานง่ายด้วยตัวประมวลผล CSS อย่างเช่น LESS

ดูตัวอย่าง LESS mixin นี้:

.flexboxGridMixin(@columnNumber,@spacingPercent) {
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * {
    box-sizing: border-box;
    width: @contentPercent/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  }
}

จากนั้นสามารถนำมาใช้เพื่อแสดงเค้าโครงกริดที่ตอบสนองได้อย่างง่ายดาย:

ul {
  list-style: none;
  padding: 0;
  @spacing: 10%;
  @media only screen and (max-width: 499px) { .flexboxGridMixin(1,@spacing); }
  @media only screen and (min-width: 500px) { .flexboxGridMixin(2,@spacing); }
  @media only screen and (min-width: 700px) { .flexboxGridMixin(3,@spacing); }
  @media only screen and (min-width: 900px) { .flexboxGridMixin(4,@spacing); }
  @media only screen and (min-width: 1100px) { .flexboxGridMixin(5,@spacing); }
}

li {
  background: pink;
  height: 100px;
  margin-top: 20px;
}

นี่คือตัวอย่างของ

http://codepen.io/anon/pen/YyLqVB?editors=110


คุณไม่เคยใช้ @contentPercent คุณตั้งใจจะทำอะไร
neverfox

ความกว้าง: @ contentPercent / @ คอลัมน์หมายเลข;
realtebo

ว้าว ! ฉันประทับใจโซลูชั่นนี้มาก ฉันจะพยายามปรับให้เข้ากับสถานการณ์ของฉัน
realtebo

3

ปัญหานี้ได้รับการแก้ไขสำหรับฉันโดยใช้ตาราง CSS

วิธีนี้ใช้ได้เฉพาะในกรณีที่คุณมีจำนวนคอลัมน์คงที่เช่นไม่ ขององค์ประกอบที่จะแสดงในแถวเดียว

-> ใช้ grid แต่ไม่ได้ระบุจำนวนแถวเนื่องจากจำนวนขององค์ประกอบเพิ่มขึ้นมันจะตัดเป็นคอลัมน์และเพิ่มแถวแบบไดนามิกฉันได้ระบุสามคอลัมน์ในตัวอย่างนี้

-> คุณไม่จำเป็นต้องให้ตำแหน่งใด ๆ กับลูก / เซลล์ของคุณเนื่องจากมันจะทำการแก้ไขซึ่งเราไม่ต้องการ

.grid-class{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 80px;
}


1

รุ่นนี้เป็นวิธีที่ดีที่สุดสำหรับบล็อกที่มีความกว้างคงที่:

http://codepen.io/7iomka/pen/oxxeNE

ในกรณีอื่น - เวอร์ชันของซอลลาร์ด

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
justify-content:center;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  max-width:200px;
  min-width:200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>


0

มีวิธีที่ไม่มีเฟล็กบ็อกซ์แม้ว่าคุณจะต้องปฏิบัติตามเงื่อนไขต่อไปนี้ 1) ภาชนะมีช่องว่างภายใน 2) รายการมีขนาดเท่ากันและคุณรู้จำนวนที่คุณต้องการต่อบรรทัด

ul {
  padding: 0 3% 0 5%;
}
li {
  display: inline-block; 
  padding: 0 2% 2% 0;
  width: 28.66%;
}

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

แน่นอนคุณสามารถทำเช่นเดียวกันได้โดยไม่ต้องแพ็ดดิงบนคอนเทนเนอร์โดยใช้ nth-child (IE 9+) เพื่อลบมาร์จิ้นทุกช่องที่สาม


0

ด้วยการใช้ flexbox และข้อความค้นหาสื่อสองสามข้อฉันได้ทำสิ่งเล็ก ๆ น้อย ๆ นี้: http://codepen.io/una/pen/yNEGjv (แฮ็กบิต แต่ทำงานได้):

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  max-width: 1200px;
  margin: 0 auto;
}

.item {
  background-color: gray;
  height: 300px;
  flex: 0 30%;
  margin: 10px;

  @media (max-width: 700px) {
     flex: 0 45%;
  }

  @media (max-width: 420px) {
    flex: 0 100%;
  }

  &:nth-child(3n-1) {
    margin-left: 10px;
    margin-right: 10px;
  }
}

0

ฉันทำมิกซ์ SCSS สำหรับมัน

@mixin last-row-flexbox($num-columns, $width-items){

  $filled-space: $width-items * $num-columns;
  $margin: calc((100% - #{$filled-space}) / (#{$num-columns} - 1));

  $num-cols-1 : $num-columns - 1;

  &:nth-child(#{$num-columns}n+1):nth-last-child(-n+#{$num-cols-1}) ~ & {
    margin-left: $margin;
  }
  @for $i from 1 through $num-columns - 2 { 
    $index: $num-columns - $i;
    &:nth-child(#{$num-columns}n+#{$index}):last-child{
      margin-right: auto;
    }
  }
}

นี่คือลิงค์ codepen: http://codepen.io/diana_aceves/pen/KVGNZg

คุณเพียงแค่ต้องตั้งค่าความกว้างของรายการเป็นร้อยละและจำนวนคอลัมน์

ฉันหวังว่านี่จะช่วยคุณได้


0

นี่คืออีกสองสามมินท์ scss

มิกซ์อินเหล่านี้คิดว่าคุณจะไม่ใช้ปลั๊กอิน js เช่นไอโซโทป (พวกเขาไม่เคารพลำดับมาร์กอัป html ดังนั้นจึงสับสนกับกฎ css nth)

นอกจากนี้คุณจะสามารถใช้ประโยชน์จากพวกเขาได้อย่างเต็มที่โดยเฉพาะอย่างยิ่งหากคุณเขียนเบรกพอยต์ตอบสนองของคุณในลักษณะมือถือเป็นครั้งแรก คุณจะใช้ flexbox_grid () บนเบรกพอยต์ที่เล็กลงและ flexbox_cell () บนเบรกพอยต์ต่อไปนี้ flexbox_cell () จะดูแลการรีเซ็ตระยะขอบที่ตั้งไว้ก่อนหน้านี้ซึ่งไม่ได้ใช้กับจุดพักขนาดใหญ่อีกต่อไป

และตราบใดที่คุณตั้งค่าคุณสมบัติการโค้งงอของคอนเทนเนอร์ได้อย่างถูกต้องคุณยังสามารถใช้ flexbox_cell () เฉพาะกับรายการได้หากคุณต้องการ

นี่คือรหัส:

// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $gutter_width){

  display: flex;
  flex-direction:row;
  flex-wrap:wrap;
  justify-content: flex-start;

  > *{
    @include flexbox_cell($columns, $gutter_width);
  }
}

// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $gutter_width){
  $base_width: 100 / $columns;
  $gutters: $columns - 1;
  $gutter_offset: $gutter_width * $gutters / $columns;

  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto; // IE10 doesn't support calc() here

  box-sizing:border-box; // so you can freely apply borders/paddings to items
  width: calc( #{$base_width}% - #{$gutter_offset} );

  // remove useless margins (for cascading breakponts)
  &:nth-child(#{$columns}n){
    margin-right: 0;
  }

  // apply margin
  @for $i from 0 through ($gutters){
    @if($i != 0){
      &:nth-child(#{$columns}n+#{$i}){
        margin-right: $gutter_width;
      }
    }
  }
}

การใช้งาน:

ul{
   // just this:
   @include flexbox_grid(3,20px);
}

// and maybe in following breakpoints, 
// where the container is already setted up, 
// just change only the cells:

li{
   @include flexbox_cell(4,40px);
}

เห็นได้ชัดว่ามันขึ้นอยู่กับคุณแล้วในที่สุดคุณจะกำหนดช่องว่างภายใน / ขอบ / ความกว้างและขอบล่างของเซลล์และสิ่งที่ชอบ

หวังว่ามันจะช่วย!


0

นี่มันแฮ็กสวย แต่มันใช้ได้สำหรับฉัน ฉันพยายามบรรลุระยะห่าง / ระยะขอบที่สอดคล้องกัน

.grid {
  width: 1024px;
  display: flex;
  flex-flow: row wrap;
  padding: 32px;
  background-color: #ddd;  

  &:after {
    content: "";
    flex: auto;
    margin-left:-1%;
  }

  .item {
    flex: 1 0 24.25%;
    max-width: 24.25%;
    margin-bottom: 10px;
    text-align: center;
    background-color: #bbb;

    &:nth-child(4n+2),
    &:nth-child(4n+3),
    &:nth-child(4n+4) {
      margin-left: 1%;
    }

    &:nth-child(4n+1):nth-last-child(-n+4),
      &:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
        margin-bottom: 0;
    }    

  }
}

http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/


0

ดูเหมือนว่าไม่มีใครเสนอวิธีแก้ปัญหาการขยายแบบยืดหยุ่นในรายการสุดท้าย ความคิดคือการมีไอเท็มเฟล็กซ์ชิ้นสุดท้ายของคุณเพื่อใช้สถานที่ทั้งหมดโดยใช้เฟล็กซ์ - รี: 1

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid > *:last-child {
  flex-grow: 1;
}

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


0

นี่คือการรวมกันของคำตอบจำนวนมาก แต่มันทำในสิ่งที่ฉันต้องการ - ซึ่งก็คือการจัดตำแหน่งลูกคนสุดท้ายใน flex container ไปทางซ้ายในขณะที่รักษาช่องว่างระหว่างพฤติกรรม (ในกรณีนี้มันเป็นสามคอลัมน์ รูปแบบ)

นี่คือมาร์กอัป:

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-direction: row;
}

.flex-container:after {
  content: "";
  flex-basis: 30%;
}

1
ในการเป็นแบบทั่วไปมากขึ้น: ขนาดแบบโค้งงอจะต้องเท่ากับขนาดของลูก
Christian Toffolo

1
ฉันได้พบแล้ว flex-grow: 0.9แทนการflex-basisทำงานสำหรับคอลัมน์จำนวนเท่าใดก็ได้ การทดสอบในพวงของเบราว์เซอร์ที่ทันสมัย - การทำงานในพวกเขาทั้งหมด แต่ padding เสียใน IE ( แต่ทำงานใน Edge0
Patabugen

0

สมมติว่า:

  • คุณต้องการโครงร่างกริด 4 คอลัมน์พร้อมการตัดคำ
  • จำนวนรายการไม่จำเป็นต้องคูณด้วย 4

กำหนดระยะขอบซ้ายบนทุกรายการยกเว้นรายการที่ 1, 5 และ 9 และอื่น ๆ หากระยะขอบซ้ายคือ 10px แล้วแต่ละแถวจะมีระยะห่าง 30px กระจายระหว่าง 4 รายการ คำนวณเปอร์เซ็นต์ความกว้างของรายการดังนี้:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

นี่เป็นวิธีแก้ปัญหาที่ดีสำหรับปัญหาเกี่ยวกับ flexbox แถวสุดท้าย

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0 3em;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>


0

หากคุณทราบความกว้างของช่องว่างระหว่างองค์ประกอบในแถวและจำนวนองค์ประกอบในแถวสิ่งนี้จะได้ผล:

ตัวอย่าง: 3 องค์ประกอบในแถวช่องว่าง 10px ระหว่างองค์ประกอบ

div:last-child:nth-child(3n+2) {
  flex-grow: 1
  margin-left: 10px
}

0

เพียงใช้เคล็ดลับ Jquery / Javascript เพื่อเพิ่ม div ว่าง:

if($('.exposegrid').length%3==2){
 $(".exposegrid").append('<div class="exposetab"></div>');
}

-1

โอ้ฉันคิดว่าฉันพบทางออกที่ดีด้วย CSS ขั้นต่ำและไม่มี JS ลองดูสิ:

img {width:100%;}
li {
  display: inline-block;
  width:8em;
  list-style:none;
}
ul {text-align: justify;}
<ul>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

กุญแจสำคัญที่นี่คือการจำไว้ว่าสิ่งที่เราพยายามที่จะบรรลุคือสิ่งที่text-align: justifyไม่!

องค์ประกอบที่ว่างเปล่าใน HTML นั้นอยู่ที่นั่นเพื่อทำให้แถวสุดท้ายแสดงผลได้อย่างสมบูรณ์แบบโดยไม่ต้องเปลี่ยนรูปลักษณ์ แต่อาจไม่จำเป็นสำหรับสิ่งที่คุณพยายามทำ เพื่อความสมดุลที่สมบูรณ์แบบในทุกสถานการณ์คุณต้องมีองค์ประกอบว่างเปล่าอย่างน้อย x-4, x คือจำนวนองค์ประกอบที่จะแสดงหรือ n-2, n คือจำนวนคอลัมน์ที่คุณต้องการแสดง


-1

เพียงเพิ่มรายการปลอมไม่กี่รายการที่มีคุณสมบัติเดียวกันยกเว้นความสูงที่กำหนดไว้ที่ 0px ต่อท้าย


การเพิ่มรายการปลอมเป็นการปฏิบัติที่ไม่ดีในทุก ๆ ทาง คุณไม่ควรกรอก DOM ด้วยสิ่งของเพียงเพื่อแฮกรอบ CSS เว้นแต่ได้รับคำสั่ง ด้วยเหตุผลหลายประการตั้งแต่ความสามารถในการเข้าถึงจนถึงการทำให้ codebase ท่วมท้นไปด้วยสิ่งแปลกประหลาดไปจนถึงการทำให้ตรรกะมีความซับซ้อนมากขึ้นในการทำความเข้าใจและทำรายการต่อไป อย่าแนะนำแฮ็กเว้นแต่คุณจะพูดอย่างชัดเจนว่าอาจเป็นวิธีที่ไม่ดีหรือมีกรณีพิเศษสำหรับเรื่องนั้น
Eksapsy

-4

คุณต้องการจัดตำแหน่ง

ใช้align-content: flex-start;แทนjustify-content: space-between;

สิ่งนี้จะดึงรายการแถวสุดท้ายไปทางซ้ายและกระจายพื้นที่อย่างสม่ำเสมอ

.container {
  display: flex;
  flex-flow: row wrap;
  align-content: flex-start;
  /*justify-content: space-between; remove this line!!!! */ 
}

https://codepen.io/anon/pen/aQggBW?editors=1100


วิธีการแก้ปัญหา danAnderson ไม่ใช่ DYNAMIC .PERİOD !!

เมื่อความกว้างของรายการเปลี่ยนจาก 25 เป็น 28 และแอนเดอร์สันไม่สามารถเว้นวรรคระหว่างภาพ

danAnderson: https://codepen.io/anon/pen/ZwYPmB?editors=1100

แบบไดนามิก: https://codepen.io/anon/pen/aQggBW?editors=1100

นั่นคือสิ่งที่ ive พยายามพูด dans แฮ็ค .....


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