CSStable display values

table display values

CSS lets any element adopt the internal layout behavior of an HTML table — without actually being a <table> — via the table family of display values. This decouples table-like layout (columns that size to their widest content, cells that stretch to a shared row height) from the semantics of tabular markup.

The Table Display Values

Value

Mimics

display: table

&lt;table&gt;

display: table-row

&lt;tr&gt;

display: table-cell

&lt;td&gt; / &lt;th&gt;

display: table-row-group

&lt;tbody&gt;

display: table-header-group

&lt;thead&gt;

display: table-footer-group

&lt;tfoot&gt;

display: table-column / table-column-group

&lt;col&gt; / &lt;colgroup&gt;

display: table-caption

&lt;caption&gt;

CSS
.layout {
  display: table;
  width: 100%;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  padding: 12px;
  vertical-align: middle; /* table cells support vertical-align! */
  border: 1px solid #ddd;
}

HTML
<div class="layout">
  <div class="row">
    <div class="cell">Sidebar</div>
    <div class="cell">Main content, possibly a different height</div>
  </div>
</div>
The Historical Use Case: Vertical Centering
Why this pattern exists
Before Flexbox and Grid existed, vertically centering content inside a box of unknown height was notoriously awkward. `table-cell` was one of the few display modes that natively supported `vertical-align: middle`, so developers used it purely as a centering hack — with no actual tabular data involved.

CSS
/* The pre-Flexbox vertical centering hack */
.center-wrapper {
  display: table;
  width: 100%;
  height: 300px;
}

.center-content {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

Today, the same result takes one line with Flexbox: display: flex; align-items: center; justify-content: center; — so this specific use case is essentially obsolete.

Where Table Display Still Earns Its Place

Table display values are rarely the first choice in 2024+ CSS, but a few quirks of genuine table layout have no exact equivalent in Flexbox or Grid, which makes display: table occasionally the simplest tool:

  • Automatic equal-height rows across independently-sized cells, with no explicit height set anywhere — table layout does this natively.

  • Column widths that automatically size to their content and stay consistent down every row, similar to table-layout: auto behavior, without writing grid-template-columns tracks by hand.

  • Rendering data that genuinely is tabular but you want to avoid &lt;table&gt; markup for a specific styling reason — the display values give you table rendering with div-based markup.

CSS
/* Equal-height columns with zero explicit heights */
.columns {
  display: table;
  width: 100%;
  border-spacing: 16px; /* like table's cellspacing */
}

.column {
  display: table-cell;
  background: #f6f6f6;
  padding: 16px;
  /* Every .column in this .columns row will match
     the tallest one automatically. */
}
Prefer Grid or Flexbox first
For new layout work, reach for Flexbox or Grid before `display: table` — they're more flexible, better supported by dev tooling, and don't carry table-layout's row/column coupling. Keep `table-*` display values in your back pocket for the rare case where automatic equal-height rows are exactly what you need and a Grid track definition would be more code.