HTML & CSS
Article

Understanding Block Formatting Contexts in CSS

By Ritesh Kumar

A Block Formatting Context is part of the visual CSS rendering of a web page in which block boxes are laid out. The positioning scheme to which it belongs is normal flow. According to W3C:

Floats, absolutely positioned elements, inline-blocks, table-cells, table-captions, and elements with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts.

The above quote pretty much sums up how a block formatting context is formed. But lets redefine it in a way that is easier to understand. A block formatting context is an HTML box that satisfies at least one of the following conditions:

  • The value of float is not none
  • The value of position is neither static nor relative
  • The value of display is table-cell, table-caption, inline-block, flex, or inline-flex
  • The value of overflow is not visible.

Creating a Block Formatting Context

A block formatting context can be explicitly triggered. So if we want to create a new block formatting context, we just need to add any one of the above mentioned CSS conditions to it.

For example, look at the following HTML:

<div class="container">
  Some Content here
</div>

A new block formatting context can be created by adding any one of the necessary CSS conditions like overflow: scroll, overflow: hidden, display: flex, float: left, or display: table to the container. Though any of the above mentioned conditions can create a block formatting context, there will also be some other effects like:

  • display: table may create problems in responsiveness
  • overflow: scroll may show unwanted scrollbars
  • float: left will push the element to the left, with other elements wrapping around it
  • overflow: hidden will clip elements that overflow

So whenever we are creating a new block formatting context, we choose the best condition based on our requirements. For uniformity, I have used overflow: hidden in all the examples given in this article.

.container {
  overflow: hidden;
}

You are free to play with declarations other than overflow: hidden.

Alignment of Boxes in a Block Formatting Context

The W3C spec states:

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

alignment

In simpler words, as we can see in the above diagram, all the boxes that belong to a block formatting context are aligned left (for left-to-right formatting) and their left outer edge touches the left edge of the containing block. In the last box we can see that even though there is a floated element (brown) on the left, the other element (green) still touches the left margin of the containing block. The principles about why this happens will be discussed below in the section on text wrapping.

A Block Formatting Context Causes Collapsing Margins

In normal flow, the boxes are laid vertically one after another starting from the top of the containing block. The vertical distance between two sibling boxes is determined by the individual margins of both siblings, but it’s not the sum of the two margins.

Lets consider an example, in order to understand this.

collapsing margins

In the above diagram we consider a block formatting context having been created where the red box (a div) contains the two green siblings (p elements).

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

And the corresponding CSS is:

.container {
  background-color: red;
  overflow: hidden; /* creates a block formatting context */
}

p {
  background-color: lightgreen;
  margin: 10px 0;
}

Ideally the margin between the two siblings should have been the sum of the margins of both elements (20px) but it’s actually 10px. This is known as collapsing margins. In a case where the margins of the siblings are different, then the higher margin will prevail.

See the Pen OVzrer by SitePoint (@SitePoint) on CodePen.

Using a Block Formatting Context to Prevent Margin Collapse

This may sound a bit confusing at first since we discussed above that block formatting contexts cause margin collapse. But one thing that we must keep in mind is that vertical margins between adjacent block boxes (siblings) collapse only if they are in the same block formatting context. If they belong to different block formatting contexts then the margins between them won’t collapse. So by creating a new block formatting context we can prevent margin collapse.

Lets add a third sibling in the earlier example, so the HTML becomes:

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

With the corresponding CSS being:

.container {
  background-color: red;
  overflow: hidden; /* creates a block formatting context */
}

p {
  background-color: lightgreen;
  margin: 10px 0;
}

The result will be same as above, i.e. there will be a collapse and the three siblings will be separated by a vertical distance of 10px. This happens because all three p tags are the part of the same block formatting context.

Now lets modify the third sibling so that it’s part of a new block formatting context. Then the HTML becomes:

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

And the 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 */
}

Now there will be a difference in the output:

preventing margin collapse

Since the second and third siblings belong to different formatting contexts, there won’t be any margin collapse between them, as evident in the following demo.

See the Pen XbVOXp by SitePoint (@SitePoint) on CodePen.

Using a Block Formatting Context to Contain Floats

A block formatting context can contain floats. Many times we will encounter a situation where a container has floated elements. In that case the container element has no height and its floated children are outside of the normal flow of the page. We generally use a clear fix to solve this problem, with the most popular method being the use of a “cleared” pseudo-element. But we can also accomplish this by defining a block formatting context.

containing floats

Lets look at an example:

<div class="container">
  <div>Sibling</div>
  <div>Sibling</div>
</div>

With the CSS:

.container {
  background-color: green;
}

.container div {
  float: left;
  background-color: lightgreen;
  margin: 10px;
}

In the above case the container won’t have any height and it won’t contain the floated children. To solve this problem we establish a new block formatting context inside the container by adding overflow: hidden. The modified CSS becomes:

.container {
  overflow: hidden; /* creates block formatting context */
  background-color: green;
}

.container div {
  float: left;
  background-color: lightgreen;
  margin: 10px;
}

Now the container will contain the floated siblings and its height will expand to contain its children, with the elements back in the normal flow of the page within this formatting context.

See the Pen Floats With and Without a Block Formatting Context by SitePoint (@SitePoint) on CodePen.

Using Block Formatting Contexts to Prevent Text Wrapping

Sometimes the text around a floated div wraps around it (as in Figure 1 in the image below) but in some cases this is not desirable and we want an appearance like in Figure 2. To solve this, we might use margins, but we can also solve this with a block formatting context.

Preventing text wrapping around floats

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:

Float model

The HTML for the diagram could be assumed as:

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

The whole black area in the above diagram denotes the p element. As we can see, the p element doesn’t shift but it goes under the floated element. The line boxes of the p element (referring to the lines of text) undergo a shift. Hence the line boxes narrow horizontally to make space for the floated element.

As the text increases, it will eventually wrap under the floated element because the line boxes no longer need to shift and hence a condition like Figure 1 appears. This explains how the paragraphs touch the left edge of the containing box even when a floated element is present and how the line boxes narrow to accommodate the floated element.

If we are able to shift the entire p element, then this wrapping problem will be solved.

Before going to the solution, let us recall again what the W3C spec says:

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

According to this, if the p element establishes a new block formatting context then it will no longer touch the left edge of the container block. This can be achieved by simply adding overflow: hidden to the p element. This way creating a new block formatting context solves the problem of text wrapping around a floated object.

See the Pen A Block Formatting Context Preventing Text Wrap by SitePoint (@SitePoint) on CodePen.

Using Block Formatting Contexts in Multi-column Layouts

If we are creating a multi-column layout spanning the full width of the container, the last column will sometimes drop to the next line in some browsers. This might happen because the browser is rounding off the column’s width and the total width becomes more than that of the container. If, however, we establish a new block formatting context in a column of the layout, it will always take the remaining space left after the previous columns have filled.

Let’s use an example of a multi-column layout with 3 columns:

Here’s the HTML:

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

And the CSS:

.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; 
}

The result is in the CodePen demo:

See the Pen Using a Block Formatting Context to make a Final Column “fit” by SitePoint (@SitePoint) on CodePen.

Now even if the width of the container changes slightly, the layout will not break. Of course, this is not necessarily a good option for multi-column layouts, but it is one way to prevent the problem of the final column dropping. Flexbox would likely be a better solution in a case like this, but this should serve to illustrate how elements behave under these circumstances.

Conclusion

I hope this post has shown you the relevance of block formatting contexts and how they affect the visual positioning of elements on a page. The examples showing their use in practical cases should make them a little more clear.

If you have anything to add, please let us know in the comments. And be sure to review the W3C’s more detailed discussion of the topic if you want to go deeper.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

  • simon codrington

    Thanks for the article. Great reading about how overflow can effect the layout of elements around it :)

    • Ritesh Kumar

      Glad that it proved useful for you.

  • carinlynchin

    nice

    • Ritesh Kumar

      Thanks @carinlynchin:disqus

  • Vasulu Saya

    Nice article on block formatting context!
    In my online teaching, I generally discourage the use of elements. But, I am convinced that for creating a new block formatting context, the use of becomes necessary.
    Thanks a lot for putting the effort to explain it to the larger web community.

    • Ritesh Kumar

      Thanks @vasulusaya:disqus . Its always great to do something for the community.

  • Paul

    This is greatly helpful, I am a new guy, and still a little confused about something:

    1. I noticed you marked “overflow: hidden” as create block formatting context, but as your information, the “float: left” should also create block formatting context, but you didn’t mark it “/* creates block formatting context */”, sorry for this stupid question.

    2. For the section of wrapping text, You mentioned “The line boxes of the p element (referring to the lines of text)”, what does it mean by line boxes? and also you said “This explains how the paragraphs touch the left edge of the containing box even when a floated element is present”, does it mean float element create block formatting context? so, the p outer edge touch the containing edge?

    • Ritesh Kumar

      Hi Paul,

      1. I mentioned in the earlier part of the article that i will use “overflow:hidden” just for uniformity . You are free to use “float:left” and it will do the same.

      2. I think http://stackoverflow.com/questions/6196725/how-does-the-css-block-formatting-context-work#answers will clear your doubts in this field. This is a detailed explanation of your doubt.

      • http://cssmojo.com/ Thierry Koblentz

        “i will use “overflow:hidden” just for uniformity . You are free to use “float:left” and it will do the same.”

        Actually, those 2 do not do the same because the latter makes the box *shrink*.

        [edit] Those interested in supporting oldIE could read this: http://yuiblog.com/blog/2010/05/19/css-101-block-formatting-contexts/

        • Ritesh Kumar

          Hey,

          You are right. I have already mentioned that though you have different options of creating a BFC, there will be some other effects of each . So you need to use the best choice according to your needs.

    • LouisLazaris

      Hi @disqus_I48IwwiW8T:disqus,

      Just to clarify a little further. Although the code does include “float: left” in a few instances, and yes, this is creating a new formatting context, in those cases it was the other elements that needed the new formatting context. For example, the two floated elements inside the collapsed container have their own BFC’s due to the “float”. But the container does not, so that’s where he needed to add it, in order to overcome the collapsed parent.

      • Paul

        Thank you, I can understand that collapse.

        But In Ritesh’s wrap text with picture example, the original code shows picture was “float: left”, and “p” element is under picture, and wrap around picture, here “container” is not set up with “overflow: “hidden”, so “container” does not have Block Formatting context, but picture was “float:left”, therefore the picture is in Block Formatting context. And “p” element not in Block Formatting context, the question one is: why “p” element touch the left outer edge of containing block?

        Based on the definition: “In a block formatting context, each box’s left outer edge touches the left edge of the containing block”, here “p” element is not in a block formatting context. never trigger block formatting context for “p”, so why “p” element(under the picture) touch the left outer edge?

        The question two: Ritesh says set up block formatting context for “p”, why this can prevent text wrap around floated element after setting block formatting context? I cannot understand it very well, and feel very uncomfortable when I am using this technique, and also I don’t feel very confident when I am using this.

        • Ritesh Kumar

          Hi @paul,

          Question 1:
          You are right . This is working here because its the default behaviour of ‘p’ even if we don’t define a new BFC on the container but that part of the tutorial was mainly to show the p overlapping the image to understand the BFC interactions between the ‘p’ tag and the ‘img’ tag.

          Don’t be confused about this as your thinking is totally right. Its just that the default behavior without the BFC (on container) is same as one with the BFC (on container) so it didn’t cause any error even if i didn’t add ‘overflow:hidden’ to container. But surely I should have mentioned this. You can add it on the container and it will work the same and will be more logical.

          Question 2 :
          Regarding your next question about how “p” doesn’t overlap “img” after creating a new BFC in “p”. Simply put two BFCs don’t collapse so img and p tag don’t collapse/overlap since both of them are different BFCs (triggered manually).

          • Paul

            Thank you, it is more clear for me now. I really appreciated it.

          • Paul

            add BFC for the “p”, “p” doesn’t wrap the “img”, and “p” and “img” laid out from left to right in horizontal, why they are not in vertically?

          • Ritesh Kumar

            Because img is a inline-block element and not a block element

          • Drake Leung

            That’s because the `p` tag is block-level element, so it will participate in the BFC. Check out the `Normal Flow` part of the doc http://www.w3.org/TR/CSS21/visuren.html#normal-flow

  • Michael Romer

    Thank you! One question: Assuming there are no author CSS rules involved, this would all be layouted in one BFC, right?

    Some Content here

    Some Content here

    Some Content here

    • Ritesh Kumar

      yes they will be part of normal flow and a BFC.

      • Michael Romer

        Thanks much! Keep up the good work! :-)

  • Drake Leung

    Nice post~ which I have learned lots of things from.
    BTW, could you recommend some post, kind of `understanding float in css`, and so on~

    Q1: What about I set `body` tag `overflow: hidden`。Can it create a new BFC?
    Q2: BFC can contain floats element, what about absolutely positioned element?

    • Laimis Petravicius

      It’s a bit late, but oh well, for some other people that come across this question
      Q1: body is already a flow root element, which means it has its own BFC without a need to trigger one for it.
      Q2: Absolutely positioned elements triggers their own BFC. To answer your question, BFC can contain another BFC inside of it and so on… (yeah, META, I know)

  • http://www.learnuxid.com/ Ahsan Idrisi

    Great article, very well explained

  • Oleg Baskakov

    Nice article, thank you.
    However I do not figure out why margins between boxes in the last demo are different.

    • Laimis Petravicius

      Imagine that BFC (when you apply overflow: hidden for an element) builds like a wall between the other element (or box, I refer to the same thing) and that wall do not let the margins collapse. Collapsing means that when a box has margin-bottom and another box after it has margin-top both has 10px, it should be a total of 20px distance (white space) between them, however, they collapse, because there is nothing in between them, and instead of 20px there is a 10px distance. Now when BFC is triggered it won’t collapse and there will be 20px distance (as it should be). The same effect can be achieved without a BFC, tho. You just add a border or padding to the one of the elements and thei will end up having 20px distance.

      • Oleg Baskakov

        All three boxes have their own BFC, because of properties overflow: hidden or float: left. So what is the difference between them that causes different vertical margins?

  • Sung Qee

    Solve my overflow:hidded confusions,Many Thanks!

  • Djain Shop

    Hi,

    This is really good article and the 3-col trick was new to me. However, what I’d like to know is, why a block with `overflow:hidden` and `flex` does not shrink to content width unlike `floats`,`inline-block`, ‘table-cell`, `inline-flex` etc which actually do shrink to content width. What specs determine the difference in behavior across BFC’s ?

    • http://cssmojo.com/ Thierry Koblentz

      Being a BFC does not make the box shrink; what make it shrink are the styles you listed.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.