Formatting contexts and CSS positioningFormatting contexts

100%

Formatting contexts.

Every box hands its children a rulebook. A plain block stacks them down the page, a flex container lines them up on one axis and shares out the spare room, a grid drops them into tracks. Some boxes also open a fresh block rulebook, and that acts as a wall: floats inside stay inside, floats outside stay out, and margins stop leaking across. Knowing which box opens which context is how you explain, and fix, an avatar that hangs out of its comment or one long file link that drags a whole board column off the screen.

Intermediate33 minUpdated 2 Oct 2026

Builds on The box model and normal flow.

The idea.

An element never decides its own layout. The box around it runs a layout algorithm for its children, and a few kinds of box start a fresh one that nothing outside can disturb.

Two layout bugs landed in Slatework's tracker in the same week. In the activity panel, a teammate's round avatar dangles below her one-line comment and nudges the first line of the next entry to the right. On the board, someone attached a file whose name is a single unbroken link, and the Review column swelled to more than four times the width of its neighbours, which shrank to slivers. Neither fix is a magic property you memorise. Both fall out of one question: which box's rules is this element being laid out by?

The answer is almost never the element itself. display has two halves. The outer half says how the box takes part in whatever its parent is doing: as a block-level box or an inline-level one. The inner half says what the box does for its own children: keep flowing them as blocks and lines (flow), flow them in a fresh, sealed block context (flow-root), or run flex, grid or table layout on them. So a span inside a paragraph sits on a line like a word, while the same span inside a flex container becomes a flex item: its inline display is quietly turned into block, and the flex algorithm sizes it.

Most block boxes simply continue the context they are in: a div inside a div joins the same block formatting context, so a float in one can reach into the other and margins can merge across their edges. Some boxes open a new context instead. A new context is a wall: everything inside is laid out by rules that start fresh at that box, and the outside sees one rectangle. Flex and grid containers are always walls. For ordinary block content you choose to build one, most cleanly with display: flow-root, and that is the whole fix for the dangling avatar.

Slatework's screen as nested formatting contexts

Slatework's screen as nested formatting contexts. The numbered component cards that follow describe each part.
Slatework's screen as nested formatting contextsComponents: 1. AppShell (The page's grid: top bar across the top, then sidebar, board and activity panel side by side.), 2. Board (Four status columns in a grid, inside a panel that scrolls sideways on small screens.), 3. BoardColumn (One status (To do, Doing, Review, Done): a flex column of task cards.), 4. TaskCard (One task: a header row, an overflow: hidden body, and attachment rows.), 5. CardHeader (A flex row: assignee avatar, task title and due-date chip.), 6. AttachmentRow (A flex row per attached file: icon, file link, size.), 7. ActivityPanel (Comments and events on the selected card each comment floats its author's avatar left.).

htmlthe root block formatting context

1AppShelldisplay: grid

7ActivityPanela grid item, so a new BFC

div.commentdisplay: flow-root

img.avatar
float: left

Comment text
an inline formatting context of line boxes

2Boarddisplay: grid, 4 columns

3BoardColumndisplay: flex, column

4TaskCarda flex item, so a new BFC

5CardHeader
display: flex
avatar · title · due date

Card body
overflow: hidden
a new BFC that also clips

6AttachmentRow
display: flex
icon · file link · size

TopBar
grid item

Sidebar
grid item

6 steps. Step through to see what one change does to these components.

The four contexts you meet in an app

ContextWho starts oneHow it places the childrenWorth knowing
Block (BFC)The root, display: flow-root, floats, absolute and fixed boxes, inline-blocks, flex and grid items, overflow other than visible and clip, contain: layout or paint (full list below)Block boxes one after another in the block direction (down the page in English); floats are pulled to a side and the content of later blocks flows around themMargins of neighbouring blocks can collapse; a float belongs to the BFC it was laid out in
Inline (IFC)A block container whose children are all inline-level (text, spans, inline-blocks, images)Inline boxes and words packed into line boxes, wrapped at soft wrap opportunities, aligned by text-align and vertical-alignVertical margins and padding of inline boxes do not push lines apart; a block inside an inline box splits it
Flexdisplay: flex or inline-flexFlex items along one main axis; each starts from its flex-basis and then grows or shrinks to share the free spaceItems are blockified, float and clear do nothing to them, and an item will not shrink below its content by default
Griddisplay: grid or inline-gridGrid items placed into rows and columns whose tracks are sized from fixed lengths, content and fr sharesItems are blockified; 1fr means minmax(auto, 1fr), so content can widen a track
Was this section helpful?

How it works.

Four mechanisms do nearly all the work: the list of things that open a block formatting context, the three effects of opening one, the way flex and grid turn their children into blocks, and intrinsic sizes, which decide how small an item is willing to get.

1

What starts a block formatting context

Many properties open a new BFC as a by-product of their real job. That is why people reach for overflow: hidden to stop a float leaking and then wonder, a week later, why a dropdown is cut off. Read the right-hand column before choosing a trigger: only flow-root does nothing else.

Triggers, and what each one also does

TriggerNew BFC?What else it does
display: flow-rootYesNothing else. The box stays a block in its parent's flow; it only seals its contents. Use this when containment is all you want
overflow: hidden | auto | scrollYesMakes the box a scroll container: hidden clips what overflows, auto and scroll may add scrollbars. Clipping also catches dropdowns and tooltips drawn inside it
overflow: clipNoClips like hidden but is not a scroll container and starts no BFC: a trap if you used it for float containment
float: left | rightYesTakes the box out of flow and shrinks it to fit its content; text and inline content around it wrap
position: absolute | fixedYesTakes the box out of flow entirely and places it against its containing block (next topic)
display: inline-blockYesThe box sits on a line like a word and is sized to its content
flex item or grid itemYes, unless it is a flex, grid or table container itselfIts size and position come from the parent's flex or grid algorithm; a nested flex or grid container starts that kind of context instead
contain: layout | paint | content | strictYesAlso a containing block for absolute and fixed descendants and a stacking context; paint also clips. Lets the browser skip work outside the box
container-type: size | inline-sizeYesMakes the box a query container for @container rules, which applies containment
column-count or column-width (multicol), column-span: allYesSplits content into columns; a spanning element starts its own BFC
table cells and captionsYesLaid out by the table algorithm
the root element (html)YesThe initial block formatting context every page starts in
2

The three effects of a new BFC

Floats are the reason block formatting contexts exist in the form they do. A float belongs to the BFC it is laid out in, not to its parent element. An ordinary block that contains only a float has nothing in flow, so its automatic height ignores the float and the float hangs out of the bottom. Blocks that come later in the same BFC run straight underneath the float; only their line boxes get shorter so the words avoid it.

Opening a new BFC changes three things. First, it contains its floats: the spec gives a BFC root with automatic height enough room to reach the bottom of the floats inside it. Second, it avoids floats outside it: a BFC's own border box is placed beside a float in the surrounding context instead of running under it, so its text forms a clean column instead of wrapping around the corner. Third, margins stop at its edge: a child's top margin can no longer collapse through the parent and push the parent down (the collapsing rules themselves are in the box model topic).

The floated avatar in Slatework's activity panel

Ines's comment is one 20 px line plus padding, 36 px tall; the float is 40 px from a top 8 px down, so it ends 12 px below the comment. The next entry's first line is shortened to avoid it. In Theo's comment the paragraph runs under the avatar and only its first two lines are shortened.

No new context. Box layout “Activity panel”: 13 shapes. View: 352 × 272 from -16, -28. 1. “aside.activity” (frame) 320 × 228 at 0, 0 2. “div.comment: Ines” (rect) 288 × 36 at 16, 16 in aside.activity 3. “avatar” (rect) badge “float: left” 40 × 40 at 24, 24 orange in div.comment: Ines 4. “line: Ready for review” (rect) 224 × 20 at 72, 24 sand in div.comment: Ines 5. “div.event: Slatebot” (rect) 288 × 56 at 16, 52 in aside.activity 6. “line 1, pushed right” (rect) 224 × 20 at 72, 60 sand in div.event: Slatebot 7. “line 2” (rect) 272 × 20 at 24, 80 sand in div.event: Slatebot 8. “div.comment: Theo” (rect) 288 × 76 at 16, 108 in aside.activity 9. “p.body” (rect) 272 × 60 at 24, 116 blue in div.comment: Theo 10. “line 1” (rect) 224 × 20 at 72, 116 sand in p.body 11. “line 2” (rect) 224 × 20 at 72, 136 sand in p.body 12. “line 3, under the avatar” (rect) 272 × 20 at 24, 156 sand in p.body 13. “avatar” (rect) badge “float: left” 40 × 40 at 24, 116 orange in div.comment: Theo

The comment, before and after

<div class="comment">
  <img class="avatar" src="/u/ines.png" alt="" width="40" height="40">
  <p class="body"><b>Ines</b> Ready for review</p>
</div>
.avatar {
  float: left;
  margin-inline-end: 8px;
  border-radius: 50%;
}
.comment { padding: 8px; }
/* one-line comments are shorter than the avatar,
   so it hangs into the next entry */
.comment {
  display: flow-root; /* contains the float, no side effects */
  padding: 8px;
}
.comment .body {
  display: flow-root; /* sits beside the avatar, never under it */
}
3

Flex and grid items become blocks

A flex or grid container lays out its children with its own algorithm, so the children's outer display stops mattering. The browser blockifies them: an inline outer display is computed as block (inline-flex becomes flex, inline-grid becomes grid), and a run of loose text directly inside the container is wrapped in an anonymous item. Properties that only made sense in block or inline layout go quiet: float and clear do not take an item out of flow, and vertical-align does nothing to it.

Each item then lays out its own children in a fresh context. A plain item becomes a new block formatting context, which is why a Slatework card in a flex column contains its floats without any help. An item that is itself display flex or grid starts that kind of context instead. The container is just as sealed toward the outside: floats around a flex or grid container do not reach into it, and its margins never collapse with its items' margins.

What a child of a flex or grid container computes to

Written on the childUsed as an itemNote
display: inlinedisplay: blockA span or a link becomes a block-level item
display: inline-flexdisplay: flexStill a flex container for its own children
display: inline-griddisplay: gridStill a grid container for its own children
float: left(ignored)The item stays in flow and is placed by the container
vertical-align: middle(ignored)Use align-self or align-items instead
position: absoluteout of flowNot an item at all: it is placed against its containing block, though the container's alignment can set its static position
4

Intrinsic sizes and the min-width auto trap

Flex and grid size things from their content, so they need to ask each item two questions. How narrow can you get? That is the min-content size: the width when every soft wrap opportunity is taken, usually the longest word or unbreakable run. How wide would you like to be? That is the max-content size: the width with no wrapping at all. fit-content sits between them: as wide as the space allows, never narrower than min-content, never wider than max-content.

Here is the trap. In block layout min-width defaults to 0. On a flex item, along the main axis, min-width auto means something else: an automatic minimum equal to the item's content-based minimum, which in practice is its min-content size unless a smaller width is set. flex-shrink lets an item shrink, but never below that floor. A task title with spaces has a small min-content and shrinks happily. A file name joined by underscores, with no space or hyphen anywhere, has no soft wrap opportunity, so its min-content is the whole name; its item refuses to shrink, and the row overflows its card.

Three things lower the floor. min-width: 0 removes it, so the item shrinks to its share and the text inside can wrap or truncate. overflow hidden, auto or scroll makes the item a scroll container, and scroll containers get an automatic minimum of 0, but the item now clips (overflow: clip is not a scroll container, so it keeps the floor). overflow-wrap: anywhere lowers the min-content size itself by counting break opportunities inside the name; overflow-wrap: break-word wraps the same way at paint time but is ignored when min-content is computed, so on its own it does not fix a flex item. Grid has the same floor in another place: 1fr is shorthand for minmax(auto, 1fr), so a track grows to its widest item's minimum unless you write minmax(0, 1fr).

Min-content and max-content of three strings on a Slatework card

  • min-content
  • max-content
Min-content and max-content of three strings on a Slatework cardOnly the file link has a min-content wider than the 224 px attachment row, because a name joined by underscores has no soft wrap opportunity until overflow-wrap anywhere adds them.0100200300400500Task titleStatus chipFile linkFile link, overflow-wrap: anywhere52 px64 px504 px9 px232 px64 px504 px504 pxattachment row (224 px)Text in the cardWidth (px)Min-content and max-content of three strings on a Slatework cardOnly the file link has a min-content wider than the 224 px attachment row, because a name joined by underscores has no soft wrap opportunity until overflow-wrap anywhere adds them.0100200300400500Task titleStatus chipFile linkFile link, overfl…File link, overflow-wrap: anywhere52 px64 px504 px9 px232 px64 px504 px504 pxattachment row (224 px)Text in the cardWidth (px)
Measured widths are illustrative, for Slatework's 13 px UI font. The dashed line is the width an attachment row gets inside a 248 px card: the laptop layout, with the board's compact card padding of 12 px.
Data
Text in the cardmin-content (px)max-content (px)
Task title52232
Status chip6464
File link504504
File link, overflow-wrap: anywhere9504
  • attachment row (224 px): Width (px) = 224

One attachment row, 224 px wide, and four ways to fit the link

AttachmentRow6AttachmentRow
  1. icon, width 16, Icon, gaps, size (fixed)
  2. width 8, Icon, gaps, size (fixed)
  3. file link, width 504, Link held at its min-content, value 504 px
  4. width 8, Icon, gaps, size (fixed)
  5. 2.4 MB, width 44, Icon, gaps, size (fixed)
  • card content edge, cut at 224
  • 356 px spill past the card, from 224 to 580
  • Icon, gaps, size (fixed)
  • Link held at its min-content
  • Link shrunk to its share
Start

As it starts. 4 steps follow.

The row is display flex with gap 8 px: a 16 px icon and a 44 px size label, both flex: none, with the link (flex: 1 1 auto) between them. The link's text is the 66-character file name on the Review card, words joined by underscores with no space or hyphen, 504 px on one line. Step through the fixes.
5

contain: an explicit wall

Every trigger above opens a context as a side effect of something else. The contain property states the intent directly. contain: layout promises that nothing inside the box affects layout outside it and nothing outside affects layout inside, and the browser enforces the promise by making the box a new block formatting context, a containing block for absolute and fixed descendants, and a stacking context. contain: paint adds clipping to the box's bounds. contain: content is shorthand for layout, paint and style; strict adds size containment, which makes the box ignore its children when sizing itself, so it needs an explicit size.

The reason to reach for it is performance, not float containment: when a contained subtree changes, the browser knows the change cannot ripple outward, so it can relayout less. That is rendering-performance territory (containment and content-visibility on large lists are taught there). The thing to remember here is the bundle: contain: layout on a Slatework card would also capture the card's fixed-position children and start a new stacking context, which the next two topics show can move a menu or a toast in ways nobody intended.

What each containment value brings with it

.task-card {
  contain: layout;
  /* new BFC: floats and margins stay inside
     containing block for absolute AND fixed descendants
     new stacking context: z-index is scoped to the card */
}

.task-card--offscreen {
  contain: content; /* = layout paint style: also clips to the card */
}
Was this section helpful?

In practice.

Slatework's board bug takes two fixes at two levels, because two different contexts each put a content-sized floor under the same link. Then the habits that keep a layout like this from regressing, and how to say it in an interview.

The Slatework board, and the card that broke it

Four columns of cards. In CSS the board is a grid, each column a flex column, each card a flex item and therefore its own block formatting context. On a laptop with the activity panel open the board gets 1,040 px, and cards use the compact 12 px padding.

The board. Board: 5 items. Column “To do”: 1. Draft the onboarding email by Priya N. badges: Copy. 2. Audit empty states by Theo B. Column “Doing”: 1. Fix the login redirect loop on Safari by Ines R. badges: Bug. Column “Review”: 1. Q4 roadmap sign-off: “Atlas_Q4_roadmap_final_v7_approved_by_finance_and_legal_signed.pdf” by Marta K. badges: PDF. Column “Done”: 1. Ship the dark theme by Theo B. badges: Design.

  1. Grid track with an auto minimum2Board
  2. Card with the attachment row4TaskCard
  3. Flex column of cards3BoardColumn

The board blow-out, fixed in two layers

1fr is minmax(auto, 1fr). The Review card's minimum is 12 + 580 + 12 = 604 px, so its track starts at 604 and the other three split what is left: (992 - 604) / 3 ≈ 129 px each. Their task titles now wrap onto several short lines.

repeat(4, 1fr). Box layout “Board panel”: 14 shapes. View: 1184 × 272 from -16, -28. 1. “div.board” (frame) badge “repeat(4, 1fr)” 1040 × 220 at 0, 0 2. “To do” (rect) 129 × 196 at 0, 16 in div.board 3. “card” (rect) 129 × 72 at 0, 56 sand in To do 4. “Doing” (rect) 129 × 196 at 145, 16 in div.board 5. “card” (rect) 129 × 72 at 145, 56 sand in Doing 6. “Done” (rect) 129 × 196 at 910, 16 in div.board 7. “card” (rect) 129 × 72 at 910, 56 sand in Done 8. “Review” (rect) badge “604 px” 604 × 196 at 290, 16 blue in div.board 9. “card: Q4 roadmap sign-off” (rect) 604 × 120 at 290, 56 sand in Review 10. “attachment row” (rect) 580 × 24 at 302, 140 in card: Q4 roadmap sign-off 11. “icon” (rect) 16 × 24 at 302, 140 gray in attachment row 12. “a.file-link” (rect) 504 × 24 at 326, 140 orange in attachment row 13. “Atlas_Q4_roadmap_final_v7_approved_by_finance_and_legal_signed.pdf” (rect) 504 × 16 at 326, 144 yellow in a.file-link 14. “2.4 MB” (rect) 44 × 24 at 838, 140 gray in attachment row

The board and the attachment row, before and after

.board {
  display: grid;
  grid-template-columns: repeat(4, 1fr); /* = minmax(auto, 1fr) */
  gap: 16px;
}
.attachment {
  display: flex;
  gap: 8px;
}
.attachment .icon,
.attachment .size { flex: none; } /* never squeezed */
.attachment .file-link {
  flex: 1 1 auto;          /* min-width: auto: never below min-content */
  overflow-wrap: break-word; /* no help: ignored for min-content */
}
.board {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)); /* tracks ignore content */
  gap: 16px;
}
.attachment {
  display: flex;
  gap: 8px;
}
.attachment .icon,
.attachment .size { flex: none; } /* never squeezed */
.attachment .file-link {
  flex: 1 1 auto;
  min-width: 0;            /* lift the flex floor */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis; /* full name in the title attribute */
}

Why it took two fixes, and the habits that prevent the third

The floor came from two contexts, so it had to be removed twice. The flex row would not shrink the link below its min-content, so the row's own min-content was the full 580 px. The grid then asked the card for its minimum, got 604 px, and, because 1fr has an auto minimum, widened the Review track to match. Fixing only the grid leaves the row spilling out of a correct-width card; fixing only the flex item leaves the track wide, because the card's min-content contribution is still computed from the unbroken name.

Slatework now follows three rules. Every 1fr in a layout that holds user content is written minmax(0, 1fr). Every flex item that holds user text (titles, names, file names, URLs) gets min-width: 0 and a decision about what happens at the edge: wrap, or truncate with the full text in a title attribute or tooltip. Every component that must contain its floats or its children's margins uses display: flow-root, never overflow: hidden, because hidden also clips.

The card header shows the same rule in miniature. It is a flex row: a 24 px avatar, the title with flex: 1 and min-width: 0, and a 52 px due-date chip with flex: none so it can never be squeezed. A long title wraps inside its share instead of pushing the chip out of the card. The More menu is a different story: its button sits in the card body, which is a BFC because overflow is hidden, and that same overflow clips the menu. That is the next topic's bug.

Slatework's layout map

Elementdisplay and the key propertiesContext it runs for its childrenWhy this one
.appgrid; areas top / side board activityGridTwo dimensions at once: a full-width top bar over three side-by-side regions
.boardgrid; repeat(4, minmax(0, 1fr))GridColumns must line up and stay equal whatever the cards hold
.columnflex; flex-direction: column; gapFlexA single stack of cards with even spacing; no margin collapsing to reason about
.task-cardblock (a flex item)Block (new BFC)Being a flex item already seals it: floats and margins stay inside
.card-headerflex; title min-width: 0FlexOne row: fixed avatar and due chip, a title that takes the rest and wraps
.card-bodyblock; overflow: hiddenBlock (new BFC)Clips a long description to six lines; also clips the More menu, see the next topic
.attachmentflex; link min-width: 0FlexOne row per file: icon, truncated name, size
.commentflow-rootBlock (new BFC)Contains the floated avatar with no clipping
.comment .bodyflow-rootBlock (new BFC)Sits beside the avatar instead of wrapping under it

Saying it in an interview

Q1
PromptYou are designing a kanban board's UI. The interviewer asks how you would lay out the columns and cards.
Grid for the board, because the columns are a two-dimensional structure that should stay aligned and equal: repeat(n, minmax(0, 1fr)), or a fixed column width inside a horizontally scrolling panel when n is large. Flex for each column's stack and for rows inside a card. Then name the one trap: user text in flex items and fr tracks has a content-sized floor, so set min-width: 0 and minmax(0, 1fr) and decide between wrapping and truncation.
Q2
Follow-upA user pastes a very long unbroken string into a card title and the whole board breaks. What happened?
The title's min-content became the whole string. As a flex item its automatic minimum is that min-content, so it would not shrink; as part of a grid item with a 1fr track, it widened the track. Fix both floors, and add overflow-wrap: anywhere for titles you would rather wrap than truncate.
Q3
Follow-upWhy not put overflow: hidden on the card to keep everything inside?
It would contain floats and stop overflow from showing, but it also clips: any dropdown, tooltip or focus ring drawn inside the card and extending past it disappears. flow-root contains floats without clipping; min-width: 0 fixes overflow at the source. Reserve overflow: hidden for content you actually want cut off.
Q4
Where it fitsHow much of this should an interview answer contain?
A sentence or two in the component and layout part, tied to the screen you are drawing: which regions are grid, which rows are flex, and how long user content is handled. Interviewers listen for the robustness question (what happens with long names, many items, narrow screens), not for a recital of the BFC list.

Where this decides the layout in the system flows

System flowThe formatting-context question in it
pinterest/masonry-home-feedWhy a CSS grid of rows cannot pack unequal pins without gaps, and why the feed places pins itself in columns from known image ratios
notion/database-viewsA table view whose cells must truncate inside widths the user sets instead of widening the column, and a board view built like Slatework's
gmail/inbox-listA one-line row of sender, subject, snippet and date: a flex row where the snippet needs min-width: 0 to truncate and the date must never shrink
netflix/home-rowsEach row is a single horizontal flex or grid track of fixed-width tiles inside a scroll container
whatsapp/chat-threadMessage bubbles sized to fit-content with a maximum width, and long links in them that must wrap with overflow-wrap: anywhere
Was this section helpful?

Trade-offs.

Three choices come up every time you build a screen like Slatework's: which context runs a region, how to seal a block, and how to let content shrink.

01
Laying out the board's columns
Chosen:Grid: repeat(4, minmax(0, 1fr))
  • Pro:Columns line up and stay equal whatever the cards hold
  • Pro:Gaps, column headers and an empty column all follow the same tracks
  • Pro:One rule on the container; nothing on the children
Downside we accept:
  • Con:Needs minmax(0, …) to stop content widening a track
  • Con:With many columns, fixed widths in a scrolling panel work better than fr shares
Ruled out:Flex row with flex: 1 on each column

Same content floor (min-width auto) on every column; Each line is sized on its own, so nothing aligns across rows if the board ever wraps

Ruled out:Floats or inline-block columns

Whitespace gaps, clearfix hacks, no equal heights; Nothing modern needs it

02
Containing a float, or stopping margins at a component's edge
Chosen:display: flow-root
  • Pro:Opens a BFC and does nothing else
  • Pro:Says what it means in code review
Downside we accept:
  • Con:Changes the inner display, so it cannot be combined with flex or grid on the same box (they already seal)
Ruled out:overflow: hidden (or auto)

Clips: dropdowns, tooltips and focus rings that extend past the box vanish; auto can add a scrollbar the design never had; Turns the box into a scroll container, which changes sticky positioning inside it

Ruled out:contain: layout (or content)

Also a containing block for fixed descendants and a stacking context; content adds paint containment, which clips

Ruled out:Clearfix pseudo-element (clear both on ::after)

Contains floats only: the box still runs under floats outside it; A workaround for something flow-root now states directly

03
Letting a flex item with user text shrink
Chosen:min-width: 0, then wrap or ellipsis
  • Pro:Removes the floor exactly where it hurts
  • Pro:You choose what happens at the edge
Downside we accept:
  • Con:Needs a decision per item: truncation hides text, so expose the full value (title attribute, tooltip, detail view)
Ruled out:overflow-wrap: anywhere

Breaks inside a word wherever it would overflow, which makes names and URLs harder to read; Changes min-content for every ancestor's sizing, sometimes more than intended

Ruled out:overflow: hidden on the item

Clips focus rings and popups drawn by anything inside the item; Fixes the floor by accident, so the next refactor can bring it back

The cost that shows up in the next topic

Slatework's card body uses overflow: hidden on purpose, to cut a long description off after six lines. That made the body a new BFC, which is harmless, and a clipping box, which is not: the More menu opens from a button inside the body, and anything inside a clipping box is cut at its edge unless its containing block lies outside it. Formatting contexts explain why the body is sealed; positioning and containing blocks explain which boxes escape the clip and how to move the menu out of it.

This topic
What opens a block formatting context and its three effects
Blockified flex and grid items
min-content, max-content and the min-width: auto floor
Containment as an explicit wall
Elsewhere
The box model and the rules of margin collapsingThe box model and normal flow
Containing blocks, clipping of positioned boxes, sticky and fixedPositioning and containing blocks
z-index, stacking contexts and the top layerStacking contexts and the top layer
Containment and content-visibility for speedRendering less
Grid template syntax in depth, masonry placementPinterest-like masonry feed
Was this section helpful?
Builds on this
Positioning and containing blocks
Read next