จัดตำแหน่งหนึ่งตรงกลางและขวา / ซ้ายจัดองค์ประกอบ Flexbox อื่น ๆ


167

ฉันต้องการที่จะมีA BและCจัดให้อยู่ตรงกลาง

ฉันจะได้รับDที่จะไปอย่างสมบูรณ์เพื่อที่เหมาะสมหรือไม่

ก่อน:

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

หลังจาก:

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

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

คำตอบ:


239

ด้านล่างนี้คือห้าตัวเลือกในการบรรลุเลย์เอาต์นี้:

  • ตำแหน่ง CSS
  • Flexbox พร้อมองค์ประกอบ DOM ที่มองไม่เห็น
  • Flexbox พร้อมองค์ประกอบหลอกที่มองไม่เห็น
  • Flexbox กับ flex: 1
  • เค้าโครงตาราง CSS

วิธีที่ 1: คุณสมบัติการกำหนดตำแหน่ง CSS

นำposition: relativeไปใช้กับภาชนะดิ้น

นำposition: absoluteไปใช้กับรายการ D.

ตอนนี้รายการนี้อยู่ในตำแหน่งที่แน่นอนภายในคอนเทนเนอร์แบบยืดหยุ่น

โดยเฉพาะอย่างยิ่งรายการ D ถูกลบออกจากการไหลของเอกสาร แต่การเข้าพักภายในขอบเขตของบรรพบุรุษในตำแหน่งที่ใกล้ที่สุด

ใช้คุณสมบัติออฟเซ็ต CSS topและrightเพื่อย้ายองค์ประกอบนี้ไปยังตำแหน่ง

ข้อแม้อย่างหนึ่งของวิธีนี้คือเบราว์เซอร์บางตัวอาจไม่สามารถลบรายการดิ้นที่อยู่ในตำแหน่งที่แน่นอนออกจากโฟลว์ปกติ สิ่งนี้จะเปลี่ยนการจัดแนวด้วยวิธีที่ไม่ได้มาตรฐานและไม่คาดคิด รายละเอียดเพิ่มเติม: รายการ flex ที่อยู่ในตำแหน่งที่แน่นอนจะไม่ถูกลบออกจากโฟลว์ปกติใน IE11


วิธีที่ # 2: Flex Auto Margins & Invisible Flex Item (องค์ประกอบ DOM)

ด้วยการรวมกันของautoระยะขอบและรายการเฟล็กซ์ที่มองไม่เห็นใหม่จะทำให้เลย์เอาต์ได้

รายการดิ้นใหม่จะเหมือนกับรายการ D และวางไว้ที่ปลายด้านตรงข้าม (ขอบด้านซ้าย)

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

visibility: hiddenรายการใหม่จะถูกลบออกจากมุมมองที่มี

ในระยะสั้น:

  • สร้างDองค์ประกอบที่ซ้ำกัน
  • วางไว้ที่จุดเริ่มต้นของรายการ
  • ใช้ดิ้นautoอัตรากำไรขั้นต้นที่จะให้A, BและCเป็นศูนย์กลางที่มีทั้งDองค์ประกอบสร้างความสมดุลเท่ากันจากปลายทั้งสอง
  • นำvisibility: hiddenไปใช้กับรายการที่ซ้ำกันD


วิธีที่ # 3: Flex Auto Margins & Invisible Flex Item (องค์ประกอบหลอก)

วิธีนี้คล้ายกับ # 2 ยกเว้นว่าจะสะอาดกว่าในเชิงความหมายและDต้องทราบความกว้าง

  • สร้างองค์ประกอบหลอกที่มีความกว้างเท่ากับD.
  • วางไว้ที่จุดเริ่มต้นของภาชนะด้วย::before.
  • ใช้ดิ้นautoอัตรากำไรขั้นต้นที่จะให้A, BและCตรงกลางพอดีกับหลอกและDองค์ประกอบของการสร้างความสมดุลเท่ากันจากปลายทั้งสอง


วิธีที่ # 4: เพิ่มflex: 1รายการด้านซ้ายและขวา

เริ่มต้นด้วยวิธี # 2 หรือที่ 3 flex: 1ข้างต้นแทนที่จะกังวลเกี่ยวกับความกว้างเท่ากันด้านซ้ายและขวาที่รายการเพื่อรักษาสมดุลเท่ากันเพียงแค่ให้แต่ละคน สิ่งนี้จะบังคับให้ทั้งคู่ใช้พื้นที่ว่างดังนั้นจึงทำให้รายการตรงกลางอยู่ตรงกลาง

จากนั้นคุณสามารถเพิ่มลงdisplay: flexในแต่ละรายการเพื่อจัดแนวเนื้อหาได้

หมายเหตุ เกี่ยวกับการใช้วิธีนี้กับmin-height:ปัจจุบันอยู่ใน Chrome, Firefox, Edge และเบราว์เซอร์อื่น ๆ กฎชวเลขflex: 1แบ่งออกเป็น:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

ที่หน่วยร้อยละ (%)ในflex-basisสาเหตุวิธีนี้ในการหยุดพักเมื่อmin-heightถูกนำมาใช้บนบรรจุภัณฑ์ เนื่องจากตามกฎทั่วไปเปอร์เซ็นต์ความสูงของเด็กต้องการการheightตั้งค่าคุณสมบัติที่ชัดเจนในพาเรนต์

นี่เป็นกฎ CSS แบบเก่าย้อนหลังไปถึงปี 1998 ( CSS ระดับ 2 ) ซึ่งยังคงมีผลในเบราว์เซอร์จำนวนมากในระดับหนึ่ง สำหรับรายละเอียดทั้งหมดดูได้ที่นี่และที่นี่

นี่คือภาพประกอบของปัญหาที่โพสต์ในความคิดเห็นโดยuser2651804 :

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


วิธีที่ # 5: CSS Grid Layout

นี่อาจเป็นวิธีการที่สะอาดและมีประสิทธิภาพมากที่สุด ไม่จำเป็นต้องมีการวางตำแหน่งองค์ประกอบปลอมหรือแฮ็กเกอร์อื่น ๆ

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

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>


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

"รายการใหม่ต้องมีความกว้างเท่ากับรายการ D ที่มีอยู่มิฉะนั้นกล่องตรงกลางจะไม่อยู่ตรงกลางอย่างแน่นอน" - นั่นแย่มากที่ต้องมีความกว้างเท่ากัน แต่ขอบคุณพระเจ้าสำหรับตาราง CSS :)
Vucko

การใช้เทคนิคกริดไอเทมไม่อยู่ตรงกลางตายมีวิธีทำให้องค์ประกอบโลโก้ตายอยู่ตรงกลางได้หรือไม่? imgur.com/a/SVg9xsj
J86

ไม่คุ้นเคยกับโซลูชันกริดมากพอแม้ว่าจะใช้งานได้เหมือนมีเสน่ห์และสะอาดที่สุด คำถามหนึ่งที่ฉันมีคือจะเพิ่มพื้นที่ว่างให้คอลัมน์กลางไม่เท่ากับทั้งสามได้อย่างไร?
Saba Ahang

6

วิธีที่ง่ายที่สุด

.box{
  display:flex;
  justify-content:center;
}
.item1{
   flex:1;
   display: flex;
   justify-content: center;
   transform: translateX(10px);/*D element Width[if needed]*/
}
 <div class="box">
   <div class="item1">
      <div>A</div>
      <div>B</div>
      <div>C</div>
   </div>
   <div class="item2">D</div>
 </div>


3

วิธีแก้ปัญหาที่ง่ายที่สุดคือการจัดศูนย์เนื้อหาให้เหมาะสมกับคอนเทนเนอร์หลักและให้ระยะขอบซ้ายอัตโนมัติแก่องค์ประกอบลูกแรกและสุดท้าย

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


.a,.d {
  margin-left:auto;
}
<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>


1
@Ason คุณพูดถูกเนื่องจากฉันมีเพียงของเล็ก ๆ ทางด้านขวาไม่ได้สังเกตเห็นมัน
Surjith SM

2

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


3
คุณสามารถสาธิตสั้น ๆ เพื่อสำรองคำสั่งของคุณได้หรือไม่?
klewis

อย่าใช้ HTML พิเศษเพียงเพื่อให้ได้รูปลักษณ์บางอย่างสามารถทำลายหน้าเว็บของคุณในเบราว์เซอร์อื่นได้
Hidayt Rahman

1

ด้วยdisplay:gridวิธีการนี้คุณสามารถใส่ulเด็กทั้งหมดลงในเซลล์เดียวกันแล้วตั้งค่าjustify-self:

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>


0

แรงบันดาลใจจากวิธี # 5: CSS Grid Layoutของโซลูชันของ@Michal Benjaminและเนื่องจากฉันใช้ Tailwind และ ณ ตอนนี้ก็ยังไม่สามารถเข้าถึงตัวเลือกกริดทั้งหมดได้ตามค่าเริ่มต้น ดูเหมือนว่าจะได้ผล:

ul {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
li:nth-child(1) { justify-content: flex-start; } // OR: margin-right: auto
li:nth-child(3) { justify-content: flex-end; } // OR: margin-left:auto
li: {align-self: center;}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

PS: ไม่แน่ใจว่าการผสมดิ้นและกริดแบบนี้เป็นความคิดที่ดีหรือไม่!


1
คุณไม่ได้ผสมกริดและเฟล็กซ์เนื้อหาที่สมเหตุสมผลคือคุณสมบัติกริด CSS และคุณสมบัติเฟล็กบ็อกซ์ (เหมือนกันสำหรับการจัดตำแหน่งตัวเอง)
Temani Afif

-1

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

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd


8
สิ่งนี้ไม่ได้อยู่ตรงกลางของรายการตรงกลางอย่างแท้จริงเนื่องจากเป็นเพียงปัจจัยในพื้นที่ที่เหลือไม่ใช่พื้นที่ทั้งหมด codepen.io/anon/pen/QKGrRk
Michael Benjamin

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

ไม่มีเงินรางวัลใดที่จะเพิ่มพฤติกรรมใหม่ให้กับโมเดล Flexbox ที่ Michael_B ให้คำตอบที่ดีเท่าที่จะได้รับ ...
Ason

-1

ฉันขยายความเกี่ยวกับคำตอบของMichael_B

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}

li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Center</li>
    <li>this</li>
  </span>
</ul>

ที่นี่ด้วยความช่วยเหลือของ SASS เป็น codepen


-2

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

grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr

-2
ul { 
  padding: 0; 
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  position:absolute;
  right:10px;

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