HTML Colgroup Tag Explained: How to Control Table Column Width and Style with col

By Pramod Behera · Updated: September 14, 2026 · 20 min read

HTML TUTORIALS – HTML Table Colgroup Tag – Introduction

HTML Table Colgroup Tag -

✅ What is <colgroup>Syntax?- This is used to group one or more columns in a table for styling or structural purposes. It's especially useful when you want to apply styles (like width or background color etc) to entire columns:-

Trulli
HTML colgroup tag structure inside a table
Trulli
HTML col tag styling individual columns

Why Style Columns Instead of Cells?

Every table styling technique covered in the earlier tutorial in this series borders, padding, zebra stripes, hover states targets rows and individual cells. But sometimes the thing you actually want to style is an entire vertical column: maybe the "Price" column across every row should always be a fixed 100px wide, or the "Status" column should always carry a light background tint regardless of how many rows the table ends up having. Doing that with per-cell CSS means repeating the same class or inline style on every single <td> in that column, which is tedious and easy to forget when a new row gets added later. <colgroup> and <col> solve this by letting you define a column's width or background once, in one place near the top of the table, and have it apply automatically down every row.

✅ Example 1: Set Column Widths-👇

ExampleCopy Code
<table border="1">
  <colgroup>
    <col style="width: 100px;">
    <col style="width: 200px;">
  </colgroup>
  <tr>
    <th>Name</th>
    <th>City</th>
  </tr>
  <tr>
    <td>Alice</td>
    <td>New York</td>
  </tr>
</table>
NameCity
PramodPune

The two <col> elements above set fixed pixel widths for the "Name" and "City" columns before a single row is even declared. Every cell that later falls into the first column position inherits the 100px width, and every cell in the second column position inherits 200px, no matter how many rows the table eventually contains.

✅ Example 2: Style Column Backgrounds-👇

ExampleCopy Code
<table border="1">
  <colgroup>
    <col style="background-color: lightblue;">
    <col style="background-color: lightyellow;">
  </colgroup>
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Ball</td>
    <td>$3.50</td>
  </tr>
</table>
ProductPrice
Ball$3.50

Here, the entire "Product" column is tinted light blue and the entire "Price" column is tinted light yellow, giving readers an instant visual split between the two kinds of information without adding a single class to any <td> or <th> in the table body.

✅ Example 3: Span Multiple Columns-👇

ExampleCopy Code
<table border="1">
  <colgroup>
    <col span="2" style="background-color: #eee;">
    <col style="background-color: #cfc;">
  </colgroup>
  <tr>
    <th>First</th>
    <th>Last</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>Pramod</td>
    <td>Behera</td>
    <td>IND</td>
  </tr>
</table>
FirstLastCountry
PramodBeheraIND

The first <col> here uses span="2" to apply its light gray background to both the "First" and "Last" columns at once with a single element, while a separate <col> gives the "Country" column its own distinct green tint.

✅ Example 4: — With Empty Tags for Control-👇

ExampleCopy Code
<table border="1">
  <colgroup>
    <col>
    <col style="background-color: #fdd;">
    <col>
  </colgroup>
  <tr>
    <th>Item</th>
    <th>Qty</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Laptop</td>
    <td>5</td>
    <td>$300</td>
  </tr>
</table>
ItemQtyPrice
Laptop5$300

This example demonstrates a subtle but important rule: even columns you don't want to style still need a placeholder <col> element in the sequence, so the browser correctly counts positions and applies the pink background only to the middle "Qty" column rather than shifting the styling onto the wrong column.

Colgroup and col Syntax Rules

RuleDetails
PlacementMust appear immediately after the opening <table> tag, before caption, thead, tbody, or any tr
Closing tag<colgroup> requires a closing tag; <col> is a void, self-closing element like <img>
Order mattersEach col corresponds to a column position left to right, matching the order columns appear in the table rows
Empty placeholdersAn unstyled column still needs a bare <col> to preserve correct positional counting, as shown in Example 4
One colgroup per tableA table typically uses a single colgroup, though multiple are technically permitted for grouped sections

Colgroup vs col: What's the Difference?

Aspect<colgroup><col>
RoleContainer that groups columns togetherDefines properties for one or more specific columns
Tag typeRequires opening and closing tagsVoid, self-closing element
Where it livesDirectly inside <table>Directly inside <colgroup>
Can it style directly?Rarely used to style directly; mainly a wrapperCarries the actual style, width, or span attribute

What CSS Properties Actually Work on Columns

Not every CSS property behaves as expected on a <col> element, since columns aren't real boxes in the same sense that cells are — a column is more like a shared styling hint applied across a vertical slice of the table.

PropertyWorks Reliably?
widthYes — the primary, most reliable use of col
background-colorYes, in all modern browsers
visibility: collapseYes — hides an entire column cleanly
borderInconsistent across browsers; apply borders to td/th instead
paddingNot supported on columns; apply to td/th instead
font/text propertiesNot supported on columns; apply to td/th instead

Understanding the span Attribute

Example 3 above demonstrates span="2", which is the key to avoiding repetitive markup when several consecutive columns should share identical styling. Without span, achieving the same result would require writing out two nearly identical <col> elements back to back:

ExampleCopy Code
<!-- Without span -->
<col style="background-color: #eee;">
<col style="background-color: #eee;">

<!-- With span (equivalent, shorter) -->
<col span="2" style="background-color: #eee;">

Both approaches produce an identical visual result, but the span version is shorter and easier to update if the shared style ever needs to change in one place.

🔍 Tag Breakdown-

-) Table Tag Breakdown -

TagPurpose
<table>Defines the table
<tr>Table row
<th>Table header (bold + centered by default)
<td>Table data (cell content)
<caption>Defines a table caption
<colgroup>Specifies a group of one or more columns in a table for formatting
<col>Specifies column properties for each column within a colgroup element
<thead>Groups the header content in a table
<tbody>Groups the body content in a table

Real-World Use Cases for Colgroup

ScenarioHow Colgroup Helps
Financial report with a wide "Description" column and narrow "Amount" columnsSet fixed widths once instead of on every row's cells
Comparison chart highlighting one "Recommended" plan columnGive that single column a distinct background tint across all rows
Spreadsheet-style data export rendered as HTMLQuickly hide an entire column with visibility: collapse without deleting data
Timetable where the first "Time" column should always stay narrowLock its width regardless of how long other column content grows

Browser Support and Limitations

Both <colgroup> and <col> have been part of HTML since its earliest table-related specifications and are supported in every modern browser, including Chrome, Firefox, Safari, and Edge. The main limitation isn't compatibility, but scope: a column, unlike a row or a cell, isn't a real rendered box, so only a small handful of CSS properties, chiefly width, background-color, and visibility, reliably apply. Anything involving text formatting, padding, or most border styling should still be handled directly on the <td> or <th> elements instead.

Alternatives: nth-child vs colgroup

A common question is whether td:nth-child() selectors in CSS could achieve the same column-styling result without <colgroup> at all.

ApproachBest For
<colgroup> / <col>Column width and simple background styling, defined once near the table markup
td:nth-child(n) in CSSFull styling flexibility (borders, padding, fonts) defined in an external stylesheet

In practice, many developers combine both: <colgroup> for setting widths directly in the markup where they're easy to see, and CSS selectors for anything more elaborate that colgroup can't reliably apply.

Common Mistakes to Avoid

❌ Mistake 1 – Placing colgroup in the wrong position
It must come immediately after the opening table tag, before thead, tbody, or any tr, or the browser ignores it.

❌ Mistake 2 – Forgetting a placeholder col for unstyled columns
Skipping a bare col element shifts every subsequent col's styling onto the wrong column.

❌ Mistake 3 – Expecting padding or fonts to work on col
These properties are not reliably supported on columns; apply them to td/th instead.

❌ Mistake 4 – Miscounting span values
A span that doesn't match the actual number of columns it should cover misaligns the rest of the colgroup.

❌ Mistake 5 – Using colgroup for row-based styling
Colgroup only affects columns; zebra striping and row hover effects still belong in tr-based CSS selectors.

Colgroup Best Practices Checklist

✔️ 1) Place colgroup right after the opening table tag
This is the only position browsers reliably honor.

✔️ 2) Include a col for every column, even unstyled ones
This keeps column position counting accurate.

✔️ 3) Use span to avoid repeating identical col elements
Cleaner markup for columns sharing the same width or color.

✔️ 4) Reserve colgroup for width, background, and visibility
Handle borders, padding, and fonts on td/th directly.

✔️ 5) Keep column widths proportional
Percentages generally adapt better across screen sizes than fixed pixel values.

Try It Yourself (Copy This Code and Paste. See how it works)

</> Try It Yourself (Copy this code and paste. See how it works)

Live Code Preview

Practice Exercises: Test Colgroup and col

  1. Build a 3-column table and use colgroup to set a different fixed width for each column.
  2. Recreate Example 3 using span="3" instead of span="2" and observe how the styling shifts.
  3. Add a bare, unstyled col as a placeholder in a 4-column table and confirm the remaining styled columns still line up correctly.
  4. Try adding padding or a border directly to a col element and compare the (lack of) effect versus applying it to td instead.
  5. Use visibility: collapse on one col to hide an entire column without removing any table data.

Frequently Asked Questions About HTML Colgroup

What is the colgroup tag used for in HTML?

The colgroup tag groups one or more columns in a table so you can apply shared styling, such as width or background color, to entire columns at once instead of repeating styles on every individual cell.

What is the difference between colgroup and col?

Colgroup is the container element that groups columns together, while col is a self-closing element placed inside colgroup that defines the properties, such as width or background color, for one or more specific columns.

How do I set a column width using colgroup?

Place a col element inside colgroup for each column and set its width using an inline style or the width attribute, such as <col style="width: 100px;">, matching the order of columns in the table.

What does the span attribute do on a col element?

The span attribute lets a single col element apply its styling to multiple consecutive columns at once, such as span="2" to style the first two columns identically without writing two separate col elements.

Where must the colgroup element be placed in a table?

The colgroup element must appear immediately after the opening table tag and before any caption, thead, tbody, or tr elements, or browsers will not apply its column styling correctly.

Can colgroup style backgrounds and borders on columns?

Colgroup and col can set background-color reliably, but many border-related CSS properties are not fully supported on columns across all browsers, so borders are usually better applied to td and th cells directly.