ทำไมการจัดแนวตั้ง: ตรงกลางไม่ทำงานกับช่วงหรือ div ของฉัน


247

ฉันพยายามจัดองค์ประกอบspanหรือdivองค์ประกอบในแนวตั้งภายในdivองค์ประกอบอื่น อย่างไรก็ตามเมื่อฉันใส่vertical-align: middleไม่มีอะไรเกิดขึ้น ฉันได้ลองเปลี่ยนdisplayคุณสมบัติขององค์ประกอบทั้งสองและดูเหมือนว่าจะไม่มีอะไรทำงาน

นี่คือสิ่งที่ฉันกำลังทำอยู่ในหน้าเว็บของฉัน:

.main {
  height: 72px;
  vertical-align: middle;
  border: 1px solid black;
  padding: 2px;
}
    
.inner {
  vertical-align: middle;
  border: 1px solid red;    
}
    
.second {
  border: 1px solid blue; 
}
<div class="main">
  <div class="inner">
    This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

นี่คือ jsfiddle ของการนำไปใช้งานแสดงว่ามันใช้งานไม่ได้: http://jsfiddle.net/gZXWC/

คำตอบ:


207

นี่น่าจะเป็นวิธีที่ดีที่สุด - เวลาผ่านไปแล้วตั้งแต่โพสต์ดั้งเดิมของฉันและนี่คือสิ่งที่ควรทำตอนนี้: http://jsfiddle.net/m3ykdyds/200

/* CSS file */

.main {
    display: table;
}

.inner {
    border: 1px solid #000000;
    display: table-cell;
    vertical-align: middle;
}

/* HTML File */
<div class="main">
    <div class="inner"> This </div>
</div>

2
ดังนั้นใครบางคนทำในสิ่งที่ OP ต้องการทำอย่างไร
Ryan Mortensen

ความคิดเห็นใด ๆ เกี่ยวกับย่อหน้าของตัวแปรบรรทัด? กล่าวคือ หากไม่มีทางรู้ว่ามันจะเป็นหนึ่งหรือสองบรรทัด ฉันต้องการผู้ใช้ jQuery หรือไม่?
foochow

เกิดอะไรขึ้นถ้าความสูงต้องเป็นแบบไดนามิกการแก้ปัญหาคืออะไร?
Murhaf Sousli

ไม่ควรเป็นคำตอบที่ได้รับการยอมรับอาศัยการรู้ระดับความสูงของ '. ininner' ดังนั้นจึงไม่ตรงกับที่ OP ขอและคำตอบที่ดีกว่าด้านล่างดูคำตอบ @timbergus หรือ Tim Perkins 'ใกล้ด้านล่าง
mike-source

@ mike-source รู้ว่าความสูงของด้านในนั้นเป็นไปได้ 100% แม้ว่าความสูงนั้นจะเป็นแบบไดนามิกเพราะจาวาสคริปต์เพียงเล็กน้อยก็สามารถเข้าใจและเปลี่ยนแปลงกฎ CSS สำหรับวัตถุ DOM นั้นได้แบบไดนามิก
Charles Addis

143

ใช้ CSS3:

<div class="outer">
   <div class="inner"/>
</div>

css:

.outer {
  display : flex;
  align-items : center;
  justify-content: center;
}

หมายเหตุ: สิ่งนี้อาจไม่ทำงานใน IE เก่า


16
สิ่งนี้ได้รับการสนับสนุนโดยเบราว์เซอร์สมัยใหม่ที่สำคัญทั้งหมดและโดยวิธีการที่ง่ายและสะอาดที่สุด
Sam

2
นอกจากนี้โปรดทราบว่าinline-flexมีองค์ประกอบหลายรายการในแถวภายในองค์ประกอบด้านใน
Dan Nissenbaum

1
ในกรณีของผมตั้งแต่ผมอยากจะอยู่ตรงกลางของเนื้อหา .inner .inner { width: 100%; }ในแนวนอนเกินไปฉันมีการเพิ่ม วิธีนี้ดูเหมือนว่าจะทำงานได้เหมือน.outer { display: table; } .inner { display: table-cell; vertical-align: middle; }แต่ไม่มีการบังคับให้ใช้ความกว้างขั้นต่ำ
Bart S

ฉันเคยjustify-content: center;จัดแนวนอนซึ่งใช้งานได้ดี
Ruth Young

140

ลองใช้วิธีนี้ใช้ได้กับฉันดีมาก:

/* Internet Explorer 10 */
display:-ms-flexbox;
-ms-flex-pack:center;
-ms-flex-align:center;

/* Firefox */
display:-moz-box;
-moz-box-pack:center;
-moz-box-align:center;

/* Safari, Opera, and Chrome */
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;

/* W3C */
display:box;
box-pack:center;
box-align:center;

4
คำตอบที่ยอดเยี่ยมนี่ทำให้ฉันมีวิธีการแก้ปัญหาที่ทำงานได้อย่างเต็มที่ซึ่งไม่ได้ทำให้เกิดปัญหาอื่น ๆ ในการเคาะ (แอพที่ใช้ jquerymobile + phonegap เพียงเพื่อชี้ให้เห็นว่าพารามิเตอร์เหล่านี้จะต้องเพิ่มไปยังบล็อก CSS เฉพาะองค์ประกอบที่จะเป็นศูนย์กลาง / กลางเช่น: #element span {height:100%;display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}- หมายเหตุความสูงเป็นสิ่งสำคัญเพื่อให้แน่ใจว่าช่วงสืบทอดมรดกเต็มความสูงของภาชนะ (อาจเป็น div) เป็นอย่างอื่น คุณยังคงไม่ได้อยู่กึ่งกลางแนวตั้ง!
Andy Lorenz

BTW คุณสามารถเขียนรหัส flexbox มาตรฐานโดยไม่ต้องใช้คำนำหน้าเบราว์เซอร์แล้วรับเบราว์เซอร์นำหน้าด้วย autoprefixer github.com/postcss/autoprefixerหรือสาธิตออนไลน์simevidas.jsbin.com/gufoko/quiet
starikovs

2
มูลค่าทรัพย์สินที่ไม่ถูกต้องboxในdisplay
Joaquinglezsantos

นอกจากนี้คำตอบของ @ user1782556 ยังทำงานได้ดีขึ้นเมื่อกล่องด้านนอกมีช่องว่างภายใน
iautomation

34

การตั้งค่าความสูงบรรทัดเป็นความสูงเดียวกันกับที่มี div จะทำงานได้เช่นกัน

DEMO http://jsfiddle.net/kevinPHPkevin/gZXWC/7/

.inner {
    line-height:72px;
    border: 1px solid #000000;
}

1
ฉันโพสต์ลิงค์ที่อธิบายวิธีนั้นเช่นกัน ไม่ใช่วิธีที่ฉันชอบ แต่ถ้าส่วนที่เหลือของเลย์เอาท์ไม่ได้รับการแก้ไขในขนาด - ฉันพบปัญหาเกี่ยวกับวิวพอร์ตขนาดต่าง ๆ ด้วยวิธีนี้
Charles Addis

2
ใช่เทคนิคความสูงของบรรทัดทำงานได้ดี แต่ถ้าคุณมีเนื้อหาบรรทัดเดียว บรรทัดเพิ่มเติมจะหายไป / จะรั่วไหลออกไปนอกภาชนะและคุณจะต้องเริ่มต้นใหม่อีกครั้ง!
Andy Lorenz

ก) line-heightจะเปลี่ยนความสูงขององค์ประกอบภายในด้วย b) องค์ประกอบด้านในยังไม่ถูกต้องอยู่กึ่งกลางแนวตั้ง c) มันไม่ทำงานกับองค์ประกอบที่ไม่มีข้อความตัวอย่างเช่น: <img>หรือองค์ประกอบที่มีความสูงคงที่
Alph.Dev

นอกจากนี้ยังสามารถล้มเหลวข้ามระบบปฏิบัติการ (Windows / Mac) เนื่องจากความแตกต่างของการแสดงผลแบบอักษร
LocalPCGuy

1
นี่เป็นสิ่งที่คาดเดาไม่ได้และมักส่งผลให้มีความสูงเพิ่มขึ้นบนภาชนะ
Undistraction

25

ในกรณีที่คุณไม่สามารถพึ่งพา flexbox ได้ ... วาง.childไว้.parentที่กึ่งกลางของ ใช้งานได้เมื่อไม่ทราบขนาดพิกเซล (กล่าวอีกนัยหนึ่งเสมอ) และไม่มีปัญหากับ IE9 +

.parent { position: relative; }

.child {
    position: absolute;
    top : 50%;
    left: 50%;
    -ms-transform: translate(-50%, -50%);
    transform    : translate(-50%, -50%);    
}
<div class="parent" style="background:lightyellow; padding:6em"> 
  <div class="child" style="background:gold; padding:1em">&mdash;</div> 
</div>


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

21

คุณควรใส่vertical-align: middleองค์ประกอบภายในไม่ใช่องค์ประกอบภายนอก ตั้งค่าline-heightคุณสมบัติในองค์ประกอบด้านนอกเพื่อให้ตรงกับheightขององค์ประกอบด้านนอก จากนั้นตั้งค่าdisplay: inline-blockและline-height: normalบนองค์ประกอบภายใน เมื่อทำสิ่งนี้ข้อความบนองค์ประกอบด้านในจะห่อด้วยความสูงบรรทัดปกติ ใช้งานได้ใน Chrome, Firefox, Safari และ IE 8+

.main {
    height: 72px;
    line-height:72px;
    border: 1px solid black;
}
.inner {
    display: inline-block;
    vertical-align: middle;
    line-height: normal;
}
<div class="main">
    <div class="inner">Vertically centered text</div>
</div>

ซอ


นี่อาจเป็นวิธีที่ง่ายที่สุด ... คำตอบอื่น ๆ ทั้งหมดในหน้านี้เป็น clunky / hacky ที่ไม่จำเป็นหรือไม่ได้รับการสนับสนุนในเบราว์เซอร์รุ่นเก่าหรือพึ่งพาการรู้ถึงความสูงขององค์ประกอบภายใน คุณไม่ต้องการline-height: normal;และdisplay:inline;ทำงานได้จริงด้วย โบนัสของวิธีนี้คือไม่รบกวนtext-align:center;ซึ่งการใช้display: table-cell;สามารถสร้างปัญหาด้วย บ่อยครั้งที่เราต้องการจัดแนวนอนและแนวตั้ง ดูซอแก้ไขนี้: jsfiddle.net/br090prs/36
mike-source

2
@ mike-source เหตุผลในการใช้line-height: normalและdisplay: inline-blockเพื่อให้ข้อความภายในห่ออย่างถูกต้อง หากคุณแน่ใจว่าข้อความใน div ด้านในจะไม่มีการพันดังนั้นคุณสมบัติเหล่านี้ไม่จำเป็น
Tim Perkins

นับตั้งแต่Microsoft สิ้นสุดการสนับสนุน IE เวอร์ชันเก่าฉันใช้ flexbox สำหรับสิ่งนี้ (ตามที่ @ user1782556 แนะนำ) คำตอบเดิมของฉันคือวิธีที่จะไปหากคุณยังต้องรองรับ IE 10 ขึ้นไป
Tim Perkins

เห็นด้วย 100% แต่ฉันยังไม่ยอมไปใช้เฟล็กซ์บ็อกซ์ แต่ส่วนตัวเท่านั้น 76% ของเบราว์เซอร์รองรับอย่างเต็มที่จนถึงเดือนพฤษภาคม 2559 (94% ถ้าคุณมีการสนับสนุนบางส่วน) ดู: caniuse.com/#search=flexible% 20box การเข้าใกล้ตัวเลือกที่เหมาะสมที่สุดนั้นขึ้นอยู่กับฐานผู้ใช้ของคุณ
mike-source

10

ฉันใช้สิ่งนี้เพื่อจัดตำแหน่งทุกอย่างที่กึ่งกลางของ div wrapper ในกรณีที่มันช่วยทุกคน

div.wrapper {
  /* --- This works --- */
  display: flex;
  /* Align Vertically */
  align-items: center;
  /* Align Horizontally */
  justify-content: center;
  /* --- ---------- ----- */
  width: 100%;
  height:100px;
  background-color: blue;
}
div.inner {
  width: 50px;
  height: 50px;
  background-color: orange;
}
<div class="wrapper">
  <div class="inner">
  </div>
</div>


7

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

จัดแนวแนวตั้งตัวอย่าง

ใช้ flexbox คุณสามารถจัดองค์ประกอบด้วยตัวเองภายในองค์ประกอบอื่น ๆ ที่มีการใช้display: flex; align-selfหากคุณต้องการจัดแนวแนวนอนคุณสามารถใช้align-itemsและjustify-contentในคอนเทนเนอร์ได้

หากคุณไม่ต้องการใช้ flexbox คุณสามารถใช้คุณสมบัติตำแหน่งได้ หากคุณสร้างคอนเทนเนอร์ที่สัมพันธ์กันและเนื้อหาสมบูรณ์เนื้อหาจะสามารถย้ายได้อย่างอิสระภายในคอนเทนเนอร์ ดังนั้นหากคุณใช้top: 0;และleft: 0;ในเนื้อหามันจะถูกวางตำแหน่งที่มุมบนซ้ายของภาชนะ

ตำแหน่งแน่นอน

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

จัดวางตรงกลางภาชนะ

ดังนั้นคุณจำเป็นต้องแก้ไขการแปลเนื้อหาครึ่งหนึ่งของขนาดไปทางซ้ายและด้านบน

ศูนย์กลางแน่นอน


5

นี่เป็นบทความที่ดีเกี่ยวกับวิธีการจัดแนว veistic .. ฉันชอบวิธีการลอย

http://www.vanseodesign.com/css/vertical-centering/

HTML:

<div id="main">
    <div id="floater"></div>
    <div id="inner">Content here</div>
</div>

และรูปแบบที่สอดคล้องกัน:

#main {
   height: 250px;
}

#floater {
   float: left;
   height: 50%;
   width: 100%;
   margin-bottom: -50px;
}

#inner {
   clear: both;
   height: 100px;
}

3
ฉันคิดว่าถ้าคุณกำหนดความสูงของบล็อค #inner จะทำให้แนวคิดของการจัดกึ่งกลางแนวตั้งไม่ถูกต้อง OPS ถูกขอให้ทำให้มันเป็นไปโดยอัตโนมัติดังนั้นฉันจึงจินตนาการว่านั่นหมายความว่าความสูงของกล่องด้านในนั้นไม่เป็นที่ทราบกันในเวลาปฏิสนธิ
Alexis Wilke

5

HTML

<div id="myparent">
  <div id="mychild">Test Content here</div>
</div>

CSS

#myparent {
  display: table;
}
#mychild {
  display: table-cell;
  vertical-align: middle;
}

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


4

มันง่ายมาก เพียงเพิ่มdisplay:table-cellในชั้นเรียนหลักของคุณ

.main {
  height: 72px;
  vertical-align: middle;
  display:table-cell;
  border: 1px solid #000000;
}

ลองดูjsfiddleนี้สิ !


4

นี่คือโซลูชันที่ง่ายที่สุดล่าสุด - ไม่จำเป็นต้องเปลี่ยนแปลงอะไรเลยเพียงเพิ่มกฎ CSS สามบรรทัดลงในคอนเทนเนอร์ของ div ที่คุณต้องการอยู่ตรงกลาง ฉันรักFlex Box#LoveFlexBox

.main {
  /* I changed height to 200px to make it easy to see the alignment. */
  height: 200px;
  vertical-align: middle;
  border: 1px solid #000000;
  padding: 2px;
  
  /* Just add the following three rules to the container of which you want to center at. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* This is true vertical center, no math needed. */
}
.inner {
  border: 1px solid #000000;
}
.second {
  border: 1px solid #000000;
}
<div class="main">
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

โบนัส

justify-contentค่าสามารถตั้งค่าให้ไม่กี่ตัวเลือกต่อไปนี้:

  • flex-startซึ่งจะจัดแนว div ลูกให้ตรงกับที่กระแสการไหลเริ่มในคอนเทนเนอร์หลัก ในกรณีนี้มันจะอยู่ด้านบน

  • centerซึ่งจะจัดแนว div ลูกให้อยู่กึ่งกลางของคอนเทนเนอร์หลัก นี่เป็นระเบียบจริงๆเพราะคุณไม่จำเป็นต้องเพิ่ม div เพิ่มเติมเพื่อล้อมรอบเด็กทุกคนเพื่อใส่เสื้อคลุมในคอนเทนเนอร์หลักเพื่อให้เด็กอยู่ตรงกลาง เพราะการที่นี้เป็นจริงศูนย์แนวตั้ง (ในcolumn flex-direction. ในทำนองเดียวกันถ้าคุณเปลี่ยนflow-directionไปrowก็จะกลายเป็นศูนย์กลางในแนวนอน

  • flex-endซึ่งจะจัดแนว div ลูกให้อยู่ในตำแหน่งที่การไหลของเฟล็กสิ้นสุดลงในคอนเทนเนอร์หลัก ในกรณีนี้มันจะย้ายไปด้านล่าง

  • space-betweenซึ่งจะแพร่กระจายเด็กทุกคนจากจุดเริ่มต้นของการไหลไปยังจุดสิ้นสุดของการไหล หากการสาธิตฉันเพิ่ม div ลูกอีกคนเพื่อแสดงว่าพวกมันกระจายออกไป

  • space-aroundคล้ายกับspace-betweenแต่มีครึ่งหนึ่งของพื้นที่ในจุดเริ่มต้นและจุดสิ้นสุดของการไหล


โซลูชั่นที่สมบูรณ์แบบ เบราว์เซอร์ที่เข้ากันไม่ได้สามารถนำเนื้อหาที่ไม่ได้จัดแนวและผู้ใช้จะต้องจัดการกับมันหรืออัพเกรดเบราว์เซอร์ของตน
doublejr

0

เนื่องจากvertical-alignทำงานได้ตามที่คาดไว้ใน a tdคุณสามารถใส่เซลล์เดียวtableในdivเพื่อจัดเรียงเนื้อหา

<div>
    <table style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center">
        Aligned content here...
    </td></tr></table>
</div>

อุ้ยอ้าย แต่ใช้ได้เท่าที่ฉันบอกได้ มันอาจไม่มีข้อเสียของวิธีแก้ปัญหาอื่น


5
ไม่โปรดไม่มีโต๊ะอีกแล้ว CSS สามารถทำได้ด้วยวิธีที่สะอาด ไม่จำเป็นต้องใช้ <table> ในกรณีนี้
เริ่ม

0

เพียงวางเนื้อหาไว้ในตารางที่มีความสูง 100% และตั้งค่าความสูงสำหรับ div หลัก

<div style="height:80px;border: 1px solid #000000;">
<table style="height:100%">
<tr><td style="vertical-align: middle;">
  This paragraph should be centered in the larger box
</td></tr>
</table>
</div>

0

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

<div class="parent">
    <div class="child">Vertically and horizontally centered child div</div>
</div>

CSS:

.parent{
    position: relative;
}
.child{
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}

0

นี่เป็นวิธีการที่ทันสมัยและใช้ประโยชน์จากฟังก์ชั่น CSS Flexbox ตอนนี้คุณสามารถจัดแนวเนื้อหาภายในคอนเทนเนอร์หลักของคุณได้โดยเพิ่มสไตล์เหล่านี้ลงใน.mainคอนเทนเนอร์

.main {
        display: flex;
        flex-direction: column;
        justify-content: center;
}

และคุณจะไปดี!

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