The most comprehensive and thorough analysis of BFC principle in history

ZuoPengFei 2017.09.21

This article explains what the CONCEPT of BFC is; Constraint rules of BFC; How to trigger the generation of new BFC; Application of BFC in layout: prevent margin overlap (collapse, whichever is the largest); Clear internal float; Adaptive two (more) column layouts.

1. What is BFC?

Block fomatting context = block-level box + Formatting Context

Box:

Box is the Box model;

  • Block-level boxes are block-level elements

Display elements with block, list-item, table attributes generate block-level boxes; And participate in the Block fomatting context;

  • Inline-level boxes are inline elements

Display elements with attributes inline, inline-block, inline-table generate inline-level boxes. And participates in inline formatting context;

Formatting context

Formatting context is a concept in the W3C CSS2.1 specification. It is a rendering area of the page and has a set of rendering rules that determine how its children will be positioned and how they will interact with other elements. The most common Formatting contexts are Block fomatting context(BFC) and Inline Formatting context(IFC).

There are only BFC and IFC in CSS2.1, and G (Grid)FC and F(Flex)FC are added in CSS3.

Landing the definition

Block formatting context (BFC). It is a separate rendering area, with only block-level box participation, which dictates how the internal block-level box is laid out and has nothing to do with the outside of the area.

2. The generation of landing

As mentioned above, the BFC is a render area. Where and how big the render area is depends on the element that generates the BFC. CSS2.1 states that an element that satisfies one of the following CSS declarations generates the BFC.

  • The root element
  • The value of float is not None
  • The value of overflow is not visible
  • The display value is inline-block, table-cell, and table-caption

Display: The table also thinks that it can generate BFC. In fact, the main reason is that the table generates an anonymous table-cell by default. It is this anonymous table-cell that generates BFC

  • The value of position is absolute or fixed

3. Constraints of the BFC

  • The internal boxes will be placed one after the other vertically
  • The vertical distance is determined by margin. (The full statement is: The margin of two adjacent boxes belonging to the same BFC will overlap (collapse), regardless of direction.)
  • The left margin of each element touches the left margin of the containing block (from left to right), even for floating elements. (This means that a BFC neutron element does not exceed its contain block, whereas an element with position as absolute can exceed its contain block boundary.)
  • The region of the BFC does not overlap with the element region of float
  • When calculating the height of the BFC, the floating child element also participates in the calculation
  • A BFC is a separate container on a page, in which child elements do not affect outside elements and vice versa

With these constraints in mind, let’s think about some of the rules we learned about CSS

  • Block elements expand to the same width as their parent, so Block elements are arranged vertically
  • Margins of two adjacent divs overlap vertically, but not horizontally (this rule is not entirely true)
  • Float elements as close to the top left (or right) as possible
  • Setting overflow: Hidden or floating parent for the parent element will contain the floating element

4. Application of BFC in layout

4.1 Prevent margin overlap (collapse)

Vertical margin overlap between two adjacent boxes
<style>
    p {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <p>Haha</p>
    <p>Hehe</p>
</body>

Copy the code

  

If the margin of the first P is 80, the distance between the two ps is still 100, whichever is the largest.

According to rule 2 of the BFC layout:

The vertical distance of the Box is determined by margin. Margins of two adjacent boxes belonging to the same BFC(in this case, the BFC of the body root element) will overlapCopy the code

We can wrap a container around p and trigger it to generate a new BFC. Then the two P’s do not belong to the same BFC, and margin overlap will not occur.

Code:

<style> .wrap { overflow: hidden; // new BFC} p {color: #f55; background: #fcc; width: 200px; line-height: 100px; text-align:center; margin: 100px; } </style> <body> <p>Haha</p> <div class="wrap"> <p>Hehe</p> </div> </body>Copy the code

Margin overlap in horizontal direction of adjacent boxes
<! doctype HTML> <html> <head> <style type="text/css"> #green { margin:10px 10px 10px 10px } #blue { margin:10px 10px 10px 10px } #red { margin:10px 10px 10px 10px } body { writing-mode:tb-rl; } </style> </head> <body> <div id="green" style="background:lightgreen; height:100px; width:100px;" ></div> <div id="blue" style="background:lightblue; height:100px; width:100px;" ></div> <div id="red" style="background:pink; height:100px; width:100px;" ></div> </body> </html>Copy the code

You can see that the horizontal margin overlaps.

We can add a display:inline-block to div, touching each div container to generate a BFC. Then the three divs do not belong to the same BFC (the BFC formed by the body root element only), and there will be no margin overlap.

Margin overlap of nested elements
<! DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <! --The viewport meta tag is used to improve the presentation and behavior of the samples on iOS devices--> <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> <title></title> <style> html, body { height: 100%; width: 100%; margin: 0; padding: 0; } #map{ padding:0; } .first{ margin:20px; background:lightgreen; width:100px; height:100px; } ul{ /*display:inline-block; */ margin:10px; background:lightblue; } li{ margin:25px; } </style> </head> <body class="claro"> <div class="first"></div> <ul> <li>1</li> <li>2</li> <li>3</li> </ul> </body> </html>Copy the code

For the vertical distance between div and ul, take the maximum margin between div, ul, and li.

To prevent margin overlap of nested elements, simply have UL generate BFC (leave out the comment in the above example) so that div, ul, and LI do not overlap.

Li is located in the same BFC, so there is still overlap.

Set line-block to li to generate a new BFC and there is no overlap.

Note that:

If a border or padding is set for ul, the element’s margin is contained within the box model of the parent element and does not overlap with the outer div.

The CSS Authority Guide mentions that the height of block-level normal flow elements is set to auto, and that there are only block-level child elements, and that the default height will be the distance between the outer border of the highest block-level child element and the outer border of the lowest block-level child element. If a block-level element has an upper or lower right inner margin, or has an upper or lower border, its height is the distance between the upper margin of its highest child and the lower margin of its lowest child.

4.2 Clearing Internal Floating information

<style>
    .par {
        border: 5px solid #fcc;
        width: 300px;
    }
 
    .child {
        border: 5px solid #f66;
        width:100px;
        height: 100px;
        float: left;
    }
</style>
<body>
    <div class="par">
        <div class="child"></div>
        <div class="child"></div>
    </div>
</body>
Copy the code

Page:

According to article 6 of the BFC layout Rules:

When calculating the height of the BFC, floating elements are also involvedCopy the code

To clear the internal float, we can trigger the PAR to generate a BFC, so that when the PAR calculates the height, the float element child inside the PAR participates in the calculation.

.par {
    overflow: hidden;
}
Copy the code

4.3 Adaptive multi-column layout

4.3.1 Adaptive two-column layout
<style>
    body {
        width: 300px;
        position: relative;
    }
 
    .aside {
        width: 100px;
        height: 150px;
        float: left;
        background: #f66;
    }
 
    .main {
        height: 200px;
        background: #fcc;
    }
</style>
<body>
    <div class="aside"></div>
    <div class="main"></div>
</body>
Copy the code

According to Article 3 of the BFC layout rules:

The left side of the margin box of each element touches the left side of the border box containing the block (for left-to-right formatting, otherwise the opposite). This is true even if there is a float.Copy the code

Thus, although there is a floating element aslide, the left side of main still touches the left side of the containing block.

According to Article 4 of the BFC layout rules:

The region of the BFC does not overlap with the float box.Copy the code

We can implement an adaptive two-column layout by triggering Main to generate a BFC.

.main {
    overflow: hidden;
}

Copy the code

When main generates the BFC, the new BFC does not overlap with the floating aside. So it will automatically narrow depending on the width of the contained block, and the width of the aside. The effect is as follows:

4.3.2 Adaptive two-column layout
<! DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <! --The viewport meta tag is used to improve the presentation and behavior of the samples on iOS devices--> <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> <title></title> <style> html, body { height: 100%; width: 100%; margin: 0; padding: 0; } .left{ background:pink; float: left; width:180px; } .center{ background:lightyellow; overflow:hidden; } .right{ background: lightblue; width:180px; float:right; } </style> </head> <body class="claro"> <div class="container"> <div class="left"> <pre> .left{ background:pink; float: left; width:180px; } </pre> </div> <div class="right"> <pre> .right{ background:lightblue; width:180px; float:right; } </pre> </div> <div class="center"> <pre> .center{ background:lightyellow; overflow:hidden; height:116px; } </pre> </div> </div> </html>Copy the code

This layout features a fixed width for the left and right columns, while the middle column ADAPTS to the browser width.

4. To summarize

In fact, the above examples all reflect the fifth rule of BFC layout:

A BFC is a separate container on a page, and the child elements inside the container do not affect the outside elements. And vice versa.Copy the code

Because elements inside and elements outside the BFC never interact,

When a float exists outside the BFC, it should not affect the layout of the Box inside the BFC, and the BFC will be narrowed without overlapping with the float. Similarly, when there is a float inside the BFC, the BFC calculates the height of the float so as not to affect the layout of the external elements. The same goes for avoiding margin overlap.

5. Extend your reading

  • CSS Clear Float Processing (Clear and BFC)

  • A new micro clearfix hack

  • Clear floating and BFC