Làm thế nào để Ngữ cảnh Định dạng Khối CSS hoạt động?


80

Làm thế nào để Ngữ cảnh Định dạng Khối CSS hoạt động?

Thông số kỹ thuật CSS2.1 cho biết rằng trong ngữ cảnh định dạng khối, các hộp được bố trí theo chiều dọc, bắt đầu từ trên cùng. Điều này xảy ra ngay cả khi có các phần tử nổi cản đường, ngoại trừ trường hợp hộp khối thiết lập ngữ cảnh định dạng khối mới. Như chúng ta đã biết, khi các trình duyệt hiển thị các hộp khối trong ngữ cảnh định dạng khối, phần tử float bị bỏ qua, tại sao việc thiết lập ngữ cảnh định dạng khối mới lại hoạt động?

Các hộp (hộp khối và hộp nội tuyến) được bố trí như thế nào trong quy trình bình thường?

Tôi đã đọc ở đâu đó rằng các phần tử khối tạo ra các hộp khối, nhưng các phần tử nổi bị bỏ qua khi tác nhân người dùng vẽ hộp và tính đến chúng khi họ điền nội dung. Trong khi các phần tử nổi sẽ chồng lên ranh giới của các phần tử khác trong hộp, giải pháp là thiết lập một ngữ cảnh định dạng khối mới cho các phần tử bị chồng chéo bằng cách sử dụng overflow:hidden.

"Ngữ cảnh định dạng khối mới vẫn là định dạng khối", vì vậy khi vẽ một hộp, nó cũng sẽ coi phần tử nổi như thể nó không thoát ra. Đúng vậy hay tôi đã hiểu nhầm "ngữ cảnh định dạng khối mới?"

Cập nhật: câu hỏi khác

Bằng cách nói "Đây là hành vi hữu ích cho các bố cục kiểu cột. Tuy nhiên, việc sử dụng chính của nó là để dừng các float, chẳng hạn như trong div" nội dung chính ", thực sự là xóa các cột phụ nổi, tức là các float xuất hiện trước đó trong mã nguồn."

Tôi không hiểu nghĩa, tôi sẽ cung cấp một ví dụ, có thể bạn sẽ hiểu tôi.

Tôi nghĩ rằng hộp nổi sẽ nổi lên trên cùng của khối containg-div với lớp content. Bên cạnh đó, nếu hộp nổi xuất hiện sớm hơn trong phần đánh dấu, thì nó sẽ hiển thị những gì tôi nghĩ nên như vậy.

Làm thế nào chúng ta có thể giải thích điều này? Chúng ta có thể sử dụng "ngữ cảnh định dạng khối và ngữ cảnh định dạng nội tuyến" để giải thích không?


Bạn có thể thêm một hình ảnh để ghi lại những gì bạn không hiểu?
mrk

Tôi biết rằng bạn không hỏi rõ ràng về float, nhưng tôi nghĩ rằng bài viết này thực sự tốt trong việc giải thích cách thức hoạt động của một trang web và nó có thể giúp bạn hiểu điều này.
Niklas Wulff

Câu trả lời:


126

Khối định dạng bối cảnh

Phần nổi, phần tử được định vị tuyệt đối, vùng chứa khối (chẳng hạn như khối nội tuyến, ô bảng và chú thích bảng) không phải là hộp khối và hộp khối có 'tràn' không phải 'hiển thị' (ngoại trừ khi giá trị đó đã được truyền đến khung nhìn) thiết lập bối cảnh định dạng khối mới cho nội dung của chúng.

Với sự táo bạo của tôi, đó là bit thiết lập quan trọng

Điều này có nghĩa là phần tử bạn sử dụng overflow(bất kỳ thứ gì khác ngoài hiển thị) floathoặc inline-block.. vv trên sẽ chịu trách nhiệm về bố cục của các phần tử con của nó. Đó là các phần tử con sau đó được "chứa", cho dù đó là lề nổi hay lề thu hẹp, chúng phải được chứa hoàn toàn bởi cha mẹ bao của chúng.

Trong ngữ cảnh định dạng khối, cạnh ngoài bên trái của mỗi hộp chạm vào cạnh trái của khối chứa (đối với định dạng từ phải sang trái, cạnh phải chạm vào)

Dòng trên có nghĩa là gì:

Bởi vì một hộp chỉ có thể là hình chữ nhật và không có hình dạng bất thường, điều này có nghĩa là một ngữ cảnh định dạng khối mới giữa hai phao (hoặc thậm chí bên cạnh một) sẽ không quấn quanh các phao bên lân cận. Các hộp con bên trong chỉ có thể mở rộng đến mức chạm vào cạnh trái (hoặc phải trong RTL) của cha mẹ chúng. Hành vi này rất hữu ích cho các bố cục kiểu cột. Tuy nhiên, công dụng chính của nó là để dừng các float, ví dụ như trong div "nội dung chính", thực sự là xóa các cột phụ nổi, tức là các float xuất hiện trước đó trong mã nguồn.


Giải phóng mặt bằng nổi

Trong trường hợp bình thường, float được cho là xóa tất cả các phần tử float trước đó, phần tử này đã được float trước đó trong toàn bộ mã nguồn, không chỉ "cột" được hiển thị của bạn. Trích dẫn từ "float cleas specs" là:

Thuộc tính này cho biết mặt nào của (các) hộp phần tử có thể không liền kề với hộp nổi trước đó. Thuộc tính 'clear' không coi là float bên trong chính phần tử đó hoặc trong các ngữ cảnh định dạng khối khác

Vì vậy, giả sử bạn có bố cục ba cột trong đó các cột bên trái và bên phải được thả nổi lần lượt sang trái và phải, các cột bên hiện đang ở trong các Khung định dạng khối mới, vì chúng được thả nổi (hãy nhớ float cũng là một trong những thuộc tính thiết lập BFC mới ), vì vậy bạn có thể vui vẻ thả nổi các phần tử danh sách bên trong chúng và chúng chỉ xóa các phần tử float đã nằm bên trong các cột bên mà họ không còn quan tâm đến các phần tử float trước đây trong mã nguồn


Để làm cho nội dung chính trở thành một Ngữ cảnh Định dạng Khối mới hay không?

Bây giờ cột giữa đó, bạn có thể chỉ cần căn lề nó từ cả hai bên để nó có vẻ nằm gọn gàng giữa hai cột nổi hai bên và lấy chiều rộng còn lại, một cách phổ biến để có được chiều rộng mong muốn nếu cột ở giữa là "linh hoạt" - điều này sẽ vẫn ổn cho đến khi bạn cần sử dụng float / clear bên trong div nội dung của mình (một trường hợp phổ biến đối với những người sử dụng hack hoặc mẫu "clearfix" bao gồm cả chúng)

Lấy mã rất đơn giản này:

Nó tạo ra những thứ sau:

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

Nói chung, điều này là ổn, đặc biệt nếu bạn không có màu nền hoặc phao bên trong (trong nội dung chính) - hãy chú ý các phao vẫn ổn (chưa được xóa) chúng có thể đang làm những gì bạn ngoại trừ chúng, nhưng chúng, phần H3trên cùng lề và lề pdưới của nội dung không thực sự được chứa bởi div nội dung (nền lightgrey).

Vì vậy, với cùng một kịch bản margined đơn giản của đoạn mã trên, hãy thêm:

.clear-r {clear: right;}

sang CSS và thay đổi hộp nổi HTML thứ hai thành:

<div class="floated clear-r"> this a floated cleared box</div>

Lần này bạn nhận được điều này:

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

Phao thứ hai đang xóa phía bên phải nhưng nó xóa toàn bộ chiều cao của cột bên phải. Cột bên phải được thả nổi trước đó trong mã nguồn nên nó đang xóa nó như đã nói! Tuy nhiên, có lẽ không phải là hiệu ứng mong muốn, cũng lưu ý rằng các lề h3plề vẫn bị thu gọn (không chứa).


Làm cho nó thiết lập một bối cảnh định dạng khối, vì lợi ích của trẻ em!

và cuối cùng làm cho cột nội dung chính chịu trách nhiệm - trở thành Bối cảnh định dạng khối - cho nội dung của nó: loại bỏ margin: 0 200px;CSS và ADD nội dung chính overflow: hidden;và bạn nhận được điều này:

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

Điều này có lẽ giống với những gì bạn mong đợi sẽ xảy ra hơn, lưu ý bây giờ các phao được chứa, chúng rõ ràng đúng cách bỏ qua cột bên phải, và cũng có h3plề được chứa thay vì thu gọn.

Với việc sử dụng rộng rãi các thiết lập lại ngày nay, các lề ít được chú ý hơn (và IE vẫn không làm cho chúng đúng) tuy nhiên những gì vừa xảy ra với trung tâm "nội dung chính" là nó đã trở thành một Ngữ cảnh Định dạng Khối và hiện chịu trách nhiệm các phần tử con (con cháu) riêng. Nó thực sự rất giống với của Microsoft ngày đầu khái niệm về hasLayout, nó sử dụng các tính chất tương tự display: inline-block, floatoverflowbất cứ điều gì khác hơn là nhìn thấy được, và các tế bào bảng dĩ nhiên luôn luôn có bố trí .. nó là tuy nhiên nếu không có sự lỗi;)

Hy vọng rằng sẽ giúp một chút, bất kỳ câu hỏi xin vui lòng hỏi!


Cập nhật: thêm thông tin được đề cập:

Khi bạn nói "nhưng các phần tử nổi bị bỏ qua khi tác nhân người dùng vẽ hộp và tính đến chúng khi họ điền nội dung."

Có phao thường phủ lên các hộp chứa của chúng, đó là ý của bạn về ranh giới chính? Khi một phần tử khối được vẽ và nó chứa một float thì chính khối cha đó sẽ được vẽ như một hình chữ nhật dưới float và nó là "các hộp ẩn danh nội tuyến" hoặc đơn giản là "các hộp dòng" của các phần tử con khác được rút ngắn để nhường chỗ cái phao

Lấy mã này:

Cái nào tạo ra cái này:

phao hoạt động như thế nào

Bạn thấy rằng phần tử mẹ không thực sự chứa float, vì trong nó không bao bọc nó hoàn toàn .. float chỉ đơn giản là nổi trên đầu nội dung - nếu bạn tiếp tục thêm nội dung vào div thì cuối cùng nó sẽ bao bọc bên dưới float vì sẽ không cần các "hộp dòng" (ẩn danh) của pphần tử tự rút ngắn nữa.

Tôi đã tô màu phần tử đoạn văn để bạn có thể thấy rằng nó cũng thực sự nằm dưới phao, nền màu đen là nơi đoạn văn bắt đầu, văn bản màu trắng là nơi bắt đầu "hộp dòng ẩn danh" - chỉ thực sự chúng mới "tạo khoảng trống "cho float, trừ khi bạn nói khác (tức là bạn thay đổi ngữ cảnh)

Một lần nữa đề cập đến hình trên, nếu bạn đặt lề bên trái của pphần tử, thì có, nó sẽ dừng việc gói văn bản dưới đáy của phần nổi vì "hộp dòng" (văn bản màu trắng) sẽ chỉ chạm vào cạnh trái vùng chứa của chúng và bạn sẽ đưa nền màu của phần pbên phải sang bên phải, không có phần nổi, nhưng bạn sẽ không thay đổi hành vi của pngữ cảnh định dạng của. Giống như cột trung tâm trong hình ảnh đầu tiên ở trên;)


clairesuzy, cảm ơn bạn rất nhiều! Nó thực sự giúp tôi rất nhiều, nhưng tôi vẫn còn một số câu hỏi, tôi đã thêm nó vào câu hỏi ban đầu. Tôi hy vọng bạn có thể giúp tôi.
eileen Tao

1
@eileen có hai điều đang xảy ra - Tôi nghĩ câu hỏi bổ sung của bạn được giải thích bằng ví dụ đầu tiên .. các hộp nổi màu tím xuất hiện sau nội dung vì đó là nơi chúng nằm trong nguồn, một dấu nổi không nổi lên trên cùng, chuyển lên trên trước nội dung (vì trong đó lề trên cùng không được cao hơn vị trí cần thiết) - các cột bên trái và bên phải cũng là các hộp nổi trước đó trong nguồn và không có cột ở giữa trở thành BFC mới nếu bạn cố gắng xóa các dấu nổi màu tím của chúng. cũng sẽ xóa các cột nổi phía nguồn trước đó .. điều đó có giúp ích gì không?
clairesuzy

1
@eileen liên kết đó đang mô tả các phần tử mức khối và phần tử mức nội tuyến, chỉ là những điều cơ bản không quá nhiều trong ngữ cảnh định dạng. các phần tử khối sẽ luôn chiếm 100% chiều rộng và nằm chồng lên nhau (theo mặc định) - các phần tử nội tuyến nằm cạnh nhau, như liên kết, nhịp, v.v. thậm chí không có chiều rộng hoặc chiều cao nên chúng không có tùy chọn. Một phần tử nổi tự động trở thành một phần tử cấp khối, vì vậy nếu bạn thả nổi một cấp nội tuyến <span>thì nó sẽ giống như một cấp khối <div>.
clairesuzy

1
tiếp tục .. lý do pnền của nó nằm dưới float là vì các phần tử float bị xóa khỏi luồng, vì trong các phần tử lân cận thực sự không biết chúng ở đó và vì chúng thuộc cùng một ngữ cảnh định dạng pnên nó là vùng chứa mẹ cho các kích thước của nó .. (đó là lý do tại sao bạn không thể đặt một thứ rộng 100% bên cạnh phao - bởi vì nó 100% là 100% vùng chứa. Chỉ những hộp ẩn danh cuối cùng mới tìm ra phao ở đó; )
clairesuzy

1
@clairesuzy - Hình ảnh bạn đăng đã hết, bạn vui lòng đăng lại được không?
bfavaretto
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.