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.
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 'containing block' and 'block container box' in CSS?
Let's start at the beginning. CSS is almost entirely about boxes. A box is just a rectangular area of the canvas. The canvas is the entire 2D space on which everything is drawn.
CSS Boxes have a whole range of flavours. Block boxes, block-level boxes, inline boxes, inline-level boxes, content boxes, padding boxes, border boxes, margin boxes, table boxes, line boxes, flex boxes, and so on. They're all just rectangular areas.
So a block is just one type of box. Many of the above boxes are characterized by two behaviours - how they are laid out relative to their containers and peers, and how their content is laid out within them. The CSS-display spec refers to these as display-outside and display-inside respectively
Display-outside refers to the "*-level" nature of the boxes. They're not what we're interested in here.
All block boxes, and some inline-level boxes are block container boxes. A block container box is a box of type "block container", not necessarily a box that contains blocks. Block containers that are not block-level boxes include those that are display:inline-block
and display:table-cell
The "block" in "block container" refers to its display-inside behaviour. Block boxes are laid out vertically within them and text flows horizontally, ordinarily limited by its edges of the rectangle.
So a "block container box" is a type of box. In contrast, "containing block" refers to a specific box. Each box defined on the canvas has exactly one containing block, with just one exception, called the initial containing block, which has no containing block.
Only a box of type "block container box" can be a box's containing block.
Time for an example. Let's suppose we have the HTML below: I'm deliberately going to use <span>
elements throughout, because this is all about CSS, and I don't want to confuse with HTML behaviour.
<span id="level1">
foo
<span id="level2">
bar
<span id="level3">
baz
<span id="level4">
qux
</span>
</span>
</span>
</span>
The CSS is very simple. Just
#level1 { display:inline-block }
The other spans are the CSS default display setting, "inline".
Now, consider the #level4
span. Its parent is the '#level3' span, which is display:inline
so the '#level3' span does not form a block container box. Similarly, the #level2
span also does not form a block container box. But the #level1
element is display:inline-block
. That forms an inline-level box, but one that is a block container box. (This is what "inline-block" means).
So the containing block for all the inline boxes formed by the #level2
, #level3
, #level4
spans and their text content is the block container box formed by the #level1
element's box.
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.
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.
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>
Related Topics
@Font Face Choppy Font in Chrome
Use CSS to Hide Contents on Print
How to Make a Fluid Sticky Footer
Selector for One Tag Directly Followed by Another Tag
Best Way to Use Media Queries for Mobile Designs
How to Change Bootstrap 3's Glyphicons to White
Calc() Function Inside Another Calc() in CSS
Can Flexbox Divide Items Evenly on Multiple Rows
What Browsers Support "!Important"
What Is the Current State of Sub-Pixel Accuracy in the Major Browsers
Firefox Line-Height Issue with Input Fields
What Are Cross-Browser, Cross Platfom Web Safe Fonts
How to Add CSS Files to a Custom Module in Odoo
Changing the Scrollbars' Style
Can Not Use Theme Color with Text or Bg
CSS - Div Width Depending on Image Size Above