2

When I read the CSS Visual formatting specification, I see that

Boxes in the normal flow belong to a formatting context, which in CSS 2.2 may be table, block or inline. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

But not all boxes create a Block Formatting Context. Where in the docs does it describe the normal flow for boxes that don't create a BFC, and if they don't create one, what formatting context applies?

.container {
    background-color: red;

    /*overflow: hidden; !* creates a block formatting context *!*/
}

p {
    background-color: lightgreen;
    margin: 10px 0;
}
<div class="container">
    <p>Sibling 1</p>
    <p>Sibling 2</p>
</div>

For example in this code, if I uncomment overflow: hidden; the div gets a BFC, but what it was before?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
ogbofjnr
  • 1,688
  • 5
  • 19
  • 41
  • Can you provide one counter-example of a "box" that would not create a block formatting context? – sjahan Apr 12 '19 at 14:22
  • 1
    From the docs: These ones that create BFC: ```Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.``` So all others not create BFC – ogbofjnr Apr 12 '19 at 14:25
  • you have it in the same spec `Inline formatting contexts` (it's eother block or inline FC) – Temani Afif Apr 12 '19 at 14:28
  • `div`s are block level by default, whether or not their overflow is hidden. What you're showing in your example is the `p` elements margins being collapsed. – DBS Apr 12 '19 at 14:51
  • @sjahan A block with the default CSS (i.e. no `position`, `float`, `opacity` etc) does NOT create a new FC. it just participates in the parent's FC. – Mr Lister Apr 12 '19 at 15:11
  • 1
    @DBS "block level" is not the same as "formatting context". – Mr Lister Apr 12 '19 at 15:12
  • 2
    @TemaniAfif - The definitions of what establishes a Block Formatting Context and an Inline Formatting Context are not mutually exclusive. A single block can establish one, both or neither. – Alohci Apr 12 '19 at 16:15
  • @Alohci true, I miss read the question I guess. I thought he want to know to which FC an element belong and for me (probably I am wrong ..) it's either an IFC or BFC if the element is in the normal flow (not absolute positionned) – Temani Afif Apr 12 '19 at 21:08

2 Answers2

2

Put simply, every block sits in a formatting context. Blocks that have no special properties (e.g. divs with no extra CSS attached) all sit in their parent's formatting context.

Only when a block has properties like position, float, opacity etc., does a new formatting context get created for the block and its contents.

And to answer your question what's it called when a block does not create a BFC of its own, that's simply what the W3C page calls "normal flow".

TylerH
  • 20,799
  • 66
  • 75
  • 101
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
  • I don't think that's quite correct. Or maybe just not clear. Properties that cause a block to establish a block formatting context do so for their contents, but the block itself remains in the block formatting context of its nearest ancestor that establishes a BFC. – Alohci Apr 12 '19 at 15:49
  • @Alohci But a block with `position:absolute` does not influence its ancestor at all, so can it still be said to "participate" in its ancestor's BFC? I thought the W3C page said it didn't. I'll read it again. – Mr Lister Apr 12 '19 at 15:59
  • Yes. The situation seems to be a bit unclear if the element is not in normal flow *as well as* establishing a BFC. I couldn't find what the spec says there, but e.g. a absolute positioned element that has none of top, bottom, left or right set, will be placed as if it were in the flow of the BFC, though it doesn't affect subsequent elements. – Alohci Apr 12 '19 at 16:05
  • @Alohci per my understanding, creating and belonging to a BFC are not related. an absolute element will create a BFC (we all agree with this) but will not belong to any one simply because it doesn't affect the sibling elements around wheares in a BFC `boxes are laid out one after the other`. also in the Spec they have a section for normal flow and absolute element. Concerning the position I think we only consider the static position (that will make the element as a part of the BFC) to only find the top value but it doesn't really mean it's part of the BFC (my interpretation thought) – Temani Afif Apr 12 '19 at 21:41
2

Where in the docs does it describe the normal flow for boxes that don't create a BFC

I would say in the same doc you are referring since an element that doesn't create a BFC is a box that necessarily belong to another BFC (or IFC) if it's an in-flow element.

if they don't create one, what formatting context applies?

Simpy no one. An element doesn't necessarily create a formatting context.


To make it easier to understand, let's consider the MDN definition:

A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with other elements.

then we can read

Setting overflow: auto created a new BFC containing the float. Our <div> now becomes a mini-layout inside our layout. Any child element will be contained inside it.

In other words, a BFC is a way to isolate a part of a layout in order to avoid any interaction with the external world. Some known interactions are floating and margin collapsing.

Let's take an easy example:

.wrapper {
  outline: 1px solid;
  overflow: hidden;
}

.wrapper>div {
  margin: 10px;
  background: red;
}
<div class="wrapper">
  <div>
    <p>some text here</p>
    <p>some text here</p>
  </div>
  <div>
  </div>
</div>
<div class="wrapper">
  <div>
  </div>
</div>

In the below example we have our wrapper creating a BFC and all the elements inside belong to it including the p tags even if they aren't direct child of it. You will notice that there is no margin collapsing with the wrapper and its child element while we have margin collapsing between the adjacent p and between p and the parent div.

Let's add floating elements:

.wrapper {
  outline: 1px solid;
  overflow: hidden;
}

.wrapper>div {
  margin: 10px;
  background: red;
}

div.float {
  float:left;
  width:50px;
  height:50px;
  margin:0;
  background:green;
}
<div class="wrapper">
  <div class="float"></div>
  <div>
    <p>some text here</p>
    <p>some text here</p>
  </div>
  <div>
  </div>
</div>
<div class="wrapper">
  <div class="float"></div>
  <div>
  </div>
</div>

Each float element belong to the BFC created by the wrapper and interact with all the elements inside it (including the p tags).

As you can see, we have a div element that doesn't create BFC and belong to the one created by the wrapper and their child also.

Now let's make the inner div create a BFC:

.wrapper {
  outline: 1px solid;
  overflow: hidden;
}

.wrapper>div {
  margin: 10px;
  background: red;
}

div.float {
  float:left;
  width:50px;
  height:50px;
  margin:0;
  background:green;
}
<div class="wrapper">
  <div class="float"></div>
  <div style="overflow:hidden">
    <p>some text here</p>
    <p>some text here</p>
  </div>
  <div>
  </div>
</div>
<div class="wrapper">
  <div class="float"></div>
  <div >
  </div>
</div>

You can clearly see how the float no longer behaves the same, and how the margin of p no longer collapses with the parent div. This is because we have isolated our content and it no longer interacts with the outside world.

Now if we remove all the overflow:hidden, we will make all the elements belong to the same BFC created by the root element (html) and no one is creating a BFC.

.wrapper {
  outline: 1px solid;
}

.wrapper>div {
  margin: 10px;
  background: red;
}

div.float {
  float:left;
  width:50px;
  height:50px;
  margin:0;
  background:green;
}
<div class="wrapper">
  <div class="float"></div>
  <div >
    <p>some text here</p>
  </div>
  <div>
  </div>
</div>
<div class="wrapper">
  <div class="float"></div>
  <div >
  </div>
</div>

We can clearly see the difference and how all the elements interact with each other epsecially the float elements.


Note that all this apply to normal flow element and to float element (with some special behavior like described in the specification) but when it comes to absolute positioning it's different.

An absolute (or fixed) element create a BFC for its content but doesn't belong to any BFC because:

It is removed from the normal flow entirely (it has no impact on later siblings)

whereas in a BFC we have:

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • You say no formatting context applies to a block that doesn't create one itself, but that isn't strictly true; there is always a formatting context. In the simplest of documents, the canvas itself is a formatting contexts and all the elements sit in it. Or, participate in it, to use the W3C's terminology. – Mr Lister Apr 13 '19 at 06:09
  • I know, it isn't easy simplifying things and still be 100% factually correct ;) – Mr Lister Apr 13 '19 at 06:10
  • 1
    @MrLister well, english isn't my best but I didn't really say *no formatting context applies* to a block. What I tried to explain is that in all the cases a box in the normal flow should at least belong to an FC (the first sentence) then it doesn't necessarily create one (second sentence). So basically you need for sure to belong to an FC and you can or not create one. I also later said that if we remove all the `overflow:hidden` from my example, all the element will belong to the BFC created by the root element – Temani Afif Apr 13 '19 at 08:01
  • when the OP asked `what formating context applies?` I didn't understand *to what FC the element belong* but what should be the FC of the element if it's not a BFC. In other words, the OP think that an element need to create an FC in all the cases and I replied *no it's not* (this is what I understand though) – Temani Afif Apr 13 '19 at 08:08