When Does a Box Establish an Inline Formatting Context

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.

Why the boxes in an inline formating context was laid out vertically?

The premise of your entire question is flawed. Assuming the inner divs retain their default styles, then they are block boxes, which means #wraper can't possibly establish an inline formatting context in that situation in the first place.

The inner divs participate in block layout, but they participate in whatever BFC that is already there (that #wraper itself also participates in). This can be from some ancestor that meets the criteria for establish a BFC; otherwise, it's the BFC of the root element.

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>

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

Do Inline elements establish a Line Box for their content?

Your heading and first paragraph ask two different questions:

  • Do Inline elements establish a Line Box for their content?
  • [Are] line boxes are formed inside inline-level elements?

They have different answers, "No", and "Sometimes" respectively, so the first thing that needs to be dealt with is the -level suffix.

An inline-level box is a broader category than an inline box. A span element which contains only text generates, by default, a sequence of inline boxes sufficient to lay out that text content over as many lines as is necessary. All inline boxes are also inline-level boxes, but the opposite is not true. Elements whose computed display is inline-block, inline-table, inline-flex and inline-grid all generate boxes that are inline-level, but are not inline boxes.

Similar applies to block versus block-level. Block-level describes how a box lays out relative to its parents and siblings. Block containers are boxes in which their child boxes are laid out either as sequence of block-level boxes, or within a stack of line boxes, and never as a mixture of both.

Elements whose computed display value is block, flow-root and list-item and are being laid out in a block formatting context (i.e. they're not a flex item or a grid item) generate a single box that is both block-level and a block container. These are called block boxes.

But boxes generated for elements that have computed display values of table, flex, and grid are block-level, but they are not block containers. Their descendants are laid out using different rules. These are not block boxes.

Conversely, elements that have computed display values of inline-block and table-cell generate boxes that are block containers but they are not block-level. They interact with their parents and siblings differently than block level boxes do.

So, specifically, inline-block boxes, which are inline-level, contain either a sequence of block-level boxes, or a stack of line boxes in which other inline-level boxes are laid out.


Now, an inline box can contain other inline-level boxes, but that does not make it a block container, even if one of those inline-level boxes is itself a block container. The block container of the inline box and all its descendant inline-level boxes that are not themselves inside other formatting contexts is the nearest ancestor that is a block container.

So, suppose we have this tree of boxes

 display:block                     block level, block container
| ↑ ↑
+ - display:inline inline level ---------+ | \
| | |- In the same line box
+ - display:inline-block inline level, block container /
| ↑
+ some text anonymous inline box --+ in a line box

where the arrows point from inline-level boxes to their block container.

How does the CSS Block Formatting Context work?

Block Formatting Contexts

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.

With my bold, it's the establish bit that is important

What this means is that the element you use overflow (anything other than visible) or float or inline-block..etc on becomes responsible for the layout of its child elements. It's the child elements which are then "contained", whether that's floats or collapsing margins they should be wholly contained by their bounding parent.

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)

What the above line means:

Because a box can only be rectangular and not irregular shaped this means a new block formatting context between two floats (or even beside one) will not wrap around neighbouring side floats. The inner, child boxes can only extend as far as to touch their parents left (or right in RTL) edge. It's this behaviour that's useful for columnar style layouts. The main use of it however is to stop floats, say in a "main content" div, actually clearing floated side columns, i.e. floats that appear earlier in the source code.


Float Clearance

In normal circumstances floats are supposed to clear all previous floated elements, that's previously floated in the whole source code, not just your displayed "column"
The telling quote from the "float clearance specs" is:

This property indicates which sides of
an element's box(es) may not be
adjacent to an earlier floating box.
The 'clear' property does not consider
floats inside the element itself or in other block formatting contexts

So say you have a three column layout where the left and right columns are floated left and right respectively, the side columns are now in new Block Formatting Contexts, because they are floated (remember float is also one of the properties that establish a new BFC), so you can happily float list elements inside them and they only clear floats which are already inside the side columns they no longer care about floats previously in the source code


##To make the main content a new Block Formatting Context or not?

Now that middle column, you can simply margin it from both sides so that it appears to sit neatly between the two side floated columns and take the remaining width, a common way to get desired width if the centre column is "fluid" - which will be fine until you need to use floats/clearance inside your content div (a common occurrence for those using "clearfix" hacks or templates including them)

Take this very simple code:

#left-col {
border: 1px solid #000;
width: 180px;
float: left;
}
#right-col {
border: 1px solid #000;
width: 180px;
float: right;
height: 200px;
}
#content {
background: #eee;
margin: 0 200px;
}
.floated {
float: right;
width: 180px;
height: 100px;
background: #dad;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
<h3>Main Content</h3>
<p>Lorem ipsum etc..</p>
<div class="floated">this a floated box</div>
<div class="floated">this a floated box</div>
</div>

Who is responsible for establishing formatting context for `body` element?

the body element acts as block container box.

No, it doesn't. We can easily proove it by using a float element:

.float {
height:50px;
width:50px;
background:red;
float:left;
}

body {
border:2px solid blue;
}

html {
border:2px solid green
}
<div class="float"></div> some text here


Related Topics



Leave a reply



Submit