Skip to navigation

Formatting contexts

When your browser lays out a normal, unstyled page, it looks at it from a macro level and a micro level. At the macro level, it tracks where one paragraph stops and another one starts. At the micro level, it lays out the text, line by line, for each paragraph.

If a page is made of paragraphs with text in them, this back-and-forth looks something like this:

  • Start the first paragraph.
    • Start laying out text on the first line, until you can’t lay out any more text.
    • Wrap onto the next line, and keep laying out text.
    • Repeat this text laying and line wrapping until there’s no more text to write in this paragraph.
  • When there’s no more text for this paragraph, mark the end of the paragraph, and start the next paragraph right below this one.

What you see above is that there are two different sets of rules. The first (outer) level of rules talk about how paragraphs lay out one after the other. The second (inner) set of rules focus on how lines of text lay out within each a paragraph. The W3C describes these as if they were different worlds, and calls them formatting contexts — literally, the contexts (rules, circumstances, environment, etc.) in which content is formatted.

According to the W3C, the outer set of rules defines the block formatting context, while the inner set of rules make up the inline formatting context.

Block formatting context

Paragraphs, lists, tables, <div>s, headings, and other block-level elements are formatted within block formatting contexts. This is a fancy and cryptic name that basically means that these elements relate to each other like you would expect:

  • If one block-level element is after another in the source code, then the second block element follows the first one on the page.

  • If one block-level element is inside the other, then it lays out inside the outer one.

  • Blocks line up against the left edge of whatever block contains it (or the right edge, with right-to-left languages).

  • The height and width of a block are based on the height and width, padding and border properties. This may seem like it should be obvious, but this isn’t true in the inline formatting context. More on that later.

There are some important, and confusing, things about block formatting contexts:

  • Vertical margins don’t add to each other. They can even cause unexpected gaps. This phenomenon is known as collapsing margins.

    The concept behind collapsing margins makes a lot of sense for most content. If you say that you want, say, 1em of space margins around your paragraph, you probably mean 1em of margin between your paragraphs, too. Without collapsing margins, a rule that says “add 1em margins around paragraphs” would mean 2ems between paragraphs.

    When it doesn’t make sense (in a colored header, for example) you can apply padding or border to cause the margin to stand out on its own.

    For more on what this means, and how to address it, read Eric Meyer’s article on collapsing margins.

  • There can be more than one block formatting context. This one throws people for a loop, but is vital to know about for dealing with tricky stuff like pushing away from floated elements, keeping floated elements contained inside a box, and clearing stuff in one area but not another. More about this later.

    Although we don’t think about it in these terms, we already know that there is more than one block formatting context when we absolutely position something. Most block elements do their thing in the <body> tag of the site. That’s one block formatting context. When we position something absolutely, we can do all sorts of crazy things in there, and they all stay inside that absolutely positioned element. That’s another block formatting context.

    The specs say the following about when new block formatting contexts are created:

    Floats, absolutely positioned elements, inline-blocks, table-cells, and elements with 'overflow' other than 'visible' establish new block formatting contexts.

    A couple of things to consider about the last two types of elements. When the specifications say “table-cells” that doesn’t just mean <td> tags. It also means elements who have their display property set to table-cell, or anonymous table cells (that is, ones that are created for you when you define an element’s display property as table, table-row-group or table but don’t define a table-cell inside of it).§

    Note: Containing lots of content in an element with overflow set to something other than visible can bring current browsers and computers to their knees. Use it sparingly and judiciously. If you must create a new block formatting context with a lot of content in it, consider floating, or using another element or property.

  • What happens in one block formatting context stays in that block formatting context.

    • Containing floats: If you have a floated element you don’t want to escape another block, make that containing block a new formatting context by floating it, or giving it overflow of anything but visible.§

    • Containing clears: If you have a floating element, like navigation, on one side, then a float next to it that you want to clear, you might accidentally clear the navigation as well as the intended item. By putting the item you want to clear, and the item it is clearing, in the same block formatting context, you can keep from clearing the navigation. This is how most float-based layouts work, where content in the center column can be floated and cleared as much as you like, because the center column is floated. §

    • Containing collapsing margins: If you have a top or bottom margin that collapses into the margins of something else, put one or the other item into its own block formatting context. (Do this only if you can’t use borders or padding, since block formatting contexts are more expensive to make than padding and borders.) §

    • Pushing boxes away from floats: Floats usually push lines of content away from their edges, but not blocks themselves. To make a float move the edge of a block, make that block a new formatting context. This is how float-based layouts work. Since each float is its own block formatting context, they get out of each other’s way. This is permitted in §

Inline formatting context

While the block formatting contexts describe the world of paragraphs, headers, and all sorts of blocks, it doesn’t describe how text should flow from one line to the next. This world is the world of the inline formatting context. This is just a fancy name for how text (and inline elements like <strong>) flow from one word to the next, wrapping to fit inside the block.

Just like block formatting contexts, inline formatting contexts have a few rules that can be surprising:

  • “line-height” rules the day, not “height”. Although replaced elements like images and objects use width and height to define their dimensions, the space taken by an inline element is determined by its line-height, not its height.


Inside Fundamentals: