The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Block flow container | .panel { display: block flow; } | View examples |
| Inline formatting root | .badge { display: inline flow-root; } | View examples |
| Compatible inline block | .badge { display: inline-block; } | View examples |
| Explicit block formatting context | .group { display: flow-root; } | View examples |
| Contain floated media | .card {
display: flow-root;
} .card img { float: inline-start;;
} | View examples |
| Stop child margin collapse | .section { display: flow-root; } | View examples |
| Remove only the principal box | .wrapper { display: contents; } | View examples |
| Expose children to a grid | .grid-group { display: contents; } | View examples |
| Layer a structural fallback | .group {
display: block;
} @supports (display:
contents) { .group { display: contents; };
} | View examples |
| Remove subtree from layout | .is-removed { display: none; } | View examples |
| Use semantic hidden state | [hidden] { display: none; } | View examples |
| Keep text for assistive tech | .sr-only {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
} | View examples |
| Generate a marker box | .step {
display: list-item;
list-style-position: inside;
} | View examples |
| Use table-internal display | .cell { display: table-cell; vertical-align: middle; } | View examples |
| Expect flex item blockification | .row { display: flex; } .row > span { display: inline; } | View examples |
| Inspect computed display | getComputedStyle(node).display | View examples |
| Keep focus on a generated box | .wrapper:focus-visible {
outline: 3px solid CanvasText;
} | View examples |
| Restore boxes for print | @media print { .screen-contents { display: block; } } | View examples |
The display property controls whether an element generates a box, how that box participates in its parent, and which formatting model lays out its children. This guide separates those decisions, shows why flow-root is the explicit block-formatting-context tool, and treats contents as a narrowly scoped box-tree operation whose accessibility behavior still demands real-device testing.
Step by step
Detailed examples
Separate outer participation from inner layout
Two-keyword display syntax makes the model explicit: the outer value says how the principal box participates in its parent, while the inner value selects flow, flow-root, flex, grid, table, or ruby layout for children. Legacy values such as inline-block map to defined pairs and remain useful fallbacks. Replaced elements and layout-internal roles have additional rules, so changing display alone does not turn arbitrary markup into a semantically correct table or control.
.status {
display: inline-block;
display: inline flow-root;
padding-inline: 0.6rem;
} Establish a block formatting context deliberately
flow-root generates a block-level block container and always establishes a new block formatting context. It encloses floats, separates its contents from outside floats, and prevents block margins from collapsing through its boundary. Unlike overflow: hidden, it does not clip intentional shadows, focus rings, or positioned decoration. A BFC is not containment: it does not provide the performance or sizing guarantees of contain.
<article class="card">
<img src="avatar.png" alt="Samira Chen">
<h2>Samira Chen</h2>
<p>Maintains the release checklist.</p>
</article> .card { display: flow-root; }
.card img { float: inline-start; margin-inline-end: 1rem; inline-size: 5rem; } Remove a box, not your document structure
display: contents normally prevents the element itself from generating boxes and promotes its child boxes for layout. The DOM node, selectors, inheritance, and event propagation still exist. Pseudo-elements can generate boxes as children. Unusual elements have special rules, and historical accessibility implementations have incorrectly removed semantics, so do not use contents casually on meaningful landmarks, lists, tables, labels, or interactive elements. Test the browser and assistive-technology combinations you support.
.dashboard { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.decorative-group { display: contents; }
@supports not (display: contents) { .decorative-group { grid-column: 1 / -1; } } Choose absence, invisibility, or clipping intentionally
display:none suppresses the whole subtree from layout and, in ordinary cases, from accessibility APIs; it is appropriate for content that is genuinely inactive. visibility:hidden preserves layout space but also makes the subtree non-interactive. opacity:0 merely makes pixels transparent and can leave focusable controls active. A visually-hidden utility uses clipping when text must remain available as an accessible name; verify it at high zoom and in forced-colors mode.
[hidden] { display: none !important; }
.sr-only {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
white-space: nowrap;
clip-path: inset(50%);
} Respect layout-internal roles and semantics
list-item adds a marker box and can be combined with an outer and inner display type. Table-internal values participate in fix-up rules that may generate anonymous wrapper boxes. They describe visual formatting, not document relationships: a div displayed as table-cell is not exposed as a table cell to assistive technology. Start with ol, ul, table, th, and td when those meanings apply, then use CSS to control their presentation.
.steps { padding-inline-start: 1.5rem; }
.steps > li { display: list-item; }
.steps > li::marker { color: #1d4ed8; font-weight: 800; } Account for blockification and generated boxes
Flex and grid containers blockify the outer display type of in-flow children; absolutely positioned and floated boxes are blockified too. This affects computed values without changing DOM semantics. display also controls whether ::before and ::after can generate boxes. Inspect computed styles when debugging, but reason about the formatting context and box tree rather than expecting the authored token to survive unchanged.
const item = document.querySelector(".row > span");
console.log(getComputedStyle(item).display); Test focus, reading order, zoom, and print
CSS visual reordering never changes sequential focus or reading order. Keep DOM order meaningful, retain native interactive elements, and never place keyboard focus on an element whose principal box has been removed by contents. Test at 400% zoom, with keyboard-only navigation, screen readers, forced colors, and printed output. Use @supports only to detect parsing; it cannot certify correct accessibility-tree behavior.
:focus-visible { outline: 3px solid CanvasText; outline-offset: 3px; }
@media print { .screen-contents { display: block; } } Local code tester
Compare flow-root and contents
Toggle the checkboxes to contain a float and flatten only the decorative grid group while the document order stays unchanged.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- CSS Working GroupCSS Display Module Level 3drafts.csswg.org
- CSS Working GroupCSS Display Module Level 4drafts.csswg.org
- World Wide Web ConsortiumCSS 2.2: Visual formatting modelw3.org
- Web Accessibility InitiativeUnderstanding Success Criterion 1.3.1: Info and Relationshipsw3.org
- MDN Web Docsdisplaydeveloper.mozilla.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



