อิลิเมนต์ที่ลอยอยู่ภายใน div, ลอยอยู่นอก div ทำไม?


274

สมมติว่าคุณมีdiv, ให้มันชัดเจนwidthและใส่องค์ประกอบในนั้นในกรณีของฉันimgอีกdivอัน

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

ทำไมนี้ มีบางอย่างที่ฉันขาดไปและฉันจะเอาไอเท็มที่ลอยอยู่ออกเพื่อยืดส่วนheightที่บรรจุได้divอย่างไร

คำตอบ:


398

วิธีที่ง่ายที่สุดคือการวางoverflow:hiddendiv parent และไม่ระบุความสูง:

#parent { overflow: hidden }

อีกวิธีคือการลอย div parent ด้วย:

#parent { float: left; width: 100% }

อีกวิธีหนึ่งใช้องค์ประกอบที่ชัดเจน:

<div class="parent">
   <img class="floated_child" src="..." />
   <span class="clear"></span>
</div>

CSS

span.clear { clear: left; display: block; }

17
มันใช้งานได้ แต่ตอนนี้ฉันสับสนเป็นสองเท่า: มีคำอธิบายสำหรับสิ่งนี้หรือเป็นแบบนี้หรือไม่
DavidR

8
ใช่มีคำอธิบาย แต่ฉันลืมไปแล้วตั้งแต่ :( มันเป็นอย่างไรoverflow:hiddenกองกำลังเบราว์เซอร์ที่ดีที่สุดที่จะสามารถมีองค์ประกอบเด็กของผู้ปกครองนั่นเป็นเหตุผลที่มันแก้ไขได้
Doug Neiner

5
ผมคิดว่าคำอธิบายสำหรับการoverflow: hiddenอยู่ที่นี่: การเชื่อมโยง และขอบคุณมากมันใช้งานได้สำหรับฉัน
Vikas Arora

6
@DavidR คำอธิบายที่ง่ายที่สุดคือ html / css เป็นเทคโนโลยีที่ล้าสมัยและคิดไม่ถึง ในความเป็นจริงการใช้เหตุผลนี้อธิบาย hir / hss จำนวนมากที่คุณไม่ต้องสงสัยเลยว่าคุณเจอตั้งแต่คุณโพสต์นี้
เบี่ยง

1
โปรดทราบว่าoverflow: hiddenจะซ่อนส่วนใดส่วนหนึ่งขององค์ประกอบที่ไหลออกจากคอนเทนเนอร์หลัก สำหรับฉันแล้วสิ่งนี้ทำให้ข้อความบางส่วนไม่สามารถอ่านได้
แมวยอดนิยม

160

เหตุผล

ปัญหาคือองค์ประกอบลอยอยู่นอกกระแส :

องค์ประกอบถูกเรียกว่าไม่ไหลหากลอยอยู่ในตำแหน่งที่แน่นอนหรือเป็นองค์ประกอบราก

ดังนั้นจึงไม่ส่งผลกระทบต่อองค์ประกอบโดยรอบเนื่องจากองค์ประกอบในการไหลจะ

นี่คือคำอธิบายใน9.5 Floats :

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

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

นี้จะถูกระบุยังอยู่ใน10.6 สูงและอัตรากำไรที่คำนวณ สำหรับบล็อก "ปกติ" ,

มีเพียงเด็กที่อยู่ในโฟลว์ปกติเท่านั้นที่จะถูกนำมาพิจารณา (เช่นกล่องลอยและกล่องที่ถูกจัดวางอย่างแน่นอนจะถูกละเว้น […])

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

โซลูชันแฮ็ค: การกวาดล้าง

วิธีการแก้ปัญหาคือการบังคับให้องค์ประกอบในการไหลอยู่ด้านล่างลอยทั้งหมด จากนั้นความสูงของผู้ปกครองจะเพิ่มขึ้นเพื่อห่อองค์ประกอบนั้น (และทำให้ลอยด้วย)

นี้สามารถทำได้โดยใช้คุณสมบัติ :clear

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

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

ดังนั้นวิธีการแก้ปัญหาคือการเพิ่มองค์ประกอบที่ว่างเปล่ากับclear: bothเป็นพี่น้องคนสุดท้ายของลอย

<div style="clear: both"></div>

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

.clearfix::after {
  clear: both;
  display: block;
}

มีหลายสายพันธุ์ของวิธีการนี้เช่นใช้ไวยากรณ์ลำไส้ใหญ่เลิกเดียว:afterเพื่อสนับสนุนเบราว์เซอร์เก่าหรือใช้อื่น ๆระดับบล็อกdisplay: tableแสดงเช่น

การแก้ไข: ราก BFC

มีข้อยกเว้นสำหรับพฤติกรรมที่เป็นปัญหาที่กำหนดไว้ที่จุดเริ่มต้น: หากองค์ประกอบบล็อกสร้างบริบทการจัดรูปแบบบล็อก (เป็นราก BFC) แล้วมันก็จะห่อเนื้อหาลอยของมัน

ตามความสูง 10.6.7 'อัตโนมัติ' สำหรับการจัดรูปแบบบล็อกรากบริบท ,

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

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

นอกจากนี้ตามที่อธิบายไว้9.5 Floatsแล้วราก BFC ก็มีประโยชน์เช่นกันดังต่อไปนี้:

กล่องเส้นขอบของตารางองค์ประกอบระดับแทนที่บล็อกหรือองค์ประกอบในการไหลปกติที่สร้างบริบทการจัดรูปแบบบล็อกใหม่ […] จะต้องไม่ทับซ้อนกล่องระยะขอบของลอยในบริบทการจัดรูปแบบบล็อกเดียวกันเป็นองค์ประกอบตัวเอง .

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

บริบทการจัดรูปแบบบล็อกถูกสร้างขึ้นโดย

  • บล็อกกล่องoverflowอื่นด้วยvisibleเช่นhidden

    .bfc-root {
      overflow: hidden;
      /* display: block; */
    }
  • ภาชนะบรรจุที่ปิดกั้นที่ไม่ได้ป้องกันกล่อง: เมื่อdisplayมีการตั้งค่าinline-block, หรือtable-celltable-caption

    .bfc-root {
      display: inline-block;
    }
  • ลอยองค์ประกอบ: เมื่อfloatมีการตั้งค่าหรือleftright

    .bfc-root {
      float: left;
    }
  • องค์ประกอบในตำแหน่งที่แน่นอนเมื่อpositionมีการตั้งค่าหรือabsolutefixed

    .bfc-root {
      position: absolute;
    }

โปรดทราบว่าสิ่งเหล่านั้นอาจมีผลกระทบด้านหลักประกันที่ไม่พึงประสงค์เช่นการตัดเนื้อหาที่มีมากเกินออกไปการคำนวณความกว้างอัตโนมัติด้วยอัลกอริธึมการหดตัวเพื่อให้พอดีหรือล้าสมัย ดังนั้นปัญหาคือมันเป็นไปไม่ได้ที่จะมีองค์ประกอบระดับบล็อกในการไหลพร้อมกับล้นที่มองเห็นได้ที่สร้าง BFC

แสดง L3แก้ไขปัญหาเหล่านี้:

สร้างflowและชนิดจอแสดงผลด้านในการแสดงที่ดีกว่ารูปแบบการไหลของประเภทการแสดงผลและการสร้างสวิทช์ที่ชัดเจนสำหรับการทำองค์ประกอบBFCราก (สิ่งนี้ควรกำจัดความต้องการแฮ็กที่ชอบและ[…])flow-root ::after { clear: both; }overflow: hidden

น่าเศร้าที่ยังไม่มีการสนับสนุนเบราว์เซอร์ ในที่สุดเราอาจจะสามารถใช้

.bfc-root {
  display: flow-root;
}

1
ดังนั้นกล่องลอยไม่ได้รับการยอมรับจากภาชนะบรรจุหลักของพวกเขาดังนั้นความสูงล่มสลาย แต่เป็นที่ยอมรับจากพี่น้องของพวกเขาดังนั้น clearfix?
symlink

@symlink ใช่แล้วพาเรนต์คอนเทนเนอร์ไม่เติบโตเพื่อล้อมรอบลอยเว้นแต่ว่าเป็นราก BFC พี่น้องที่ไม่ใช่ราก BFC จะไม่ได้รับผลกระทบโดยตรงจากบล็อก อย่างไรก็ตามการกวาดล้างย้ายพวกเขาด้านล่างลอยก่อนหน้าใด ๆ
Oriol

"พี่น้องที่ไม่ใช่ราก BFC จะไม่ได้รับผลกระทบโดยตรงจากบล็อก (แต่ในกล่องบรรทัดของพวกเขา)" - คุณช่วยอธิบายเรื่องนี้หน่อยได้ไหม? คุณหมายความว่าใน jsFiddle นี้: jsfiddle.net/aggL3Lk7/2ภาพอินไลน์ลอยไม่ได้ส่งผลกระทบต่อช่วง (ดังนั้นชายแดนของช่วงขีดเส้นใต้มัน) แต่ภาพที่มีผลต่อข้อความ (ซึ่งเป็นกล่องสาย) ตามที่ปรากฏ จากข้อเท็จจริงที่ว่าข้อความไม่ได้ขีดเส้นใต้ภาพ?
symlink

1
@symlink ใช่แน่นอน ในซอของคุณชายแดนเป็นของพ่อแม่ แต่โดยพื้นฐานแล้วมันจะเหมือนกันสำหรับพี่น้อง: jsfiddle.net/aggL3Lk7/3
Oriol

1
ฉันเห็นด้วย นี่ควรเป็นคำตอบที่ยอมรับได้ เป็นที่น่าสนใจสำหรับฉันว่า W3 กำลังเรียกวิธีที่เราถูกบังคับให้รหัส "แฮ็ค" บางคนเมาไม่ดี
DR01D



11

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

และนั่นคือเหตุผลที่คุณได้รับผลลัพธ์ที่เป็น


3
สิ่งนั้นเกี่ยวข้องกับองค์ประกอบลอยที่ยืดความสูงของพ่อแม่อย่างไร
เบี่ยง

11

ในบางกรณีเช่นเมื่อ (ถ้า)คุณเพิ่งใช้floatเพื่อให้องค์ประกอบไหลใน "บรรทัด" เดียวกันคุณอาจใช้

display: inline-block;

แทน

float: left;

มิฉะนั้นการใช้clearองค์ประกอบในตอนท้ายจะใช้งานได้แม้ว่ามันจะขัดกับเกรนเพื่อให้ต้องการองค์ประกอบที่จะทำงาน CSS


11

นี่คือวิธีการที่ทันสมัยกว่า:

.parent {display: flow-root;} 

ไม่มีการแก้ไขเพิ่มเติม

ps ใช้ล้น: ซ่อนอยู่; ซ่อนกล่องเงาไว้ ...


ทำงานได้ใน Safari 11 เช่นกัน
pendingfox

7

ขอบคุณLSerniคุณแก้ไขให้ฉัน

เพื่อให้บรรลุนี้:

+-----------------------------------------+
| +-------+                     +-------+ |
| | Text1 |                     | Text1 | |
| +-------+                     +-------+ |
|+----------------------------------------+

คุณต้องทำสิ่งนี้:

<div style="overflow:auto">
    <div style="display:inline-block;float:left"> Text1 </div>
    <div style="display:inline-block;float:right"> Text2 </div>
</div>

4

ดังที่ลูคัสกล่าวสิ่งที่คุณอธิบายคือพฤติกรรมที่ตั้งใจไว้สำหรับคุณสมบัติโฟลต สิ่งที่ทำให้หลายคนสับสนคือการลอยได้ถูกผลักไปไกลกว่าการใช้งานดั้งเดิมเพื่อชดเชยข้อบกพร่องใน CSS layout model

ดูFloatutorialหากคุณต้องการทำความเข้าใจเกี่ยวกับการทำงานของคุณสมบัตินี้


0

คุณสามารถทำได้อย่างง่ายดายด้วยก่อนอื่นคุณสามารถทำ div flex และปรับใช้เนื้อหาทางขวาหรือซ้ายและแก้ไขปัญหาของคุณ

<div style="display: flex;padding-bottom: 8px;justify-content: flex-end;">
					<button style="font-weight: bold;outline: none;background-color: #2764ff;border-radius: 3px;margin-left: 12px;border: none;padding: 3px 6px;color: white;text-align: center;font-family: 'Open Sans', sans-serif;text-decoration: none;margin-right: 14px;">Sense</button>
				</div>

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