Block Level Element Vs Block Formatting Context

Block Level Element vs Block Formatting Context

Note that this answer uses the term "box" in lieu of "element", as CSS makes a distinction between elements and boxes. For the purposes of this answer, an HTML element is represented by a single box in CSS layout. In reality an element may generate any number of boxes (or none at all, as in display: none), but that's outside the scope of this question.

Can a HTML element be both a block level element and form a block formatting context?

Yes. The criteria in which a block box (i.e. a block-level block container box) may establish a BFC are stated in section 9.4.1 of CSS2.1, namely:

  • floats,
  • absolutely positioned elements, and
  • "block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport)" (as directly quoted from the spec)

Does being a block level element imply that it forms a block formatting context, or conversely, does forming a block formatting context imply that it must be a block level element?

Neither:

  1. The above answer implies that not all block boxes establish block formatting contexts. A block box with the CSS properties display: block; overflow: visible; float: none; position: static (or position: relative) does not establish a BFC.
  2. Conversely, an inline-block is an example of a box that establishes a BFC, but is itself inline-level, not block-level.

In a similar vein, how does this translate to inline elements and elements that form an inline formatting context?

An inline box is an inline-level box whose contents participate directly in its parent's inline formatting context (see section 9.4.2). Notably, the only boxes that can establish inline formatting contexts are block container boxes.

The difference between an inline box and an inline-block is that an inline-block's contents participate in the BFC that it establishes, not in the parent's IFC. Instead, only the inline-block itself participates in its parent's IFC.

What does a block formatting context actually do?

Formatting contexts in general establish a set of rules for the layout of their contents.

The rules for Block formatting contexts are that their in-flow contents are laid out vertically one after the other.

In addition, BFCs have a few side-effects, that exist largely to make the rules established for their contents implementable, such as the way they work in the presence of floats inside or next to them.

Taking your points one by one,

  • According to MDN's definition, participating in a BFC makes an element adhere to the box model...but don't all elements, even a
    floated element, adhere to the box model?

Yes they do. MDN does not actual say that it makes them adhere, just that they do adhere. The MDN statement is rather redundant, but not harmful or incorrect.

  • According to the spec's definition, all boxes are laid out vertically, but my right-floating div and the p tag are side by side.

This is incorrect. The floating div overlaps the p element. Only the inline content of the p element is side by side with the floating div.

  • It seems that a BFC just makes the container fit all elements participating in its BFC, but if this is the case, then how come
    using a position: absolute instead of a float: left doesn't provide
    the same outcome of making the container fit the absolutely

    positioned element?

As said above, that BFCs contain their floats is best regarded as a side-effect of the BFC, not really what it does.

Finally, although BFCs provide some isolation of their contents from the outside world, it is not complete. For example, inline-block elements establish BFCs for their contents, but their baselines escape this isolation and are used to vertically align the elements with their inline neighbours.

How can block container establish both block and inline formatting contexts at the same time?

It's entirely possible, and even necessary for certain CSS rules. The easiest way to understand this is with an example of such a box.

<div style="overflow:auto">hello world</div>

Here we have an element with display:block (by default for div elements) and overflow:auto. This is one way that an element's rendered box will establish a block formatting context. This affects, for example, how the box's location and dimensions are affected by the presence of floats.

Compare these two examples:

.formatting.contexts {  overflow:visible;}
.container { width:70px;}
img { float:left; margin-right:3px;}
<div class="container">  <img src="http://placehold.it/16" alt="placeholder grey square less than one line in height">  <div class="formatting contexts">hello world</div></div>

When does a box establish an inline formatting context?

To answer your question, I reread Section 9.2.1 of the CSS 2.1 spec.

Based on my reading, you have your answer: the inline formatting context is triggered when a block container box contains only inline elements.

In contrast to a block formatting context that can be triggered explicitly (for example, setting overflow: hidden to a block-level element), an inline formatting context cannot be triggered explicitly.

Inline formatting contexts appear to always exist as descendant block boxes within a "principal block-level box", and these descendant block boxes may be anonymous.

I offer the following description as a mental model for understanding block/inline formatting contexts.

A block-level element (e.g. a <div>) fulfills two responsibilities: one, positioning, and two, content formatting.

When dealing with positioning, a block-level element acts as a "block-level box".

When dealing with formatting, a block-level element acts as a "block container box".

Acting as a "block-level box", the block-element behaves according to the type of positioning (static, absolute, relative, fixed) specified by the position property.

Acting as a "block container box", the block-element establishes a block-formatting context if the block-element has at least one child block-level element. If all the child elements are inline-level boxes, then an inline-formatting context is established.

If the "block container box" contains text and block elements, then the text is treated as being contained in one or more anonymous block-level boxes, and a block-formatting context is established.

Aside
The CSS spec is not exactly light reading. I have reread Chapters 9 and 10 several times and I have yet to come up with a plain-English translation.

Clarifying definition of block container and block box

HTML elements are not CSS boxes. Zero, one, or multiple boxes are generated for a single HTML element.

The primary concept you're missing is that of an anonymous box.

Suppose you have

<section>
<span>Foo</span>
<div>Bar</div>
Baz
</section>

where section and div are display:block and span is display:inline, just as they are by default.

Now "Bar" and "Baz" get wrapped in anonymous inline boxes, and the span generates an inline box.

Further, because the block box generated by the section element would contain both inline boxes and block boxes, the span and "Baz" inline boxes are wrapped in anonymous block boxes. So the final box tree looks like this.

Block Box             <= from `section` element
+--- Block Box <= anonymous block box
| +--- Inline Box <= from `span` element
+--- Block Box <= from `div` element
| +--- Inline Box <= anonymous inline box from "Bar"
+--- Block Box <= anonymous block box
+--- Inline Box <= anonymous inline box from "Baz"

As you can see from this, no block box contains both a block box and an inline box as direct children, which is what your quoted paragraph is saying.

What formatting context applies to elements that don't create their own?

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

What is the difference between Normal Flow, Flow Layout, Block and Inline Layout?

Normal flow = flow layout = block-and-inline.

block-layout ≠ inline-layout

CSS2 describes block layout:

In a block formatting context, boxes are laid out one after the other, vertically², beginning at the top of a containing block.

and inline layout:

In an inline formatting context, boxes are laid out horizontally², one after the other, beginning at the top of a containing block.

There's plenty more detail¹ there, but that's the essence of the layouts.

The purpose of "Normal flow" is provided a single term of layout to be contrasted with floated and positioned layout, and the internals of other independent formatting contexts.


¹ Pretty much the entirety of sections 9 through 16 of the CSS 2.2 specification are describing that detail.

² "Vertically" and "Horizontally" here assumes a horizontal writing-mode. CSS 3 introduces a vertical writing-mode where everything's rotated though 90°, so "vertically" and "horizontally" are reversed.

What's the difference between a block-level box and a principal block-level box?

A principal block-level box is the block-level box generated by a given element that's directly affected by style rules that apply to the element.

Most elements generate only one box. For these elements, they are essentially the same thing, since there are no other boxes involved.

However, an element can generate more than one box depending on its display type, such as a list item; when you declare styles for such an element, the styles are typically applied to the principal box and any additional boxes that are generated will be rendered accordingly.

For example, a list item has a marker box in addition to the principal box; if you specify list-style-position: outside, the list marker will be placed outside the boundaries of the principal box but the background and borders of the principal box won't be affected. Note that the marker box is still a descendant of the principal box, so inheritable properties such as color will apply to the marker (this is why color: red turns both the text and its bullet marker red).

Most other block-level elements, including display: block but excluding display: table (see section 17.4), will simply generate a principal block box for their content and nothing else, making them essentially just "block boxes", but only for those elements.

In other words, all principal block-level boxes are block-level boxes, but not all block-level boxes are principal, for example anonymous block boxes. Also, inline elements, including inline blocks, do not generate any principal boxes themselves, nor is there such a thing as a principal inline box.

What is meant by participate in the definition of “normal flow” in the CSS 2.1 spec?

When a box is said to participate in some formatting context, it just means that element is laid out according to the rules of that formatting context. If an element participates in a block formatting context, it's block-level and it's governed by block layout. If an element participates in an inline formatting context, it's inline-level and it's governed by inline layout. And so on.

"Block container box" and "block formatting context" are two different and only very loosely related concepts. You seem to be conflating them, which is unwise.

A block container box establishes a block formatting context only under certain conditions. The criteria for this to happen are listed in the spec, but basically the only time a block container box doesn't establish a BFC is when it has display: block; overflow: visible; float: none; position: static/relative (from here).

As stated in the spec, every block-level box participates in some block formatting context. It doesn't matter whether its parent block container establishes a BFC. If its parent doesn't establish a BFC, then the parent's parent, or the parent's parent's parent, or some other ancestor higher up in the tree — all the way up to the root element — does. This means that a single block formatting context can — and almost always does — encompass many nesting levels of elements. This is collectively referred to as the normal flow.

Even if you had an entire layout of block boxes, if none of them establishes a BFC, then all of them participate in the same BFC that's established by the root element (and the root element is guaranteed to establish one). In the following example, all three elements participate in the root element's BFC, and so they are governed by block layout, even though none of them establishes its own BFC:

<body>
<div>
<p>
</div>
</body>

The effects of overflow: hidden on block formatting contexts in the presence of floats are discussed elsewhere, but in short, floats never intrude into other block formatting contexts, which is why making the p establish its own BFC causes it to become narrower due to the float. Making the div establish its own BFC doesn't change anything because, once again, the p is still participating in some BFC regardless — you're just changing whose BFC it's participating in.

Implications of Block Formatting Context

A block formatting context is a tool to help browsers render elements. It prevents tricky cases, so it's not really visual.

For example, float elements are not in the page flow. So other elements could be under or wrap around a floating element.

.float {  float: left;  width: 50px;  height: 50px;  margin: 10px;  background: turquoise;}
.container { height: 100px; margin-left: 30px; background: tomato;}
<div class="float"></div><div class="container"></div>


Related Topics



Leave a reply



Submit