The pseudo-semantic table
Flexbox and CSS Grid invited a naive expectation: that properties like align-self and justify-content would apply to block and inline elements generally — tables, lists, fixed elements — with the same syntax and outcomes regardless of the underlying reference boxes. They don't. But a hybrid can be built by stripping an HTML table of its layout behavior and reassembling it with CSS Grid: markup that reads like a table but lays out like a grid. Variants of the technique have already been used to make tables responsive.
Straight tables have real advantages, and this is not an argument against them. They give a clean structure that browsers understand and translate for assistive technology, and they offer a <caption> element. CSS Grid, meanwhile, remains necessary where intrinsic responsiveness, source order independence and positioning matter. HTML tables should still display actual tabular data. The question is narrower: whether the table's presentational flavor can be reused as markup.
Why table markup is worth keeping
Technically <table> is semantic rather than presentational like a <div>; browsers and authors share a common meaning for it. Call that meaning pseudo-semantic. Reading <th> signals a heading followed by data:
<div class="product-title">Wall Calendar</div>
Headings and <strong> carry title semantics but not the relationship between <th> and <td>, and <dl> terms are better reserved for textual structures such as glossaries than for layouts.
A table used purely as a pseudo-semantic markup skin raises a fair objection:
/* 🧟 */
table {
display: grid;
}
Swap test: divs versus cells
Compare a generic-div version:
<article class="card">
<div class="card-number">
<strong>CARD NUMBER</strong>
<span>1234 5678 9123 4567</span>
</div>
<div class="card-bank">
<strong>CROWN <br>ATLANTIC <br>BANK</strong>
</div>
<div class="card-name">
<strong>CARD HOLDER</strong>
<span>JANE DOE</span>
</div>
<!-- more -->
</article>
with the table-based version:
<table class="card">
<tr class="card-number">
<th>CARD NUMBER</th>
<td>1234 5678 9123 4567</td>
</tr>
<tr class="card-bank">
<th>CROWN <br>ATLANTIC <br>BANK</th>
</tr>
<tr class="card-name">
<th>CARD HOLDER</th>
<td>JANE DOE</td>
</tr>
<!-- more -->
</table>
The corresponding CSS for the first, along with its result:
.card {
display: grid;
grid-template-columns: auto auto 1fr;
gap: 2lh;
}
and the revised style for the table markup:
.card {
display: grid;
grid-template-columns: auto auto 1fr;
gap: 2lh;
/* Soul stripping */
tbody {
/* Bypass tbody in the layout */
display: contents;
}
tr, tr > * {
/* Avoid table-row and table-cell styles */
display: block;
}
}
The latter is easier to scan than a handful of generic divs, while still being laid out with CSS Grid. No browser has rejected the hybrid so far, and VoiceOver and keyboard navigation behave as they would with a real table.
We're encouraged to keep content and presentation separate, and this does exactly that without affecting the table's semantics, such as its role.
Perhaps it should affect them — that is the understandable discomfort. The construction looks gross and runs against the grain. But CSS is capable of bending plenty of other HTML elements the same way.



