css dojo(re)learn CSS, the right way

The Flow layout

Prerequisite: knowledge from the Box model and Layout kata is necessary to understand the concept of outer/inner display types.

In this kata, we’re going to answer the following questions:(link to the complete list of questions)


The Flow layout is the basic default layout and is optimized for the primary role of a webpage (like this one): display lines of text content with eventual boxes (such as images) between paragraphs.

Lines of text wrapped in boxesImage
A simple representation of the Flow layout

This may be the most important part of the dojo. The Flow layout is the default layout and thus applies almost everywhere in a web page. By learning it correctly, many CSS frustrations will disappear.

The Block Formatting Context (BFC)

The Flow layout always happens in a Block Formatting Context. A BFC is created in certain conditions, including by:

Inside a BFC, the browser will recursively crawl every nested element:

Nested boxes marked as in the flow or not depending on their display typesBlock Formatting Contextdisplay: block flow;In the flow display: block flow;display: inline flow;display: inline flow;In the flow In the flow In the flow display: block flex;display: block flow;In the flow Not in the flow
Will the box be in the flow or not?

Reminder: most elements will have a default display value that will make them participate in the flow.

When every nested element is scanned, the browser ends up with a soup of boxes that participate in the flow and that will be used for the layout algorithm.

Inline and block boxes grouping

Once the browser have determined which boxes will participate in the flow, it looks at their outer display type (which is either block or inline) and create block-level boxes and inline-level boxes accordingly.

One more definition: we call a block container box any box that will contain block-level boxes or inline-level boxes. (Yes I know that using block container box and block-level box is super confusing but those are the exact terms in the spec.)

There is only one rule with block container boxes: a block container boxes must contain only block-level boxes or only inline-level boxes. There can be no mixup between block-level boxes and inline-level boxes in a block container box

What if I have some text that is not wrapped in inline elements such as <span>? In order to have only inline-level boxes in the parent block container box, the browser creates anonymous inline-level boxes around unwrapped text. You can’t select them with CSS but you can still inspect them with the dev tools.

The dev tools inspecting the HTML generated in the editor above
An anonymous inline-level box as seen in the dev tools

What if I mix up inline and block elements, such as <span> and <block>? In order to have no mixup of block-level boxes and inline-level boxes in the block container box, the browser creates anonymous block-level boxes around inline-level children. Again, you can’t select them with CSS and you can’t inspect them with the dev tools (but trust me, they are here).

If we try to sum up all of this, the browser takes all elements participating in the flow in a block formatting context, turns them into boxes (block-level and inline-level boxes), arrange them in block container boxes and introduces anonymous block-level and inline-level boxes accordingly.

A drawing showing squares and lines at the top to represent block and inline boxes, and at the bottom the same squares and lines arranged in boxes following the layout rulesUnwrapped textUnwrapped textBlock-level boxesInline-level boxesBlock Formatting ContextAnonymous block-level boxAnonymousinline-level box
An example of block-level and inline-level boxes grouping

What if I introduce a block element inside of an inline element?

Task: Put a block element inside the middle inline element and try to predict the result

Remember, we are dealing with boxes here. The Flow layout doesn’t care about DOM elements. It only cares about block-level boxes and inline-level boxes. The browser will see five boxes to group together:

Thus, the <div> breaks the "no-mixup rule" and forces a block formatting context by introducing anonymous block-level boxes around the groups of inline-level boxes. The browser tries to reconcile other CSS properties in the most logical way possible. Here, you can see that there is a border on the bottom, left and top sides of the first anonymous inline-level box and the right border is on the last anonymous inline-level box.

Now, let’s say we have a paragraph with inline-level boxes. We also have a block element, for instance a button, that we want to inline in our text. How can we do this?

Task: Inline the "button" in the text without changing its shape by using the display property

Have you found it?


...


If you already know the answer with the shorthand, try to do it with the outer/inner display syntax and truly understand why it works.


...


Congratulations! You just reinvented display: inline-block;!

Why display: inline; doesn’t work: by setting inline, you are explicitly setting the outer display type to inline (which is what we want because we want to inline the button in its parent) but also implicitly setting the inner display type to flow. If the inner display type is flow, the children of our button will participate in the parent flow. The only child of our button is an unwrapped text, therefore an anonymous inline-level box, therefore our button will lose some of its block-level box properties that we want to keep.

By choosing flow-root, we force the creation of an independent Block Formatting Context. The BFC will introduce a root block container box that will honor block-level boxes properties.

Good! At this stage, you should have a good grasp of how block-level boxes and inline-level boxes are organized, and how to alter this organization. Don’t hesitate to let your brain cool off and think about it twice. I’m repeating myself but it probably is the most confusing concept about CSS, and it is really important to truly understand it.

We then move on to the final part of the layout algorithm. Right now, we have a boxes tree with block container boxes containing only block-level boxes or only inline-level boxes.

  1. Inside a block container box containing only block-level boxes, the browser will apply block formatting
  2. Inside a block container box containing only inline-level boxes, the browser will apply inline formatting

Block formatting

When a block container box has only block-level boxes as children, block formatting applies:

Task: here, every margin collapses and every block is 10px vertically from its adjacent boxes. Try to break the margin collapsing in at least 3 different ways

Inline formatting

When a block container box has only inline-level boxes as children, inline formatting applies. Let’s bring up the schema from the styling text kata to understand what is the line height and the baseline:

A lorem ipsum text with arrows pointing to different characteristics of a line of text
Schema of a line of text and related CSS properties

Task: Make the "first" line bigger by changing its font-size and the "second" by changing its line-height

Task: Break the super duper long word!

Task: Make the empty line in the HTML paragraph appear

What I should remember

Ooof! That was a hard one. Now you should have enough knowledge to truly understand and use the Flow layout!

Rate this kata!
I learnt nothing
I learnt a lot