HTML Table Borders with CSS

Give a table visible lines by putting a border on the th and td cells, then add border-collapse: collapse to the table so neighbouring cells share one line instead of drawing two. For gaps between cells use border-collapse: separate with border-spacing. Rounded corners need the separate model, because collapsed borders ignore border-radius.

The table border properties at a glance
GoalCSSWhere it goes
Single shared grid linesborder-collapse: collapsetable
Lines around every cellborder: 1px solid #cccth, td
Gaps between cellsborder-spacing: 4pxtable (separate model only)
Striped rowstbody tr:nth-child(even) { background: #f5f5f5 }rows
Rounded outer cornersborder-radius + border-collapse: separatetable and corner cells
Lines between rows onlyborder-bottom: 1px solid #dddth, td

Updated

Tables have their own border rules, separate from ordinary boxes, so the CSS that works on a div often looks wrong on a table. Use the playground to switch between the collapsed and separated models, change the line width, spacing and corner radius, then copy the exact CSS it builds.

Table border playground

table {
  border-collapse: collapse;
}
th, td {
  border: 1px solid #94a3b8;
  padding: 8px 12px;
}

Table border properties reference

Properties that change how table lines are drawn
PropertyValuesInitialNotes
border-collapsecollapse, separateseparateSet on the table. Collapse merges shared edges.
border-spacingone or two lengths0Horizontal then vertical gap. Ignored when collapsed.
borderwidth style colournoneUsually set on th and td.
border-radiuslengths0Ignored in the collapsed model.

Editable table border examples

Collapsed grid with a header row

The classic data table: one line between every cell and a tinted header.

<style>
  table { border-collapse: collapse; width: 100% }
  th, td { border: 1px solid #cbd5e1; padding: 6px 10px; text-align: left }
  th { background: #f1f5f9 }
</style>
<table>
  <tr><th>Plan</th><th>Sites</th><th>Price</th></tr>
  <tr><td>Starter</td><td>1</td><td>$10</td></tr>
  <tr><td>Studio</td><td>5</td><td>$30</td></tr>
</table>

Rows only, with zebra stripes

No vertical lines. A bottom border on each cell plus an even-row tint keeps long rows easy to follow.

<style>
  table { border-collapse: collapse; width: 100% }
  th, td { border-bottom: 1px solid #e2e8f0; padding: 6px 10px; text-align: left }
  thead th { border-bottom: 2px solid #334155 }
  tbody tr:nth-child(even) { background: #f8fafc }
  td.num { text-align: right; font-variant-numeric: tabular-nums }
</style>
<table>
  <thead><tr><th>Month</th><th>Visits</th></tr></thead>
  <tbody>
    <tr><td>July</td><td class="num">1,204</td></tr>
    <tr><td>August</td><td class="num">980</td></tr>
    <tr><td>September</td><td class="num">1,377</td></tr>
  </tbody>
</table>

Rounded table corners

The separate model with zero spacing, borders on the right and bottom of each cell, and the outer corners rounded.

<style>
  table { border-collapse: separate; border-spacing: 0; width: 100%;
          border: 1px solid #94a3b8; border-radius: 12px; overflow: hidden }
  th, td { padding: 6px 10px; text-align: left;
           border-right: 1px solid #cbd5e1; border-bottom: 1px solid #cbd5e1 }
  tr > :last-child { border-right: 0 }
  tr:last-child > td { border-bottom: 0 }
  th { background: #e0f2fe }
</style>
<table>
  <tr><th>Day</th><th>Opens</th></tr>
  <tr><td>Monday</td><td>9:00</td></tr>
  <tr><td>Saturday</td><td>10:00</td></tr>
</table>

The obsolete border attribute next to the CSS version

Both tables look alike. The second keeps the styling in CSS, which is what the HTML standard asks for.

<table border="1"><tr><td>Old</td><td>attribute</td></tr></table>
<br>
<style> .css { border-collapse: collapse } .css td { border: 1px solid #000; padding: 2px } </style>
<table class="css"><tr><td>CSS</td><td>borders</td></tr></table>

Two border models

In the separated model each cell is its own box with its own border, and border-spacing sets the gap between those boxes. It is the default, which is why a bare table with cell borders looks doubled.

In the collapsed model the browser resolves each shared edge into a single line. That is what most data tables want, at the cost of losing border-spacing and rounded corners.

Readable data tables

Horizontal rules between rows guide the eye along a line of figures better than a dense grid. Right align numeric columns, keep a clear header row with th elements, and add a caption so the table has a name for screen reader users.

Zebra stripes help on long tables with many columns. Check that the stripe colour still leaves enough contrast for the text sitting on it.

How it works

  1. Pick the collapse or separate model in the playground and watch the double lines merge or split.
  2. Choose which lines to draw: a full grid, rows only, or just an outer frame.
  3. Turn on zebra rows or rounded corners; rounding switches the table to the separate model for you.
  4. Copy the generated CSS, or start from one of the editable examples further down.

Tips

Frequently asked questions

Why does my table show double borders?

The initial value of border-collapse is separate, so every cell draws its own border and two neighbours sit side by side. Set border-collapse: collapse on the table and adjacent borders merge into one line.

Why does border-radius not work on my table?

Rounded corners are ignored in the collapsed border model. Switch the table to border-collapse: separate, set border-spacing: 0, then round the outer corner cells or wrap the table in a div with border-radius and overflow: hidden.

Is the HTML border attribute still allowed on tables?

The HTML standard lists the border attribute on table as obsolete and says to use CSS instead. Browsers still draw it for old pages, but new code should set borders in a stylesheet so one rule controls every table.

What does border-spacing take?

One length sets the gap both across and down. Two lengths set the horizontal gap between columns first and the vertical gap between rows second, for example border-spacing: 8px 4px. It has no effect when the table is collapsed.

How do I add a border to only one column?

Target the cells in that column with a selector such as td:nth-child(2), th:nth-child(2) and give them a left or right border. Styling the cells directly works the same in both border models.

Related: HTML table generator, Markdown table generator, CSS box model and display, CSS selectors cheat sheet, HTML and CSS cheat sheet.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap