วิธีจัดกึ่งกลางคอนเทนเนอร์แบบยืดหยุ่น แต่จัดชิดซ้าย


92

ฉันต้องการให้รายการดิ้นอยู่ตรงกลาง แต่เมื่อเรามีบรรทัดที่สองให้มี 5 (จากภาพด้านล่าง) ต่ำกว่า 1 และไม่อยู่กึ่งกลางในพาเรนต์

ป้อนคำอธิบายภาพที่นี่

นี่คือตัวอย่างของสิ่งที่ฉันมี:

ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  margin: 0;
  padding: 0;
}
li {
  list-style-type: none;
  border: 1px solid gray;
  margin: 15px;
  padding: 5px;
  width: 200px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
</ul>

http://jsfiddle.net/8jqbjese/2/

คำตอบ:


79

Flexbox Challenge & ข้อ จำกัด

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

เมื่อใช้โค้ดที่โพสต์ในคำถามเราสามารถสร้าง flex container ใหม่ที่ห่อหุ้ม flex container ปัจจุบันul ) ซึ่งจะช่วยให้เราไปที่ศูนย์ด้วยuljustify-content: center

จากนั้นรายการดิ้นของ uljustify-content: flex-startอาจจะเหลือชิดกับ

#container {
    display: flex;
    justify-content: center;
}

ul {
    display: flex;
    justify-content: flex-start;
}

สิ่งนี้จะสร้างกลุ่มไอเท็มเฟล็กซ์ที่จัดชิดซ้ายตรงกลาง

ปัญหาของวิธีนี้คือในบางขนาดหน้าจอจะมีช่องว่างทางด้านขวาของหน้าจอulทำให้ไม่ปรากฏอยู่ตรงกลางอีกต่อไป

ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่

สิ่งนี้เกิดขึ้นเนื่องจากในเค้าโครงแบบยืดหยุ่น (และจริงๆแล้ว CSS โดยทั่วไป) คอนเทนเนอร์:

  1. ไม่รู้ว่าเมื่อใดที่องค์ประกอบห่อหุ้ม
  2. ไม่ทราบว่าพื้นที่ที่เคยครอบครองอยู่นั้นว่างเปล่าและ
  3. ไม่คำนวณความกว้างใหม่เพื่อลดขนาด - ห่อเค้าโครงที่แคบลง

ความยาวสูงสุดของช่องว่างทางด้านขวาคือความยาวของสินค้าเฟล็กซ์ที่คาดว่าคอนเทนเนอร์จะอยู่ที่นั่น

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

การสาธิต


แนวทางปฏิบัติเพิ่มเติม

รูปแบบที่ต้องการสามารถทำได้โดยไม่ต้องใช้ flexbox inline-blockและ คำสั่งสื่อ

HTML

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
</ul>

CSS

ul {
    margin: 0 auto;                  /* center container */
    width: 1200px;
    padding-left: 0;                 /* remove list padding */
    font-size: 0;                    /* remove inline-block white space;
                                        see https://stackoverflow.com/a/32801275/3597276 */
}

li {
    display: inline-block;
    font-size: 18px;                 /* restore font size removed in container */
    list-style-type: none;
    width: 150px;
    height: 50px;
    line-height: 50px;
    margin: 15px 25px;
    box-sizing: border-box;
    text-align: center;
}

@media screen and (max-width: 430px) { ul { width: 200px; } }
@media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
@media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px;  } }
@media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
@media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }

โค้ดด้านบนแสดงคอนเทนเนอร์ที่อยู่ตรงกลางแนวนอนพร้อมด้วยองค์ประกอบลูกที่จัดชิดซ้ายดังนี้:

ป้อนคำอธิบายภาพที่นี่

การสาธิต


ตัวเลือกอื่น

  • ปรับขนาดและจัดแนวรายการดิ้นในแถวสุดท้ายอย่างเหมาะสม

  • การก่ออิฐ Desandro

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

    ที่มา: http://masonry.desandro.com/

  • CSS Grid Layout Module ระดับ 1

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

    แหล่งที่มา: https://drafts.csswg.org/css-grid/


3
ใช่หลายสิ่งที่ผู้คนต้องการทำและจบลงด้วยการใช้ flexbox สำหรับเป็นเพียงการสร้างกริด โชคดีที่สิ่งนี้จะถูกครอบคลุมโดย CSS Grids เมื่อการเข้าถึงนั้นเป็นสถานะที่สรุปได้มากขึ้น
TylerH

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

บางทีความคิดอีกอย่างหนึ่งคือการทำmargin:0 autoบนกระดาษห่อหลักเพื่อให้ทุกอย่างอยู่ตรงกลางบนหน้ากระดาษ จากจุดนั้นส่วนประกอบลูกทั้งหมด (เช่นเฟล็กซ์คอนเทนเนอร์แรก) ก็ไปเกี่ยวกับกระบวนการแถวไหลปกติหรือไม่? ดูเหมือนว่าสิ่งนี้สามารถทำได้ง่ายๆ
klewis

13

คุณสามารถทำได้ด้วย CSS Grid เพียงใช้ repeat(autofit, minmax(width-of-the-element, max-content))

ul {
       display: grid;
       grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
       grid-gap: 16px;
       justify-content: center;
       padding: initial;
}

li {
    list-style-type: none;
    border: 1px solid gray;
    padding: 5px;
    width: 210px;
}
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
</ul>

http://jsfiddle.net/rwa20jkh/


น่าสนใจ. แต่ไม่ได้กำจัดช่องว่างทางด้านขวาหรือตรงกลางของตาราง
สีแดง

2
@Red มีสิ่งหนึ่งที่ผิด ฉันเปลี่ยนjustify-items: centerเป็นjustify-content:centerและตอนนี้ศูนย์สมบูรณ์แบบ
Joe82

ฉันไม่เข้าใจภายในส่วน210px minmaxฉันจะทำสิ่งเดียวกัน แต่ไม่มีข้อ จำกัด เทียมได้210pxอย่างไร? ไม่มีข้อ จำกัด เช่นนั้นกับ flexbox ฉันต้องการผลลัพธ์เหมือนกับ flexbox ทุกประการ แต่พื้นที่เนื้อหาต้องอยู่กึ่งกลางเหมือนในโซลูชันของคุณ
Andrey Mikhaylov - lolmaus

1
สวัสดี @ AndreyMikhaylov-lolmaus วิธีนี้ใช้ได้ผลเมื่อคุณต้องการตั้งค่าความกว้างคงที่ให้กับองค์ประกอบทั้งหมด ในคำถามมันแสดงเป็นwidth:200pxและในตัวอย่างของฉันตามที่ฉันตั้งไว้width:210pxฉันต้องเพิ่มมันด้วยเช่นกันในminmaxส่วน
Joe82

@ Joe82 ขอบคุณสำหรับการชี้แจง! 🙏คุณรู้วิธีทำให้มันใช้งานได้กับองค์ประกอบความกว้างโดยพลการหรือไม่?
Andrey Mikhaylov - lolmaus

0

ตามที่ @michael แนะนำนี่เป็นข้อ จำกัด ของ flexbox ปัจจุบัน แต่ถ้าคุณต้องการที่จะยังคงใช้flexและjustify-content: center;แล้วเราสามารถแก้ปัญหานี้โดยการเพิ่มหุ่นองค์ประกอบและกำหนดlimargin-left

    const handleResize = () => {
        const item_box = document.getElementById('parentId')
        const list_length  = item_box.clientWidth
        const product_card_length = 200 // length of your child element
        const item_in_a_row = Math.round(list_length/product_card_length)
        const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
        const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin 
        const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
        dummy_product.style.marginLeft = `${left_to_set}px`
    }
    handleResize() // Call it first time component mount
    window.addEventListener("resize", handleResize); 

ตรวจสอบซอนี้(ปรับขนาดและดู)หรือวิดีโอสำหรับการอ้างอิง


0

วิธีหนึ่งที่จะทำให้ได้สไตล์ที่ต้องการโดยมีระยะขอบคือทำดังต่อไปนี้:

#container {
    display: flex;
    justify-content: center;
}

#innercontainer {
    display: flex;
    flex: 0.9; -> add desired % of margin
    justify-content: flex-start;
}

0

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

ตัวอย่าง

<div class="table-container">
  <div class="table-content">
    <p class="table-title">Table 1</p>
    <p class="mesa-price">$ 20</p>
  </div>
  
  <!-- Make stuff justified start -->
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
  <div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>

ผลลัพธ์

ป้อนคำอธิบายภาพที่นี่


0

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

หากใครก็ตามที่มาที่นี่แล้วไม่สามารถแก้ไขปัญหาได้แม้ว่าจะอ่านคำตอบเหล่านี้แล้วก็ตามให้ลองชำระเงินเพื่อหาข้อผิดพลาดโง่ ๆ ในกรณีของฉันมันเป็นspanกับflex-growชุดที่จะ1เพิ่มเป็น spacer


-1

ฉันพบปัญหานี้ขณะเขียนโค้ดด้วย React Native มีโซลูชันที่ยอดเยี่ยมที่คุณสามารถใช้ FlexBox ได้ ในสถานการณ์เฉพาะของฉันฉันพยายามจัดกึ่งกลางกล่องดิ้นสามกล่อง (Flex: 2) ไว้ในกล่องอื่นโดยใช้ alignItems วิธีแก้ปัญหาที่ฉันคิดขึ้นคือใช้สองว่างเปล่าแต่ละอันมี Flex: 1

<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
  <View style={{flex: 1}} />
    // Content here
  <View style={{flex: 1}} />
</View>

ง่ายพอที่จะแปลงเป็นเว็บ / CSS


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