ระยะขอบลบใน CSS ทำงานอย่างไรและเหตุใด (margin-top: -5! = margin-bottom: 5)


108

เคล็ดลับทั่วไปสำหรับองค์ประกอบการวางตำแหน่งแนวตั้งคือการใช้ CSS ต่อไปนี้:

.item {
    position:absolute;
    top:50%;
    margin-top:-8px; /* half of height */
    height: 16px;
}

เมื่อเห็นในมุมมองเมตริกเช่นเดียวกับใน Chrome นี่คือสิ่งที่คุณเห็น:

ใส่คำอธิบายภาพที่นี่

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

ทำไมmargin-top:-8px ไม่เหมือนกับ margin-bottom:8px ?

อัตรากำไรเชิงลบทำงานอย่างไรและอะไรคือสัญชาตญาณเบื้องหลัง พวกเขา 'ชน' (ในกรณีmargin-top < 0) สิ่งของได้อย่างไร?

คำตอบ:


89

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

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

ถ้าฉันจะสร้างภาพกราฟิกฉันอาจจะใช้อะไรแบบนี้ (ไม่ใช่เพื่อปรับขนาด):

ขอบบนติดลบ

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

โบนัส:

ยังคงต้องเชื่อว่าการอ่านรายละเอียดเป็นวิธีที่จะไป (เมื่อเทียบกับบทความเช่นนี้ )? ฉันเห็นว่าคุณกำลังพยายามจัดองค์ประกอบให้อยู่กึ่งกลางในแนวตั้งดังนั้นทำไมคุณต้องตั้งค่าไม่ใช่หรือmargin-top:-8px;margin-top:-50%;

ดีแนวตั้งตรงกลางใน CSS เป็นหนักกว่าที่มันควรจะเป็น เมื่อกำหนดระยะขอบบนหรือล่างเป็น % ค่าจะคำนวณเป็นเปอร์เซ็นต์ที่สัมพันธ์กับความกว้างของบล็อกที่มีอยู่เสมอ นี่เป็นข้อผิดพลาดที่พบบ่อยและไม่ค่อยมีการอธิบายมุมมองภายนอกของ w3 docos


84

ฉันจะพยายามอธิบายด้วยสายตา:

/**
 * explaining margins
 */

body {
  padding: 3em 15%
}

.parent {
  width: 50%;
  width: 400px;
  height: 400px;
  position: relative;
  background: lemonchiffon;
}

.parent:before,
.parent:after {
  position: absolute;
  content: "";
}

.parent:before {
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: dashed 1px #ccc;
}

.parent:after {
  left: 0;
  right: 0;
  top: 50%;
  border-top: dashed 1px #ccc;
}

.child {
  width: 200px;
  height: 200px;
  background: rgba(200, 198, 133, .5);
}

ul {
  padding: 5% 20px;
}

.set1 .child {
  margin: 0;
  position: relative;
}

.set2 .child {
  margin-left: 75px;
  position: relative;
}

.set3 .child {
  margin-left: -75px;
  position: relative;
}


/* position absolute */

.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}

.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}

.set6 .child {
  top: 50%; /* level from which margin-top starts 
	- downwards, in the case of a positive margin
	- upwards, in the case of a negative margin	
	*/
  left: 50%; /* level from which margin-left starts 
	- towards right, in the case of a positive margin
	- towards left, in the case of a negative margin	
	*/
  margin: -75px;
  position: absolute;
}
<!-- content to be placed inside <body>…</body> -->
<h2><code>position: relative;</code></h2>
<h3>Set 1</h3>
<div class="parent set 1">
  <div class="child">
    <pre>
.set1 .child {
  margin: 0;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 2</h3>
<div class="parent set2">
  <div class="child">
    <pre>
.set2 .child {
  margin-left: 75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 3</h3>
<div class="parent set3">
  <div class="child">
    <pre>
.set3 .child {
  margin-left: -75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h2><code>position: absolute;</code></h2>

<h3>Set 4</h3>
<div class="parent set4">
  <div class="child">
    <pre>
.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 5</h3>
<div class="parent set5">
  <div class="child">
    <pre>
.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 6</h3>
<div class="parent set6">
  <div class="child">
    <pre>
.set6 .child {
  top: 50%;
  left: 50%;
  margin: -75px;
  position: absolute;
}
		</pre>
  </div>
</div>


33

ระยะขอบคือระยะห่างนอกองค์ประกอบของคุณเช่นเดียวกับช่องว่างภายในคือระยะห่างภายในองค์ประกอบของคุณ

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


2
+1ฉันชอบคำตอบของคุณ สามารถปรับปรุงได้โดยการฉีดคำonsetและoffset. เป็นเรื่องจริงที่หลายคนมักใช้คำว่าoffset( เชิงลบ ) เมื่อหมายถึงonset( บวก ) ข้อความนี้จะทำลายตัวเองหากคุณอัปเดตคำตอบของคุณ ไชโย!
arttronics

1
เกี่ยวกับอะไรmargin-bottom: -8px;? ทำไมmargin-bottom:-8pxไม่เหมือนกับmargin-top:-8px?
Rick

27

ขอบด้านบนของ -8px หมายความว่าจะสูงกว่า 8px หากมีระยะขอบ 0

ระยะขอบล่างของ 8px หมายความว่าสิ่งที่อยู่ด้านล่างจะมีขนาด 8px ต่อไปหากมันมีระยะขอบ 0


1
ฉันแค่พยายามทำให้สิ่งต่างๆเรียบง่าย แต่ฉันเห็นด้วยนี่อาจเป็นการเขียนคำตอบที่แย่ที่สุดของฉัน!
Rich Bradshaw

2
ฉันคิดว่าคำตอบค่อนข้างดี ไม่มีการใช้คำตอบทางเทคนิคขั้นสูงที่พวกเราครึ่งหนึ่งไม่เข้าใจ
หมายเลข 945

1
เกี่ยวกับอะไรmargin-bottom: -8px;? ทำไมmargin-bottom:-8pxไม่เหมือนกับmargin-top:-8px?
Rick

22

มีจุดที่ดีอยู่แล้ว แต่ในขณะที่มีข้อมูลมากมายเกี่ยวกับการแสดงผลของระยะขอบโดยเบราว์เซอร์ แต่ทำไมยังไม่มีคำตอบ:

"เหตุใด margin-top: -8px จึงไม่เหมือนกับ margin-bottom: 8px"

สิ่งที่เราสามารถถามได้คือ:

เหตุใดองค์ประกอบที่อยู่ข้างหน้าของขอบด้านล่างที่เป็นบวกจึงไม่ "ชนกัน" ในขณะที่องค์ประกอบต่อไปนี้เป็น "ขอบด้านบน" ที่เป็นบวก

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

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

พิจารณา html ต่อไปนี้:

<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>

คล้ายกับตำแหน่งในโค้ดกล่องทั้งสามนี้จะปรากฏ 'จากบนลงล่าง' แบบเรียงซ้อนกันในเบราว์เซอร์ ( ทำให้สิ่งต่างๆเรียบง่ายเราจะไม่พิจารณาorderคุณสมบัติของโมดูล 'flex-box' css3 ที่นี่ ) ดังนั้นเมื่อใดก็ตามที่ใช้สไตล์กับช่อง 3 ตำแหน่งขององค์ประกอบก่อนหน้า (สำหรับกล่อง 1 และ 2) ได้ถูกกำหนดไว้แล้วและไม่ควรเปลี่ยนแปลงอีกต่อไปเพื่อประโยชน์ในการแสดงผลความเร็ว

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

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


คำตอบที่ดีที่สุด ข้อความนี้ยังอธิบายถึง "ทำไม" ในขณะที่คำตอบอื่น ๆ จะอธิบายเฉพาะ "how" เท่านั้น
Amir Hossein Ahmadi

1
คำตอบนี้ช่วยให้ฉันเข้าใจเหตุผลได้ดีขึ้น ขอบคุณ @schellmax
iRamesh

3

เนื่องจากคุณได้ใช้การกำหนดตำแหน่งแบบสัมบูรณ์และระบุเปอร์เซ็นต์บนสุดขอบด้านบนเท่านั้นที่จะส่งผลต่อตำแหน่งของวัตถุ. รายการของคุณ หากคุณวางตำแหน่งโดยใช้ด้านล่าง: 50% คุณต้องมีขอบล่าง -8px เพื่อจัดกึ่งกลางและระยะขอบบนจะไม่มีผล

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

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

ในกรณีของคุณ 50% อันดับแรกจะส่งผลให้ส่วนบนขององค์ประกอบเริ่มต้นตรงกลางหน้า ด้วยการใช้ระยะขอบบนที่เป็นลบเบราว์เซอร์จะใช้จุด 8px ในองค์ประกอบจากด้านบน (เช่นเส้นตรงกลาง) เป็นตำแหน่งที่จะวางตำแหน่งที่ 50%

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


+1. เข้าท่า ... มันจะดีมากที่จะเสริมด้วยตัวชี้นำภาพเพื่อให้การแสดงภาพสมบูรณ์
PhD

3

ฉันสงสัยว่าคำถามนี้ได้รับคำตอบที่ดีหรือไม่: css margins ทำงานอย่างไรและทำไมถึงเป็น margin-top: -5; ไม่เหมือนกับ margin-bottom: 5 ;?

ระยะขอบคือระยะห่างจากสภาพแวดล้อมขององค์ประกอบ margin-top พูดว่า "... ระยะห่างจากสภาพแวดล้อมเมื่อเราวัดจาก 'ด้านข้าง' บนของ 'กล่อง' ขององค์ประกอบและระยะขอบล่างคือระยะทางจากด้านล่าง 'ด้านข้าง' ของ 'กล่อง'" จากนั้น margin-top: 5; เกี่ยวข้องกับเส้นรอบวงด้านบน, -5 ในกรณีนั้น; สิ่งใดก็ตามที่เข้ามาจาก 'ด้านข้าง' ด้านบนสามารถทับซ้อน 'ด้านข้าง' ขององค์ประกอบได้โดย 5 และระยะขอบล่าง: 5; หมายถึงระยะห่างระหว่างองค์ประกอบด้านล่าง 'ด้านข้าง' และโดยรอบคือ 5

โดยทั่วไป แต่ผลกระทบจากองค์ประกอบ float'ed และชอบ: http://www.w3.org/TR/CSS2/box.html#margin-properties

http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/

ฉันยืนหยัดที่จะได้รับการแก้ไข

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