Question

CSS Space Between Table Rows: border-spacing Explained

htmlcss

Question

Is it possible to add space between two rows of an HTML table using CSS? I tried applying border-spacing: 5em to a table-row selector, but it did not work:

tr.classname {
  border-spacing: 5em;
}

What is the correct way to create spacing between table rows?

Short Answer

You will learn why border-spacing must be applied to the <table> element, why border-collapse affects it, and when padding or other techniques are better choices for table row separation.

Concept

HTML tables use a special layout model. A <tr> is a table row, but it does not control the gaps between table cells or rows.

The CSS property border-spacing controls the distance between cells in a table. Because it describes the table grid as a whole, it belongs on the <table> element, not on <tr> or <td>.

For border-spacing to work, the table must use the separate-border model:

table {
  border-collapse: separate;
  border-spacing: 0 1rem;
}

If the table has border-collapse: collapse, its borders are merged and border-spacing has no visible effect.

This matters in real interfaces because tables are often used for invoices, reports, admin lists, schedules, and other truly tabular data. Understanding which element owns a layout property helps you choose CSS that the browser can apply correctly.

Mental Model

Think of a table as a tray holding a grid of cups.

  • The <table> is the entire tray.
  • A <tr> is one horizontal line of cups.
  • A <td> is one cup.

border-spacing changes the empty space built into the tray grid, so it must be set on the tray (<table>). A single row cannot decide how far away every other row should be.

Take Quiz

Syntax and Examples

Use border-spacing on the table:

table {
  border-collapse: separate;
  border-spacing: horizontal vertical;
}

The first value is horizontal space between columns. The second value is vertical space between rows.

<table class="orders">
  <tr>
    <td>Order #1001</td>
    <td>Processing</td>
  </tr>
  <tr>
    <td>Order #1002</td>
    <td>Shipped</td>
  </tr>
</table>
.orders {
  border-collapse: separate;
  border-spacing: 0 1rem;
}

.orders td {
  padding: 0.75rem;
  background: #f3f4f6;
}

0 1rem means:

  • 0: no extra space between columns.
  • 1rem: one rem of extra space between rows.

If you want the same gap in both directions, use one value:

.orders {
  border-spacing: 1rem;
}

The attempted selector does not work because border-spacing is not a property that a tr uses to position other rows:

/* This does not create row gaps. */
tr.classname {
  border-spacing: 5em;
}

Step by Step Execution

Consider this table:

<table class="schedule">
  <tr>
    <td>09:00</td>
    <td>Team meeting</td>
  </tr>
  <tr>
    <td>11:00</td>
    <td>Code review</td>
  </tr>
</table>

And this CSS:

.schedule {
  border-collapse: separate;
  border-spacing: 0 12px;
}

.schedule td {
  padding: 8px;
  background: white;
}

What happens:

  1. The browser reads .schedule and identifies the <table>.
  2. border-collapse: separate tells the browser to keep cell borders and cell gaps separate.
  3. border-spacing: 0 12px creates no horizontal gap and a 12px vertical gap.
  4. The first row is laid out normally.
  5. Before the next row, the table grid leaves 12px of space.
  6. Padding inside each <td> adds room inside the cells; it does not create the gap between rows.

If border-collapse: collapse were used instead, step 3 would not produce a gap.

Real World Use Cases

border-spacing is useful when table rows should look like separate visual items:

  • Admin dashboards: Give each user, order, or support ticket row breathing room.
  • Financial reports: Separate transaction rows without adding heavy borders.
  • Booking schedules: Make time slots easier to scan.
  • Email-safe or legacy table layouts: Where a real table is already required.
  • Comparison tables: Add both horizontal and vertical separation between plan details.

For data that is not naturally tabular, such as a stack of product cards, use Flexbox or CSS Grid instead of a table.

Take Quiz

Real Codebase Usage

In production code, developers usually combine row spacing with cell styling:

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0 0.5rem;
}

.data-table td,
.data-table th {
  padding: 0.75rem 1rem;
  background: white;
}

.data-table tbody tr {
  box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
}

Common project patterns include:

  • Use border-spacing: 0 <value> to separate rows while keeping columns aligned without gaps.
  • Apply padding to td and th for readable content.
  • Apply background colors to cells when rows need to resemble individual cards, because a row's background may not visually fill the spaces as expected.
  • Reset inherited table styles explicitly. A CSS framework or browser stylesheet may set border-collapse: collapse.
  • Use a class on the table, such as .data-table, rather than styling every table globally.

Common Mistakes

Applying border-spacing to <tr>

/* Incorrect for row gaps */
tr.classname {
  border-spacing: 5em;
}

border-spacing belongs on the table:

table.classname {
  border-spacing: 0 5em;
}

Forgetting border-collapse: separate

.orders {
  border-collapse: collapse;
  border-spacing: 0 1rem; /* Has no effect */
}

Fix it by using separate:

.orders {
  border-collapse: separate;
  border-spacing: 0 1rem;
}

Using margin on table rows

tr {
  margin-bottom: 1rem;
}

Margins do not reliably create row spacing because table rows follow table layout rules. Prefer border-spacing for an actual table.

Using only one value unintentionally

table {
  border-spacing: 1rem;
}

This adds 1rem in both directions. For row-only spacing, use two values:

table {
  border-spacing: 0 1rem;
}

Confusing padding with row separation

Padding makes each cell larger, but adjacent rows still touch when there is no border spacing. Use padding for internal room and border-spacing for external gaps.

Comparisons

TechniqueBest useKey behavior
border-spacing on tableGaps between rows or cells in a real tableRequires border-collapse: separate
padding on td / thMore room inside cellsDoes not create a gap between adjacent rows
border-bottom on cellsVisual row dividersDraws a line instead of empty space
margin on trUsually avoidDoes not work reliably in table layout
Flexbox or Grid gapCard lists and non-tabular layoutsUse when the content is not a semantic table

border-collapse also changes the result:

ValueResult
separateCells can have spacing between them; border-spacing works
collapseAdjacent borders merge; border-spacing is ignored
Take Quiz

Cheat Sheet

/* Vertical gaps only */
table {
  border-collapse: separate;
  border-spacing: 0 1rem;
}

/* Horizontal and vertical gaps */
table {
  border-collapse: separate;
  border-spacing: 0.5rem 1rem;
}

/* Same gap in both directions */
table {
  border-collapse: separate;
  border-spacing: 1rem;
}
  • Apply border-spacing to <table>, not <tr>.
  • Syntax: border-spacing: horizontal vertical;.
  • A single value applies to both directions.
  • border-collapse: separate is required.
  • Use padding on td and th for space inside cells.
  • Do not rely on margins on table rows.

FAQ

Why is border-spacing not working on my table?

Check whether the table or a CSS framework sets border-collapse: collapse. Set border-collapse: separate on the same table.

Can I add space only between table rows?

Yes. Use a horizontal value of 0 and a vertical value such as 12px:

table { border-spacing: 0 12px; }

Can I use margin-bottom on a <tr>?

It is not a reliable way to space table rows. Table rows are laid out by the table formatting model. Use border-spacing instead.

Does border-spacing add space around the outside of the table?

It can create space between the table edge and its first or last cells as part of the separate-border model. Use table or container padding if you need precise outer spacing.

Should I use a table for a list of cards?

Only use a table for data with row-and-column relationships. For cards, navigation items, or general page layout, use Flexbox or Grid and their gap property.

Can I use pixels instead of em or rem?

Yes. px, em, rem, and other valid CSS length units can be used. rem is often convenient for scalable interface spacing.

Take Quiz

Mini Project

Description

Create a compact order table where each order appears as a visually separate row. This pattern is common in dashboards and order-management screens, while preserving correct table semantics for tabular data.

Goal

Build a two-column orders table with vertical space between rows and readable cell padding.

Requirements

Use a semantic <table> with a header and at least three order rows. Apply vertical row spacing without adding horizontal column spacing. Keep table borders in the separate-border model. Add padding and a background color to the table cells. Use valid CSS selectors scoped to the table.

Take Quiz

Keep learning

Related questions

View more