Learn how to set predictable HTML table column widths with CSS, colgroup, table-layout, selectors, and overflow handling.
By Neha ImranPublished 2022-10-06Updated 2026-09-17
On this page
Use CSS to set the width of an HTML table and its columns. For a maintainable table, define column widths with
and use table-layout: fixed when the table must follow those proportions. The browser can still adjust a column when content does not fit, so the examples below also show how to handle that boundary.
Set column widths with CSS
The old width attribute on
or
is obsolete HTML. Browsers may still parse legacy markup, but new code should put presentation rules in CSS. Percentages are relative to the table’s used width, so the table itself needs an available width from its parent.
For a small, one-off table, an inline declaration such as <th style="width: 15%">ID</th> is enough. In a reusable component, prefer a stylesheet or a <colgroup> so the rule applies to the whole column, including its data cells:
The three percentages add up to 100%, so the table has a clear initial allocation: Name is wider than ID and Age. table-layout: fixed makes sizing depend primarily on the table width, explicit column widths, and the first row rather than on the longest cell in every row. overflow-wrap: anywhere allows an unusually long value to wrap instead of forcing the table wider.
The <colgroup> must occur before the table’s row groups. A <col> represents a column, not a visible cell, and it has no content of its own. Use span on a <col> when consecutive columns share one rule. This approach also keeps the HTML semantic: use <th> for headings and scope="col" so assistive technology can associate headings with their cells.
Choose between classes and :nth-child()
You can set widths on the first row with selectors such as .people th:nth-child(1) { width: 15%; }, .people th:nth-child(2) { width: 70%; }, and .people th:nth-child(3) { width: 15%; }. This preserves the original class-based and :nth-child() techniques without adding a class to every header. Classes are clearer when column meaning matters; :nth-child() is convenient for a stable, simple column order.
Do not rely on :nth-child() when rows contain colspan, when header rows have a different structure, or when columns can be reordered. In those cases, <colgroup> or named classes make the intended column mapping explicit. If only some widths are specified, the browser distributes the remaining space; do not assume an unspecified column will always receive an exact percentage under automatic layout.
Handle content that does not fit
Fixed layout does not make a narrow column large enough for every possible value. A long unbroken URL or identifier can overflow if it cannot wrap. The following boundary keeps the width rule but makes the cell scroll horizontally instead of changing the page layout:
For ordinary prose, wrapping is usually preferable to horizontal scrolling. Test the table with realistic content and at narrow viewport widths. Widths are hints interpreted by the table layout algorithm, not a guarantee that every cell will remain at an exact pixel size.