การใช้ระยะขอบ: อัตโนมัติเพื่อจัดแนว div ในแนวตั้ง


114

ดังนั้นผมจึงรู้ว่าเราสามารถตั้งศูนย์กลาง div margin:0 auto;แนวนอนถ้าเราใช้ ควรmargin:auto auto;ทำงานวิธีที่ผมคิดว่ามันควรจะทำงาน? จัดกึ่งกลางในแนวตั้งด้วยหรือไม่?

ทำไมไม่vertical-align:middle;ทำงานทั้งสองอย่าง?

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

JSFiddle


1
ขอแนะนำให้อ่านและใช้คำตอบของ @ zpr ด้านล่างเกี่ยวกับ Flexbox ได้รับการสนับสนุนค่อนข้างดี ณ วันนี้และ css ของคุณจะสะอาดกว่ามาก
Govind Rai

ถ้า ((วันที่ใหม่ ()) getFullYear ()> 2017) useFlexBox = true;
Brandito

คำตอบ:


175

อัปเดต ส.ค. 2020

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


คุณไม่สามารถใช้:

vertical-align:middleเพราะมันไม่ใช้บังคับกับองค์ประกอบระดับบล็อก

margin-top:autoและmargin-bottom:autoเนื่องจากค่าที่ใช้จะคำนวณเป็นศูนย์

margin-top:-50%เนื่องจากค่ามาร์จิ้นตามเปอร์เซ็นต์ถูกคำนวณเทียบกับความกว้างของบล็อกที่มี

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

คุณสามารถใช้ได้:

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

.container {
    display: table;
    height: 100%;
    position: absolute;
    overflow: hidden;
    width: 100%;
}
.helper {
    #position: absolute;
    #top: 50%;
    display: table-cell;
    vertical-align: middle;
}
.content {
    #position: relative;
    #top: -50%;
    margin: 0 auto;
    width: 200px;
    border: 1px solid orange;
}
<div class="container">
    <div class="helper">
        <div class="content">
            <p>stuff</p>
        </div>
    </div>
</div

JSFiddleทำงานได้ดีตาม Browsershot


10
#เป็นการแฮ็กเพื่อให้กฎนำหน้าซึ่งตีความโดย IE7 และต่ำกว่าเท่านั้น คุณอาจต้องการรวมกฎเหล่านี้ไว้ในสไตล์ชีตเฉพาะของ IE แทนโดยใช้ความคิดเห็นตามเงื่อนไขเป็นต้น
OV

2
+1 สำหรับการอ้างถึงสาเหตุที่เป็นเช่นนี้การคำนวณเปอร์เซ็นต์ระยะขอบตามความกว้างนั้นเปิดหูเปิดตามาก
ricosrealm

2
ฉันสงสัยเกี่ยวกับคำสั่ง 'infinite loop'
Barun

105
มนุษยชาติเคยไปดวงจันทร์มาแล้วเมื่อหลายปีก่อนและเรายังต้องจัดการกับซากวัวนี้ จัดเรียงสิ่งต่างๆในแนวตั้งในเบราว์เซอร์พระเยซู
user151496

3
ใน> = IE9 อายุposition: absolute; top: 50%; transform: translateY(-50%);ยังเป็นไปได้และเป็นที่นิยมมาก ... (ไม่เหมือนที่top:50%;margin: - $halfHeightคุณไม่ต้องรู้ส่วนสูงล่วงหน้า ... )
Frank Nocke

112

เนื่องจากคำถามนี้ถูกถามในปี 2012 และเราได้รับการสนับสนุนเบราว์เซอร์สำหรับ flexboxes มายาวนานฉันรู้สึกราวกับว่าคำตอบนี้จำเป็น

หากจอแสดงผลของภาชนะผู้ปกครองของคุณเป็นflexแล้วใช่ , margin: auto auto(ยังเป็นที่รู้จักmargin: auto) จะทำงานไปยังศูนย์มันทั้งแนวนอนและแนวตั้งโดยไม่คำนึงว่าจะเป็นinlineหรือblockองค์ประกอบ

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
}
#child {
    margin: auto auto;
}
<div id="parent">
    <div id="child">hello world</div>
</div>

โปรดทราบว่าไม่จำเป็นต้องระบุความกว้าง / ความสูงอย่างแน่นอนเช่นนี้ ตัวอย่าง jfiddleซึ่งใช้การปรับขนาดที่สัมพันธ์กับวิวพอร์ต

แม้ว่าการรองรับเบราว์เซอร์สำหรับ flexbox จะอยู่ในระดับสูงสุดตลอดเวลาในการโพสต์ แต่เบราว์เซอร์จำนวนมากยังไม่รองรับหรือต้องใช้คำนำหน้าผู้จำหน่าย อ้างอิงhttp://caniuse.com/flexboxสำหรับข้อมูลการสนับสนุนเบราว์เซอร์ที่อัปเดต

อัปเดต

เนื่องจากคำตอบนี้ได้รับความสนใจเล็กน้อยฉันจึงอยากจะชี้ให้เห็นว่าคุณไม่จำเป็นต้องระบุmarginเลยว่าคุณกำลังใช้งานอยู่หรือไม่display: flexและต้องการให้องค์ประกอบทั้งหมดอยู่ตรงกลางในคอนเทนเนอร์:

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
    align-items: center; /* horizontal */
    justify-content: center; /* vertical */
}
<div id="parent">
    <div>hello world</div>
</div>


4
ผู้ปกครอง {display: flex; } child {margin: auto 0; } นั้นยอดเยี่ยมมาก
Arek Kostrzeba

OMG เพื่อนคุณเป็นคนร็อคสตาร์ฉันไม่สามารถโหวตให้คุณได้มากกว่าหนึ่งครั้ง !!!
PirateApp

เป็นคำตอบที่ดีเมื่อคุณอาจสับสนกับปัญหาความพอดีของเนื้อหา โดยการตั้งค่า flex บนคอนเทนเนอร์ div เนื้อหาไม่จำเป็นต้องตั้งค่าคุณสมบัติใด ๆ
Eric

1
นี่เป็นทางออกที่ดีที่สุดและสวยงามสำหรับการทำงานในปี 2018 ขอบคุณ
SilverSurfer

ฉันต้องการเพิ่มว่า ณ เดือนพฤษภาคม 2018 ด้วยวิธีแก้ปัญหานี้ข้อความไม่ได้จัดแนวตั้งตรงกลางใน IE 11
Yefu

62

นี่คือทางออกที่ดีที่สุดที่ฉันพบ: http://jsfiddle.net/yWnZ2/446/ ใช้งานได้ใน Chrome, Firefox, Safari, IE8-11 และ Edge

ถ้าคุณได้ประกาศheight( height: 1em, height: 50%ฯลฯ ) หรือเป็นองค์ประกอบที่เบราว์เซอร์รู้ความสูง ( img, svgหรือcanvasตัวอย่าง) แล้วสิ่งที่คุณต้องการสำหรับแนวตั้งตรงกลางคือ:

.message {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    margin: auto;
}

โดยปกติคุณจะต้องระบุwidthหรือmax-widthดังนั้นเนื้อหาจะไม่ยืดความยาวทั้งหมดของหน้าจอ / คอนเทนเนอร์

หากคุณกำลังใช้นี้กิริยาที่คุณต้องการเป็นศูนย์กลางเสมอใน viewport ที่ทับซ้อนกันเนื้อหาอื่น ๆ ที่ใช้สำหรับองค์ประกอบทั้งสองแทนposition: fixed; http://jsfiddle.net/yWnZ2/445/position: absolute

นี่คือบทความที่สมบูรณ์ยิ่งขึ้น: http://codepen.io/shshaw/pen/gEiDt


3
สิ่งนี้ไม่ได้จัดกึ่งกลางไว้ในองค์ประกอบหลักอย่างจำเป็น แฮ็คได้ดีถ้าคุณต้องการให้อยู่ตรงกลางหน้า
Joel Mellon

2
เพียงแค่เพิ่มposition: relativeไปยังพาเรนต์และองค์ประกอบจะอยู่กึ่งกลางภายในพาเรนต์ ฉันเขียนบทความที่ใหญ่กว่านี้ในนิตยสาร Smashing เกี่ยวกับเทคนิคนี้หากคุณต้องการอ่านเพิ่มเติม: coding.smashingmagazine.com/2013/08/09/…
shshaw

บางครั้งค่าสัมบูรณ์ขึ้นอยู่กับผู้ปกครองหรือสองคนขึ้นไป (เทียบกับร่างกาย) และญาติอาจเป็นปู่ย่าตายายหรือปู่ย่าตายาย (เทียบกับผู้ปกครอง) บางทีผู้ที่รู้ว่าเมื่อใดหรือเหตุใดจึงสามารถควบคุมเทคนิคนี้ได้ดีขึ้น - ฉันไม่เคยพิจารณาปัญหาเหล่านั้นจริงๆ แต่ฉันรู้ว่าการเปลี่ยนจากสัมบูรณ์ไปเป็นญาตินั้นไม่ได้เป็นวิธีแก้ปัญหาในการทำงานนี้ ฉันอ่านบทความของคุณเล็กน้อยและดูเหมือนว่าสัมบูรณ์และสัมพัทธ์ขึ้นอยู่กับบรรพบุรุษที่สมบูรณ์หรือญาติครั้งแรกถูกต้องหรือไม่?
Joel Mellon

ฉันเพียงเล็กน้อยช้า. ฉันเพิ่งอ่านความคิดเห็นของคุณด้านบนอีกครั้ง ฉันไม่ได้สังเกตว่าคุณบอกว่าจะเพิ่มลงในparent- เข้าใจแล้ว ขอบคุณมาก!
Joel Mellon

1
@commonpike ปัญหาเดียวกับ IE8 / 9 คือถ้าคุณใช้display: tableสำหรับเนื้อหาความสูงตัวแปร มิฉะนั้นวิธีนี้ควรได้ผลตามที่คาดไว้ อ่านข้อเขียนเพื่อดูรายละเอียดเพิ่มเติมโดยรวม คุณควรจะทดสอบมุมมองแบบเต็มใน IE8 / 9 เพื่อดูว่ามีปัญหาหรือไม่
shshaw

22

แก้ไข: เป็นปี 2020 ฉันจะใช้กล่องดิ้นแทน

คำตอบเดิม:

Html

<body>
  <div class="centered">
  </div>
</body>

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

ใช้ไม่ได้กับ IE 8 และรุ่นเก่ากว่า เนื่องจากรองรับการแปลงค่าที่เหมาะสม (พร้อมคำนำหน้า -ms-) ตั้งแต่เวอร์ชัน 9.0 ขึ้นไป (เช่น 10 ไม่จำเป็นต้องมีคำนำหน้าอีกต่อไป)
DevWL

5
จริงฉันไม่สนใจ IE8
Gal Margalit

และผู้เขียนแท็ก html5 สำหรับคำถามของเขา☺
Gal Margalit

9

ฉันรู้ว่าคำถามนี้มาจากปี 2012 แต่ฉันพบวิธีที่ง่ายที่สุดเท่าที่เคยมีมาและฉันต้องการแบ่งปัน

HTML:

<div id="parent">
     <div id="child">Content here</div>
</div>

และ CSS:

#parent{
     height: 100%;
     display: table;
}    
#child {
     display: table-cell;
     vertical-align: middle; 
}

7

ถ้าคุณรู้ว่าความสูงของ div ที่คุณต้องการไปยังศูนย์คุณสามารถวางตำแหน่งอย่างแน่นอนภายในแม่และตั้งค่าแล้วมูลค่าให้กับtop 50%นั่นจะทำให้ส่วนบนสุดของ div ลูกน้อยลง 50% ของพาเรนต์นั่นคือต่ำเกินไป ดึงกลับขึ้นโดยการตั้งค่าmargin-topให้สูงครึ่งหนึ่ง ตอนนี้คุณมีจุดกึ่งกลางแนวตั้งของ div ลูกนั่งอยู่ที่จุดกึ่งกลางแนวตั้งของแม่ - กึ่งกลางแนวตั้ง!

ตัวอย่าง:

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
    position: absolute;
    top: 50%;
    margin-top: -25px;
    height: 50px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

http://jsfiddle.net/yWnZ2/2/


1
margin-topไม่สามารถตั้งค่าใน% เมื่อเทียบกับความสูงขององค์ประกอบดังนั้นคุณจะจบลงด้วยขนาดขึ้นอยู่กับการแก้ไข
OV

1
นั่นคือ ... สิ่งที่ฉันพูดในคำตอบของฉัน? "ถ้าคุณทราบความสูงของ div ที่คุณต้องการจัดกึ่งกลาง" และฉันไม่ได้บอกว่า OP ควรใช้% ในmargin-top.
tuff

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

3
โอเคฉันได้ทำความเข้าใจกับส่วนที่คุณมองข้ามไปแล้วหวังว่าจะชัดเจนกว่านี้
tuff

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

3

โซลูชันทั้งสองนี้ต้องการเพียงสององค์ประกอบที่ซ้อนกัน
อันดับแรก - การวางตำแหน่งสัมพัทธ์และสัมบูรณ์หากเนื้อหาคงที่ (ศูนย์ด้วยตนเอง)

.black {
    position:relative;
    min-height:500px;
    background:rgba(0,0,0,.5);

}
.message {
    position:absolute;
    margin: 0 auto;
    width: 180px;
    top: 45%; bottom:45%;  left: 0%; right: 0%;
}

https://jsfiddle.net/GlupiJas/5mv3j171/

หรือสำหรับการออกแบบที่ลื่นไหล - สำหรับศูนย์เนื้อหาที่แน่นอนให้ใช้ตัวอย่างด้านล่างแทน:

.message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

https://jsfiddle.net/GlupiJas/w3jnjuv0/

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

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

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

/*in a wrapper*/  
display:table;   

และ

/*in the element inside the wrapper*/
display:table-cell;
vertical-align: middle;
text-align: center;

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

.black {
    display:table;
    height:500px;
    width:100%;
    background:rgba(0,0,0,.5);

}
.message {
    display:table-cell;
    vertical-align: middle;
    text-align: center;
}

https://jsfiddle.net/GlupiJas/4daf2v36/

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


2

.black {
    display:flex;
    flex-direction: column;
    height: 200px;
    background:grey
}
.message {
    background:yellow;
    width:200px;
    padding:10px;
    margin: auto auto;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>


คุณช่วยบอกเราหน่อยได้ไหมว่าวิธีแก้ปัญหานี้เกี่ยวกับอะไร? นอกจากนี้ฉันเห็น "ข้อความป๊อปอัป" ของคุณที่ด้านล่างไม่ได้อยู่ตรงกลาง
Alex

ฉันพลาดอะไรบางอย่างไป แต่ตอนนี้มันได้รับการปรับแต่งเพื่อให้ div อยู่ตรงกลางในแนวตั้ง คุณสามารถตรวจสอบได้เลย
Seetpal singh

0

ไม่มีวิธีง่ายๆเพียงวิธีเดียวในการจัดกึ่งกลาง div ในแนวตั้งซึ่งจะช่วยได้ในทุกสถานการณ์

อย่างไรก็ตามมีหลายวิธีในการดำเนินการขึ้นอยู่กับสถานการณ์

นี่คือบางส่วนของพวกเขา:

  • ตั้งค่าช่องว่างด้านบนและด้านล่างขององค์ประกอบหลักเช่นช่องว่างภายใน: 20px 0px 20px 0px
  • ใช้ตารางเซลล์ตารางจะจัดกึ่งกลางเนื้อหาในแนวตั้ง
  • ตั้งค่าตำแหน่งขององค์ประกอบหลักที่สัมพันธ์กันและ div ที่คุณต้องการจัดกึ่งกลางในแนวตั้งเป็นค่าสัมบูรณ์และจัดรูปแบบเป็นด้านบน: 50px; ด้านล่าง: 50px; ตัวอย่างเช่น

คุณอาจใช้ Google สำหรับ "css vertical centering"


0

ความสูงตัวแปรอัตโนมัติขอบบนและล่าง

.black {background:rgba(0,0,0,.5);
width: 300px;
height: 100px;
display: -webkit-flex; /* Safari */
display: flex;}
.message{
background:tomato;
margin:auto;
padding:5%;
width:auto;
}
<div class="black">
<div class="message">
    This is a popup message.
</div>

ความสูงตัวแปรอัตโนมัติขอบบนและล่าง



0
.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background:yellow;
    width:200px;
    padding:10px;
}

 - 


----------


<div class="black">
<div class="message">
    This is a popup message.
</div>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.