The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Fill the containing block | .data-table { inline-size: 100%; } | View examples |
| Move the caption | .data-table caption { caption-side: bottom; } | View examples |
| Align cell content | .data-table :is(th, td) {
text-align: start;
vertical-align: top;
} | View examples |
| Use content-aware layout | .content-sized { table-layout: auto; } | View examples |
| Use fixed table layout | .predictable { inline-size: 100%; table-layout: fixed; } | View examples |
| Size a column | .predictable col:first-child { inline-size: 12rem; } | View examples |
| Break unspaced values | .predictable :is(th, td) { overflow-wrap: anywhere; } | View examples |
| Use separated borders | .spaced {
border-collapse: separate;
border-spacing: 0.5rem 0.75rem;
} | View examples |
| Hide empty cell paint | .spaced { empty-cells: hide; } | View examples |
| Round separate cells | .spaced :is(th, td) {
border: 1px solid #cbd5e1;
border-radius: 0.4rem;
} | View examples |
| Collapse adjacent borders | .ruled { border-collapse: collapse; } | View examples |
| Draw compact rules | .ruled :is(th, td) {
border: 1px solid #94a3b8;
padding: 0.65rem;
} | View examples |
| Contain horizontal overflow | .table-scroll {
max-inline-size: 100%;
overflow-x: auto;
} | View examples |
| Preserve useful columns | .table-scroll > table { min-inline-size: 42rem; } | View examples |
| Request intact printed rows | @media print { .data-table tr { break-inside: avoid; } } | View examples |
Table CSS is most predictable when semantic HTML establishes the grid and a wrapper manages narrow viewports. Choose auto layout when content should influence column measures; choose fixed layout with a definite table width when explicit columns and the first row should determine the grid. Collapsed borders produce a compact ruled surface, while separated borders support spacing, rounded cells, and empty-cell control. Keep captions, header associations, and source order in HTML because visual styling cannot replace them.
Step by step
Detailed examples
Let HTML define the table before CSS styles the grid
Use table, caption, thead, tbody, tr, th, and td according to the data relationships. A caption names or explains the whole table, while scope on straightforward row and column headers makes associations explicit. CSS can move a caption visually and align cell contents, but it cannot repair missing relationships or a misleading DOM order. Logical inline sizing and text-align: start adapt the same rules to different writing directions.
<table class="data-table">
<caption>Quarterly service reliability</caption>
<thead>
<tr><th scope="col">Service</th><th scope="col">Uptime</th><th scope="col">Incidents</th></tr>
</thead>
<tbody>
<tr><th scope="row">Payments</th><td>99.98%</td><td>2</td></tr>
<tr><th scope="row">Search</th><td>99.95%</td><td>4</td></tr>
</tbody>
</table> .data-table { inline-size: 100%; }
.data-table caption {
caption-side: bottom;
padding-block: 0.75rem;
text-align: start;
color: #475569;
}
.data-table :is(th, td) {
text-align: start;
vertical-align: top;
} Note: Do not replace the table's internal display roles with grid or flex solely to create a visual layout.
Choose auto or fixed sizing intentionally
Auto layout measures contributions from table content and is appropriate when unknown data should influence column widths. Fixed layout applies only when the table also has a definite width; it ignores later cell content for width computation and uses explicit column measures, first-row cells, then remaining space. That makes results more predictable and can allow earlier layout as rows arrive, but it does not make rendering cost-free. Use col elements for shared track intent, and define wrapping for long tokens that cannot fit.
<table class="predictable">
<colgroup><col class="service-column"><col><col></colgroup>
<thead><tr><th>Service</th><th>Owner</th><th>Endpoint</th></tr></thead>
<tbody><tr><td>Payments</td><td>Commerce</td><td>https://api.example.test/payments/health</td></tr></tbody>
</table> .predictable {
inline-size: 100%;
table-layout: fixed;
}
.predictable .service-column { inline-size: 12rem; }
.predictable :is(th, td) { overflow-wrap: anywhere; }
.content-sized { table-layout: auto; } Note: Test with translated labels and worst-case production values; a fixed grid can clip or wrap content that its chosen tracks cannot accommodate.
Use separated borders for gaps, rounded cells, and empty-cell control
border-collapse: separate keeps every cell border independent. border-spacing accepts one distance for both axes or horizontal and vertical distances in that order; percentages and negative values are not allowed. empty-cells: hide suppresses the border and background painting of empty cells only in separated mode. This model is the dependable choice for card-like cells and rounded corners because collapsed mode ignores table border spacing and border radii. Use padding inside cells for content breathing room regardless of model.
.spaced {
inline-size: 100%;
border-collapse: separate;
border-spacing: 0.5rem 0.75rem;
empty-cells: hide;
}
.spaced :is(th, td) {
border: 1px solid #cbd5e1;
border-radius: 0.4rem;
padding: 0.65rem;
background: #fff;
} Build compact ruled tables with collapsed borders
Collapsed mode merges adjacent table and cell border candidates, then conflict resolution chooses the winning style, width, and color for each edge. border-spacing, table padding, and table or cell border-radius do not provide their separated-mode effects, so use cell padding for spacing. Complex mixtures of row, column, and cell borders have historically exposed interoperability differences, and the CSS Tables Level 3 collapsed-border algorithm continues to evolve. A uniform cell rule is easier to maintain and test than relying on intricate conflicts.
.ruled {
inline-size: 100%;
border-collapse: collapse;
}
.ruled :is(th, td) {
border: 1px solid #94a3b8;
padding: 0.65rem;
}
.ruled thead { background: #e2e8f0; }
.ruled tbody tr:nth-child(even) { background: #f8fafc; } Note: Do not expect border-spacing or rounded cell corners to work in collapsed mode; switch models when those effects are requirements.
Contain narrow-screen overflow without dismantling table semantics
For dense data, horizontal scrolling often preserves comparisons better than converting cells into pseudo-labeled cards. Put overflow on a labeled wrapper and leave the table's native display roles intact. tabindex="0" provides a keyboard entry point where a scroll area would otherwise be unreachable, though focus behavior is evolving and should be tested with target browsers and assistive technologies. A modest minimum table width protects columns, while a visible focus style identifies the active scroll region. In print, request intact rows and repeated header groups, but treat fragmentation controls as best-effort because paged-media implementations vary.
<h2 id="reliability-title">Service reliability</h2>
<div class="table-scroll" role="region" aria-labelledby="reliability-title" tabindex="0">
<table class="data-table ruled">
<thead><tr><th scope="col">Service</th><th scope="col">Owner</th><th scope="col">Uptime</th></tr></thead>
<tbody><tr><th scope="row">Payments</th><td>Commerce</td><td>99.98%</td></tr></tbody>
</table>
</div> .table-scroll {
max-inline-size: 100%;
overflow-x: auto;
}
.table-scroll:focus-visible { outline: 3px solid #2563eb; outline-offset: 3px; }
.table-scroll > table { min-inline-size: 42rem; }
@media print {
.table-scroll { overflow: visible; }
.table-scroll > table { min-inline-size: 0; }
.data-table thead { display: table-header-group; }
.data-table tr { break-inside: avoid; }
} Note: Avoid hiding columns that users need to understand a row; prioritize data or provide an alternate summary when every column cannot fit.
Local code tester
Compare fixed layout and collapsed borders
Resize the preview and edit column measures, wrapping, and border rules on a semantic data table.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



