BFC in CSS

What is landing

In CSS rendering of a Web page, the Block Fromatting Context is laid out in a block-level box. W3C defines BFC as follows:

Floating elements and absolutely positioned elements, block-level containers that are not block-level boxes (such as inline-blocks, table-cells, and table-captions), and block-level boxes that do not have overflow value “unavailable”, Both create new BFC (block-level format context) for their content.

To make it easier to understand, let’s redefine the BFC in a different way. To create a BFC for an HTML element, one or more of the following conditions must be met:

1. Float is not none.

2. Position is not static or relative.

3, display is inline-block, table-cell, flex, table-caption or inline-flex

Overflow is not visible

A BFC is an independent layout environment in which the layout of elements is independent, and in a BFC, block boxes and row boxes (row boxes are made up of all inline elements in a row) are arranged vertically along the border of their parent element.

How do I create a BFC

Creating a BFC to display is as simple as meeting one of the above four CSS criteria. Such as:

<div class="container"> Your contentCopy the code

Add rules like overflow: Scroll, overflow: hidden, display: flex, float: left, or display: table to the class container to display the creation of the BFC. While adding any of the above can create a BFC, there are some side effects:

1. Display: table may cause responsiveness problems

Overflow: Scroll may produce redundant scroll bars

Float: left moves the element to the left and surrounds it with other elements

4. Overflow: Hidden will crop the overflow element

Therefore, whenever you need to create a BFC, consider it based on your needs. For this article, you will use Overflow: Hidden:

.container {
    overflow: hidden;
}
Copy the code

Besides, two

How are boxes aligned in the BFC

As mentioned earlier, in a BFC, block boxes and row boxes (which consist of all inline elements in a row) are arranged vertically along the border of their parent element. The W3C specification is:

In the BFC, the margin-left edge of each box touches the border-left edge of the container (or, for right-to-left formats, the right edge). The same is true for floats (although the Line Box inside the Box may narrow due to floats), unless the Box creates a new BFC (in which case the Box itself may narrow due to floats).

Margin folding

In a normal flow layout, boxes are arranged vertically, and the spacing between them is determined by their margins, but not the sum of them.

<div class="container">
  <p>Sibling 1</p>
  <p>Sibling 2</p>
</div>
Copy the code

Corresponding CSS:

.container {
  background-color: red;
  overflow: hidden; /* creates a block formatting context */
}
p {
  background-color: lightgreen;
  margin: 10px 0;
}
Copy the code

The rendering result is shown below:

In the figure above, a red box (div) contains two sibling elements (p), and a BFC has been created.

In theory, the Margins between the two P elements should be the sum of the Margins (20px), but they are actually 10px as a result of Collapsing the Margins.

In CSS, the margins of two adjacent boxes (which may be siblings or ancestors) can be combined to form a single margin. This way of combining margins is called folding, and the resulting margins are called folded margins. The result of folding is calculated according to the following rules:

1. When two adjacent margins are both positive, the result of folding is the greater value between them.

2. When two adjacent margins are both negative, the result of folding is the greater value of their absolute values.

3. When two margins are positive and negative, the result of folding is the sum of the two.

A prerequisite for making a fold: margin must be adjacent! (For cases where no folding occurs, see the link to the reference article.)

What can BFC do?

Use BFC to avoid margin folding

BFC can cause margin folding and can be used to avoid it. The BFC produces margin folding under the condition that two adjacent elements are in the same BFC. Therefore, margin folding can be avoided if two adjacent elements are in different BFC.

Improve the previous example:

<div class="container">
    <p>Sibling 1</p>
    <p>Sibling 2</p>
    <p>Sibling 3</p>
</div>
Copy the code

Corresponding CSS:

.container {
  background-color: red;
  overflow: hidden; /* creates a block formatting context */
}
p {
  background-color: lightgreen;
  margin: 10px 0;
}
Copy the code

The result is the same as above, due to margin folding, the vertical distance between the three adjacent P elements is 10px, because all three P tags belong to the same BFC.

Modify the third P element to create a new BFC:

<div class="container">
    <p>Sibling 1</p>
    <p>Sibling 2</p>
    <div class="newBFC">
        <p>Sibling 3</p>
    </div>
</div>
Copy the code

Corresponding CSS:

.container {
    background-color: red;
    overflow: hidden; /* creates a block formatting context */
}
p {
    margin: 10px 0;
    background-color: lightgreen;
}
.newBFC {
    overflow: hidden;  /* creates new block formatting context */
}
Copy the code

The result now looks like this:

Because the second and third P elements now belong to different BFC, there is no margin folding between them.

BFC includes floating

Floating elements leave the document flow (absolute positioning elements leave the document flow). If a child element of a container with no height or whose height is auto is a floating element, the height of the container will not be split. We usually solve this problem with pseudo-elements (:after or :before). The BFC can contain floats and also solve the problem of the container height not being split open.

Here’s an example:

<div class="container"> <div>Sibling</div> <div> CSS:. Container {background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }Copy the code

In the example above, the container does not have any height, and it does not contain floating child elements. The height of the container is not stretched. To solve this problem, create a BFC in the container:

.container {
    overflow: hidden; /* creates block formatting context */
    background-color: green;
}
.container div {
    float: left;
    background-color: lightgreen;
    margin: 10px;
}
Copy the code

Now that the container can wrap around the floating child elements, and its height is extended to encompass the child elements, the floating elements are back to the regular flow of the page in this new BFC.

Use BFC to avoid text wrapping

As shown in the figure above, for floating elements, it is possible to create a text wrap (Figure1), but this is not the layout we want (Figure2 is the desired layout). To solve this problem, we can use margins, but we can also use BFC.

First let us understand why the text wraps. For this we have to understand how the box model works when an element is floated. This is the part I left earlier while discussing the alignment in a block formatting context. Let us understand what is happening in Figure 1 in the diagram below:

Suppose the HTML is:

<div class="container">
    <div class="floated">
        Floated div
    </div>
    <p>
        Quae hic ut ab perferendis sit quod architecto, 
        dolor debitis quam rem provident aspernatur tempora
        expedita.
    </p>
</div>
Copy the code

The whole black area in the figure above represents the P element. The p element is not shifted but it is superimposed on the floating element, whereas the text of the P element (the row box) is shifted, and the row box Narrows horizontally to make room for the floating element. As the text increases, the final text will be wrapped around the floating element, because the row box will no longer need to be shifted and will look like Figure1.

Review the W3C’s description again:

In the CONTEXT of the BFC, the outer left side of each Box is adjacent to the left side of the containing block (or, in the right-to-left format, the outer right side of the Box is adjacent to the right side of the containing block), even if there are floats (although the Line Box inside the Box may be narrowed by floats), Unless the box creates a new BFC (in which case the box itself may be narrowed due to floating).Copy the code

Thus, if the p element creates a new BFC it is no longer attached to the left side of the containing block.

Use BFC in multi-column layouts

If we create a multi-column layout that covers the entire width of the container, in some browsers the last column will sometimes fall to the next row. This may be because the browser has rounded the column width so that the total width of all columns exceeds the container. But if we create a new BFC in the last column of a multi-column layout, it will always occupy the space left over after the other columns have filled up first.

Such as:

<div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column  3</div> </div>Copy the code

Corresponding CSS:

The column {width: 31.33%; background-color: green; float: left; margin: 0 1%; } /* Establishing a new block formatting context in the last column */ .column:last-child { float: none; overflow: hidden; }Copy the code

Now although the width of the box has changed slightly, the layout will not break. Of course, this is not always a good idea for multi-column layouts, but it keeps the last column from dropping. Elastic boxes may be a better solution to this problem, but this approach can be used to illustrate how elements behave in these environments.