Các phần tử nổi trong div, nổi bên ngoài div. Tại sao?


274

Giả sử bạn có một div, cung cấp cho nó một xác định widthvà đặt các yếu tố trong đó, trong trường hợp của tôi imgvà một yếu tố khác div.

Ý tưởng là nội dung của container divsẽ khiến container divbị kéo dài ra, và làm nền cho nội dung. Nhưng khi tôi làm điều này, vật chứa có thể divco lại để phù hợp với các vật thể không nổi và các vật thể nổi sẽ hoàn toàn thoát ra được, hoặc một nửa, một nửa và không có bất kỳ ảnh hưởng nào đến kích thước của vật lớn div.

Tại sao lại thế này? Có thứ gì đó tôi đang thiếu, và làm thế nào tôi có thể lấy các vật phẩm trôi nổi để kéo dài heightvật chứa div?

Câu trả lời:


397

Cách đơn giản nhất là đặt overflow:hiddendiv cha và không chỉ định chiều cao:

#parent { overflow: hidden }

Một cách khác là cũng nổi div cha mẹ:

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

Một cách khác sử dụng một yếu tố rõ ràng:

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

CSS

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

17
Nó hoạt động, nhưng bây giờ tôi bối rối gấp đôi: có một lời giải thích cho điều này hay đây chỉ là nó như thế nào?
DavidR

7
Vâng, có một lời giải thích nhưng tôi đã quên nó :( Nó chỉ là như vậy. Nó overflow:hiddenbuộc trình duyệt phải tốt nhất có thể để chứa các phần tử con của cha mẹ. Đó là lý do tại sao nó sửa nó.
Doug Neiner

5
Tôi nghĩ rằng giải thích cho overflow: hiddenlà ở đây: liên kết . Và cảm ơn rất nhiều, nó đã làm việc cho tôi
Vikas Arora

6
@DavidR Giải thích đơn giản nhất là html / css là một phần công nghệ ngày càng kém, được suy nghĩ kém và được triển khai kém. Trong thực tế, lý do này thực sự giải thích rất nhiều vấn đề về html / css mà bạn không nghi ngờ gì khi gặp phải bài đăng này.
Nhẹ

1
Hãy nhớ rằng overflow: hiddensẽ chỉ ẩn bất kỳ phần nào của một phần tử chảy ra khỏi vùng chứa cha. Đối với tôi, điều này khiến một số đoạn văn bản nhất định trở nên không thể đọc được.
Top Cat

160

Lý do

Vấn đề là các phần tử nổi nằm ngoài luồng :

Một phần tử được gọi là hết dòng nếu nó được thả nổi, định vị tuyệt đối hoặc là phần tử gốc.

Do đó, chúng không tác động đến các yếu tố xung quanh như một yếu tố trong dòng chảy .

Điều này được giải thích trong 9.5 Floats :

Vì phao không nằm trong luồng, các hộp khối không định vị được tạo trước và sau hộp phao chảy theo chiều dọc như thể phao không tồn tại. Tuy nhiên, các hộp dòng hiện tại và tiếp theo được tạo bên cạnh phao được rút ngắn khi cần thiết để nhường chỗ cho hộp lề của phao.

nhập mô tả hình ảnh ở đây

Điều này cũng được quy định trong 10.6 Tính chiều cao và tỷ suất lợi nhuận . Đối với các khối "bình thường" ,

Chỉ có trẻ em trong dòng chảy bình thường được tính đến (ví dụ: hộp nổi và hộp được định vị tuyệt đối bị bỏ qua [V]]

nhập mô tả hình ảnh ở đây

Giải pháp Hacky: giải phóng mặt bằng

Một cách để giải quyết vấn đề là buộc một số phần tử trong dòng được đặt bên dưới tất cả các số float. Sau đó, chiều cao của cha mẹ sẽ phát triển để bọc phần tử đó (và do đó cũng nổi).

Điều này có thể đạt được sử dụng các cleartài sản :

Thuộc tính này cho biết các cạnh của hộp phần tử có thể không liền kề với hộp nổi trước đó.

nhập mô tả hình ảnh ở đây

Vì vậy, một giải pháp là thêm một phần tử trống với clear: bothtư cách là anh chị em cuối cùng của phao

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

Tuy nhiên, đó không phải là ngữ nghĩa. Vì vậy, tốt hơn nên tạo một phần tử giả ở cuối phần cha mẹ:

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

Có nhiều biến thể của phương pháp này, ví dụ: sử dụng cú pháp dấu hai chấm đơn không dùng nữa :afterđể hỗ trợ các trình duyệt cũ hoặc sử dụng các màn hình cấp khối khác như display: table.

Giải pháp: rễ BFC

Có một ngoại lệ đối với hành vi có vấn đề được xác định ngay từ đầu: nếu một phần tử khối thiết lập Bối cảnh định dạng khối (là gốc BFC), thì nó cũng sẽ bọc nội dung nổi của nó.

Theo 10.6.7 'Độ cao' tự động cho các gốc ngữ cảnh định dạng khối ,

Nếu phần tử có bất kỳ hậu duệ nổi nào có cạnh lề dưới nằm dưới cạnh nội dung dưới cùng của phần tử, thì chiều cao được tăng lên để bao gồm các cạnh đó.

nhập mô tả hình ảnh ở đây

Ngoài ra, như đã giải thích 9,5 Floats , rễ BFC cũng hữu ích vì những điều sau đây:

Hộp viền của bảng, phần tử được thay thế ở cấp độ khối hoặc một phần tử trong luồng bình thường thiết lập bối cảnh định dạng khối mới [Biệt] không được chồng lên hộp lề của bất kỳ số float nào trong cùng bối cảnh định dạng khối như chính phần tử .

nhập mô tả hình ảnh ở đây

Một bối cảnh định dạng khối được thiết lập bởi

  • Chặn các hộp overflowkhác visible, vdhidden

    .bfc-root {
      overflow: hidden;
      /* display: block; */
    }
  • Chặn các thùng chứa không phải là hộp chặn: khi displayđược đặt thành inline-block, table-cellhoặc table-caption.

    .bfc-root {
      display: inline-block;
    }
  • Các phần tử nổi: khi floatđược đặt thành lefthoặc right.

    .bfc-root {
      float: left;
    }
  • Các yếu tố hoàn toàn định vị: khi positionđược đặt thành absolutehoặc fixed.

    .bfc-root {
      position: absolute;
    }

Lưu ý rằng những hiệu ứng này có thể có các hiệu ứng tài sản thế chấp không mong muốn, như cắt nội dung tràn, tính toán độ rộng tự động với thuật toán thu nhỏ để phù hợp hoặc trở nên lỗi thời. Vì vậy, vấn đề là không thể có phần tử cấp khối trong luồng với tràn tràn có thể nhìn thấy để thiết lập BFC.

Hiển thị L3 giải quyết các vấn đề này:

Tạo các kiểu hiển thị bên trongflowbên trong để thể hiện tốt hơn các kiểu hiển thị bố cục luồng và để tạo một công tắc rõ ràng để tạo một phần tử là gốc BFC . (Điều này sẽ loại bỏ sự cần thiết của các bản hack như và [Bắn])flow-root ::after { clear: both; }overflow: hidden

Đáng buồn thay, không có hỗ trợ trình duyệt nào. Cuối cùng, chúng tôi có thể sử dụng

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

1
Vì vậy, các hộp nổi không được nhận biết bởi các thùng chứa cha mẹ của chúng, do đó sự sụp đổ chiều cao, nhưng được anh chị em của chúng nhận ra, do đó có phải là xóa?
symlink

@symlink Có, các thùng chứa cha mẹ không phát triển để đóng phao, trừ khi chúng là gốc BFC. Anh chị em không phải là rễ BFC không bị ảnh hưởng trực tiếp bởi các khối (nhưng hộp dòng của họ là). Tuy nhiên, giải phóng mặt bằng di chuyển chúng dưới bất kỳ float trước.
Oriol

"Anh chị em không phải gốc BFC không bị ảnh hưởng trực tiếp bởi các khối (nhưng hộp dòng của họ là)." - Bạn có thể làm rõ điều này xin vui lòng? Bạn có nghĩa là trong jsFiddle này: jsfiddle.net/aggL3Lk7/2 , hình ảnh nội tuyến nổi không ảnh hưởng đến khoảng (do đó đường viền của khoảng đó nằm dưới nó) nhưng hình ảnh đang ảnh hưởng đến văn bản (là hộp dòng) như được hiển thị bởi thực tế là văn bản không gạch chân hình ảnh?
symlink

1
@symlink Vâng, chính xác. Chà, trong fiddle của bạn, đường viền thuộc về cha mẹ, nhưng về cơ bản nó sẽ giống với anh chị em: jsfiddle.net/aggL3Lk7/3
Oriol

1
Tôi đồng tình. Đây phải là câu trả lời được chấp nhận. Điều thú vị đối với tôi là W3 đang gọi theo cách chúng ta buộc phải mã hóa "hack". Ai đó xấu lên.
DR01D



11

Không thiếu thứ gì. Float được thiết kế cho trường hợp bạn muốn một hình ảnh (ví dụ) ngồi bên cạnh một vài đoạn văn bản, vì vậy văn bản chảy xung quanh hình ảnh. Điều đó sẽ không xảy ra nếu văn bản "kéo dài" container. Đoạn đầu tiên của bạn sẽ kết thúc, và sau đó đoạn tiếp theo của bạn sẽ bắt đầu dưới hình ảnh (có thể vài trăm pixel bên dưới).

Và đó là lý do tại sao bạn nhận được kết quả.


3
Làm thế nào mà có liên quan đến yếu tố nổi kéo dài đúng chiều cao của cha mẹ?
Nhẹ

11

Trong một số trường hợp, tức là khi (nếu) bạn chỉ sử dụng floatđể có các phần tử chảy trên cùng một "dòng", bạn có thể sử dụng

display: inline-block;

thay vì

float: left;

Mặt khác, sử dụng một clearphần tử ở cuối hoạt động, ngay cả khi nó có thể đi ngược lại hạt cần một phần tử để làm những gì nên làm CSS.


11

Đây là cách tiếp cận hiện đại hơn:

.parent {display: flow-root;} 

Không còn rõ ràng hơn.

ps Sử dụng tràn: ẩn; che giấu cái bóng hộp để ...


Hoạt động trong Safari 11 cũng vậy
chờ đợi

7

Cảm ơn LSerni bạn đã giải quyết nó cho tôi.

Để đạt được điều này :

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

Bạn phải làm điều này:

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

4

Như Lucas nói, những gì bạn đang mô tả là hành vi dự định cho thuộc tính float. Điều khiến nhiều người nhầm lẫn là float đã được đẩy mạnh vượt ra ngoài mục đích sử dụng ban đầu của nó để bù đắp những thiếu sót trong mô hình bố cục CSS.

Hãy xem Floatutorial nếu bạn muốn hiểu rõ hơn về cách thức hoạt động của khách sạn này.


0

Trước tiên, bạn có thể dễ dàng thực hiện div flex và áp dụng nội dung biện minh đúng hoặc trái và vấn đề của bạn đã được giải quyết.

<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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.