ทำไมรูปแบบส่วนบนของ CSS นี้ไม่ทำงาน


321

ฉันพยายามเพิ่มค่ามาร์จิ้นใน div ภายใน div อื่น ทุกอย่างทำงานได้ดียกเว้นค่าสูงสุดดูเหมือนว่าจะถูกละเว้น แต่ทำไม

สิ่งที่ฉันคาดหวัง:
สิ่งที่ฉันคาดหวังด้วยระยะขอบ: 50px 50px 50px 50px;

สิ่งที่ฉันได้รับ:
สิ่งที่ฉันได้รับด้วยกำไร: 50px 50px 50px 50px;

รหัส:

#outer {
    	width: 500px; 
    	height: 200px; 
    	background: #FFCCCC;
    	margin: 50px auto 0 auto;
    	display: block;
}
#inner {
    	background: #FFCC33;
    	margin: 50px 50px 50px 50px;
    	padding: 10px;
    	display: block;
}
<div id="outer">
  <div id="inner">
  	Hello world!
  </div>
</div>

W3Schoolsไม่มีคำอธิบายว่าทำไมมาร์จินจึงมีพฤติกรรมเช่นนี้


4
คุณลองลอยอันในไหม?
Rooster

6
ฮัม .. float:left;มันใช้งานได้ ... แต่ทำไมถึงเป็นอย่างนี้ ฉันไม่ต้องการให้มันลอย และทำไมถึงมีกำไรสำหรับซ้าย / ขวา?
jamietelin

44
ยินดีต้อนรับสู่โลกแห่งความสนุกของอัลกอริทึมการล่มสลายของ CSS!
GordonM

10
W3Schools vs. W3CDocs ... ฉันคิดว่าเรามีผู้ชนะ : D
enderskill

15
jsFiddle ของมันเพื่อบันทึกคนต่อไป 25 วินาทีjsfiddle.net/kLeu9
CodyBugstein

คำตอบ:


453

คุณจะเห็นว่าระยะขอบด้านบนสุดของ#innerองค์ประกอบยุบลงไปที่ขอบด้านบนของ#outerองค์ประกอบโดยเหลือเพียง#outerระยะขอบที่ไม่คงที่ (แม้ว่าจะไม่ได้แสดงในรูปภาพของคุณ) ขอบด้านบนของกล่องทั้งสองจะชิดกันเนื่องจากระยะขอบของพวกเขาจะเท่ากัน

นี่คือจุดที่เกี่ยวข้องจากข้อมูลจำเพาะของ W3C:

8.3.1 การยุบขอบ

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

ที่อยู่ติดกันระยะขอบแนวตั้งยุบ[... ]

สองมาร์จิ้นอยู่ติดกันหาก:

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

คุณสามารถทำสิ่งใดสิ่งหนึ่งต่อไปนี้เพื่อป้องกันไม่ให้ระยะขอบยุบได้:

  • ลอยdivองค์ประกอบของคุณอย่างใดอย่างหนึ่ง
  • สร้างdivองค์ประกอบแบบอินไลน์ของคุณอย่างใดอย่างหนึ่ง
  • ชุดoverflowของ#outerเป็นauto (หรือค่าอื่นใดนอกจากvisible)

เหตุผลที่ตัวเลือกข้างต้นป้องกันไม่ให้ระยะขอบยุบเนื่องจาก:

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

ระยะขอบซ้ายและขวาจะทำงานตามที่คุณคาดไว้เพราะ:

ระยะขอบแนวนอนไม่เคยยุบ



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

ลิงก์ใน Floating ดูเหมือนจะใช้งานไม่ได้
EP

@episanty: นั่นคือสิ่งที่เกิดขึ้นเมื่อคุณเชื่อมโยงไปยังความคิดเห็น ยกเลิกการเชื่อมโยง
BoltClock

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

92

ลองใช้display: inline-block;กับ div ด้านใน

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:inline-block;
}

6
คำตอบที่ดี. น่าจะดีกว่าถ้ามีการอธิบายว่าทำไมการเปลี่ยนแปลงนี้แก้ไขปัญหาได้
JohnFx

1
ตกลงนั่นนอกลู่นอกทาง! ทำไมจึงใช้งานได้ อะไรคือเหตุผลที่อธิบายว่าทำไมมันไม่ทำงานอย่างที่คาดไว้ ขอบด้านซ้าย / display:inline-block;ขวางานได้โดยไม่ต้อง ตั้งค่ากลับมาเมื่อใช้display:inline-block;คือคุณสูญเสียความกว้าง 100% ใน div
jamietelin

3
การสลับเป็น inline-block บังคับให้เบราว์เซอร์ประเมินขนาดของ div อีกครั้งหลังจากมีการวางและกฎอื่น ๆ
Rooster

พยายามแก้ปัญหาของฉันทำเอฟเฟกต์บันได
Jonny

1
display:inline-blockทำงานให้ฉัน ขอบคุณมาก.
starkeen

24

สิ่งที่ @BoltClock พูดถึงนั้นค่อนข้างแข็งแกร่ง และที่นี่ฉันแค่ต้องการเพิ่มวิธีแก้ไขปัญหานี้อีกหลายอย่าง ตรวจสอบอัตรากำไรขั้นต้น w3c_collapsingนี้ ชิ้นส่วนสีเขียวเป็นความคิดที่มีศักยภาพที่จะแก้ไขปัญหานี้

โซลูชันที่ 1

ระยะขอบระหว่างกล่องลอยและกล่องอื่น ๆ จะไม่ยุบ (ไม่ใช่แม้แต่ระหว่างลูกลอยและลูกที่ไหล)

นั่นหมายความว่าฉันสามารถเพิ่มลงfloat:leftในอย่างใดอย่างหนึ่ง#outerหรือ#inner สาธิต 1

ยังแจ้งให้ทราบว่าfloatจะทำให้การใช้งานautoในขอบ

โซลูชันที่ 2

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

อื่น ๆ กว่าvisibleใส่ให้ของเข้าoverflow: hidden #outerและวิธีนี้ดูเหมือนเรียบง่ายและเหมาะสม ฉันชอบมัน.

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    overflow: hidden;
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

โซลูชัน 3

ระยะขอบของกล่องที่วางไว้อย่างแน่นอนจะไม่ยุบ (ไม่ใช่แม้แต่กับเด็กที่กำลังไหลเข้า)

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: absolute; 
}
#inner{
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

หรือ

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: relative; 
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
    position: absolute;
}

ทั้งสองวิธีนี้จะทำให้การไหลปกติของ div

โซลูชันที่ 4

ระยะขอบของกล่องแบบอินไลน์บล็อกไม่ยุบ (ไม่ใช่แม้แต่กับลูกที่ไหลเข้า)

เหมือนกับ @enderskill

โซลูชันที่ 5

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

สิ่งนี้ไม่ได้เกี่ยวข้องกับคำถามมากนักเนื่องจากเป็นอัตราการยุบระหว่างพี่น้อง โดยทั่วไปหมายความว่าถ้าบนกล่องมีและพี่น้องกล่องมีmargin-bottom: 30px margin-top: 10pxอัตรากำไรรวมระหว่างพวกเขาเป็นแทน30px40px

โซลูชันที่ 6

ระยะขอบบนสุดขององค์ประกอบบล็อกการไหลยุบลงด้วยระยะขอบสูงสุดของบล็อกระดับเด็กในการไหลหากองค์ประกอบนั้นไม่มีเส้นขอบด้านบนไม่มีการขยายด้านบนสุดและเด็กไม่มีการกวาดล้าง

นี่น่าสนใจมากและฉันสามารถเพิ่มเส้นขอบบนสุดหนึ่งเส้น

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    border-top: 1px solid red;

}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;

}

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


14

ไม่แน่ใจว่าทำไมสิ่งที่คุณใช้ไม่ได้ แต่คุณสามารถเพิ่มได้

overflow: auto;

ไปยัง div ภายนอก


โหลดโซลูชันที่แตกต่างสำหรับปัญหานี้ ขอบคุณ! คำตอบนี้รวมกับคำตอบของ @ BoltClock จะให้ข้อมูลที่ดีว่าทำไมโซลูชั่นนี้จึงใช้งานได้
jamietelin


11

ไม่แน่ใจว่าทำไม แต่เปลี่ยน CSS ภายในเป็น

display:inline-block;

ดูเหมือนว่าจะทำงาน


3

ไม่ตอบ "ทำไม" (ต้องเป็นสิ่งที่มีขอบ / ยุบ) แต่ดูเหมือนว่าวิธีที่ง่ายที่สุด / ตรรกะที่สุดในการทำสิ่งที่คุณพยายามจะเป็นเพียงแค่เพิ่มpadding-topdiv ภายนอก :

http://jsfiddle.net/hpU5d/1/

หมายเหตุเล็กน้อย - ไม่จำเป็นต้องตั้ง div เป็นdisplay:block;เว้นแต่จะมีอย่างอื่นในรหัสของคุณที่บอกว่าไม่ถูกบล็อค



2

ฉันเดาว่าการตั้งค่าคุณสมบัติตำแหน่งของ#inner div เป็นญาติอาจช่วยให้ได้ผลลัพธ์ แต่อย่างไรก็ตามฉันลองใช้รหัสต้นฉบับที่วางในคำถามบน IE9 และ Google Chrome ล่าสุดและพวกเขาก็ให้ผลที่พึงประสงค์โดยไม่ต้องแก้ไขใด ๆ


2

ใช้padding-top:50pxสำหรับ div ภายนอก บางสิ่งเช่นนี้:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

หมายเหตุ: การขยายจะเพิ่มขนาดของ div ของคุณ ในกรณีนี้ถ้าขนาดของ div ของคุณมีความสำคัญฉันหมายความว่ามันต้องมีความสูงเฉพาะ ลดความสูง 50px:

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

1

คุณเคยลอง! สำคัญมาก่อนเลยมันจะบังคับทุกอย่าง:

margin:50px 50px 50px 50px !important;

-1

เพื่อการแก้ไขอย่างรวดเร็วลองห่อองค์ประกอบลูกของคุณเป็นdivองค์ประกอบดังนี้

<div id="outer">
   <div class="divadjust" style="padding-top: 1px">
      <div id="inner">
         Hello world!
      </div>
   </div>
</div>

ระยะขอบของinnerdiv จะไม่ยุบเนื่องจากการขยาย1pxระหว่างouterและinnerdiv ดังนั้นในเชิงตรรกะคุณจะมี1pxพื้นที่พิเศษพร้อมกับระยะขอบของinnerdiv ที่มีอยู่

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