What is the relationship between 'Normal Flow' and 'BFC'? - html

I read this in MDN's Introduction to formatting contexts:
Introduction to formatting contexts
The outermost element in a document that uses block layout rules establishes the first, or initial block formatting context. This means that every element inside the <html> element's block is laid out according to normal flow following the rules for block and inline layout. Elements participating in a BFC use the rules outlined by the CSS Box Model, which defines how an element's margins, borders, and padding interact with other blocks in the same context.
So can we think of 'Normal Flow' as the way to layout in BFC, and Normal Flow is the largest BFC created by the root element (HTML)
My mental model
Is this rough mental model correct?
I consulted the documentation:
Introduction to formatting contexts
Block and inline layout in normal flow
Some concepts from the CSS specification documentation such as:'visual formatting model','block container box','block level box','block box'.

It used to be a decent approximation. Less so nowadays that we have Flex formatting contexts and Grid formatting contexts.
To grasp normal flow, a better place to start is The glossary in the CSS Level 3 Display specification, which says:
out-of-flow
in-flow
A box is out-of-flow if it is extracted from its expected position and interaction with surrounding content and laid out using a different paradigm outside the normal flow of content in its parent formatting context. This occurs if the box is floated (via float) or absolutely positioned (via position). A box is in-flow if it is not out-of-flow.
Note: Some formatting contexts inhibit floating, so that an element with float: left is not necessarily out-of-flow.
So normal flow is all content that's not floated or absolute positioned (including for this purpose, fixed positioned). You probably shouldn't tie this too closely to any particular formatting context.

Related

What is the difference between "block box" and "block-level element"?

This MDN doc says:
In CSS we broadly have two types of boxes - block boxes and inline
boxes.
But in this MDN doc that talks about normal flow, block boxes are never mentioned. Only block-level elements are mentioned.
What is the difference?
Block vs Block-Level
Lots. Block boxes are both block-level and also block containers. That's display:block, display:flow-root, the principal box of display:list-item and the table wrapper box of display:table.
Boxes that are block-level, but not block containers, and therefore not block boxes are those which have e.g. display:flex, display:grid and the table grid box of display:table
Boxes that are block containers, but not block-level, and therefore not block boxes are those which have e.g. display:inline-block and display:table-cell.
Stating that there are broadly two types of boxes - block and inline - is at best misleading, if not outright wrong. We could better say that there are broadly two types of boxes - block-level and inline-level, but even then, only broadly. Block-level boxes are participants in a Block Formatting Context. Inline-level boxes are participants in an Inline Formatting Context. Boxes that are participants in other formatting contexts, such as flex items, grid items, and some of the internal table and ruby boxes are neither.
Elements vs Boxes
Elements are objects of SGML, HTML and DOM. Boxes are objects of CSS. A block-level element is one that when the CSS box tree is being formed, by default generates at least a principal box which is block-level.

Why are inline-level boxes not being laid out according to block formatting context rules despite being inside one?

I am trying to understand the relationship between formatting context and inner and outer display types.
On one hand, the official explanation, in W3 and related websites, says that, all boxes have a formatting context. They either create one, or continue the one of their parent, which too, either created a formatting context, or continued one of its parent, and so on until the initial block formatting context established by the HTML element.
Elements inside a block formatting context are laid out according to block formatting context rules. So that means that, when you insert a div inside another div, the child div is laid out according to the block formatting context rules, because its parent has a block formatting context rules.
So then why aren't elements with display:inline or inline-flex not being laid out according to block formatting context rules?
The explanation states that, the inner display type defines the formatting context which determines the way elements will be laid out. The outer display type dictates how the principle box participates in the flow layout.
This last explanation confuses me, because, isn't the way elements participate inside a container determined by the formatting context of that container?
When you set the display type of a div to "flex", that element creates a flex formatting context inside of itself, however, on the outside, it still behaves according to block formatting context rules, because it is inside one, is that not correct? So, then, why is the same thing not happening with inline elements, or elements with display inline-flex? Why is their outer display type not block when they are inside one?
If changing the display property changes the formatting context inside the element, while its outer behavior is determined by the formatting context of ITS parent, then why are inline elements and inline-flex elements and probably others too not being laid out according to block rules when inside a block formatting context?
then why are inline elements and inline-flex elements and probably others too not being laid out according to block rules when inside a block formatting context?
You are missing a small piece of the puzzle that is called anonymous block box
In other words: if a block container box (such as that generated for the DIV above) has a block-level box inside it (such as the P above), then we force it to have only block-level boxes inside it.
In order to force only block level boxes inside a block formatting context we put our inline elements (or inline-block ones) inside an anonymous block box. That anonymous box will then create an inline formatting context inside it for the inline elements.
Considering this, all the rules you have described will be accurate.

Block Level Element vs Block Formatting Context

What is the difference between a HTML element that is a block level element and a HTML element that forms a block formatting context?
Can a HTML element be both a block level element and form a block formatting context?
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?
In a similar vein, how does this translate to inline elements and elements that form an inline formatting context?
(For some context, I've been trying to read Learn CSS Layout - The Pedantic Way but it's been a bit challenging to follow Chapter 1)
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:
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.
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.

Can a Floated Element Affect "Cousin" Elements?

In what all cases does a floated element push other elements and/or text out of the way?
For example, can floats ever push a "cousin" element around (or any other text/element that requires traversing up the DOM)?
My understanding is that floated elements will overlap only adjacent elements (and their contents) but will then push text and inline/inline-block elements out of the way so no overlap occurs. I've had a few times where float behavior has surprised me in the past so I'd like to verify what I thought I knew.
Directly from the MDN.
Block formatting contexts are important for the positioning (see float) and clearing (see clear) of floats. The rules for positioning and clearing of floats apply only to things within the same block formatting context. Floats do not affect the layout of things in other block formatting contexts, and clear only clears past floats in the same block formatting context.
Block formatting context

Is overflow:hidden to fit a width a hack - is there an alternative?

Is overflow:hidden to fit a width a hack? We have a responsive website that uses overflow:hidden in conjunction with width:100% to set the layout properly. However, any new feature that we add has issues.
For example, we implemented a custom html drop down. The drop down is partially hidden when expanded outside the container.
Is there a proper way to get this to work without having to redo the styles for the entire page?
The behavior I'm trying to describe is used in #4 in this article
http://webdesignerwall.com/tutorials/5-useful-css-tricks-for-responsive-design/comment-page-2
The purpose of overflow:hidden is not to clear floats per se, but to control child content containment by establishing a new block formatting context(BFC) flow root, one feature of BFCs is float containment.
More on BFCs from MDN
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 each other.
A block formatting context contains everything inside of the element
creating it that is not also inside a descendant element that creates
a new block formatting context.
Block formatting contexts are important for the positioning (see
float) and clearing (see clear) of floats. The rules for positioning
and clearing of floats apply only to things within the same block
formatting context. Floats do not affect the layout of things in other
block formatting contexts, and clear only clears past floats in the
same block formatting context.
Technically the way to clear floats is to use clear, this will also mean you dont have to rely on using overflow:hidden thereby removing your menu cropping issue.
You can, for example, have an element after your floated elements with clear set on it - another alternative would be to use a clearfix (also, here). A clearfix uses a psuedo element to apply the relevant clear.
More on clear from MDN
The clear CSS property specifies whether an element can be next to
floating elements that precede it or must be moved down (cleared)
below them.
[...]
The floats that are relevant to be cleared are the
earlier floats within the same block formatting context.