261

I have a table containing many rows. Some of these rows are class="highlight" and signify a row that needs to be styled differently and highlighted. What I'm trying to do is add some extra spacing before and after these rows so they appear slightly separated from the other rows.

I thought I could get this done with margin-top:10px;margin-bottom:10px; but it's not working. Anyone knows how to get this done, or if it could be done? Here's the HTML and I've set the 2nd tr in the tbody to class highlight.

<table>
<thead>
  <tr>
     <th>Header 1</th>
     <th>Header 2</th>
  </tr>
</thead>
<tbody>
  <tr>
     <td>Value1</td>
     <td>Value2</td>
  </tr>
  <tr class="highlight">
     <td>Value1</td>
     <td>Value2</td>
  </tr>
  <tr>
     <td>Value1</td>
     <td>Value2</td>
  </tr>
  <tr>
     <td>Value1</td>
     <td>Value2</td>
  </tr>
</tbody>
</table>
Katti
  • 2,013
  • 1
  • 17
  • 31
sameold
  • 18,400
  • 21
  • 63
  • 87
  • possible duplicate of [CSS: how do I create a gap between rows in a table?](http://stackoverflow.com/questions/1264187/css-how-do-i-create-a-gap-between-rows-in-a-table) and http://stackoverflow.com/questions/351058/space-between-two-rows-in-a-table – j08691 May 21 '12 at 18:13
  • try this: tr.highlight td { position: relative; background-color: #EEEEEE; padding: 5px 0 5px 0; } – Simon Dorociak May 21 '12 at 18:19
  • 2
    if you are using the [`separated` box model](https://developer.mozilla.org/en-US/docs/Web/CSS/border-collapse), I obtained the effect you wanted playing with borders of cell elements (TD and TH), not TR like @Jrd suggested: tr.highlight td { border-top: 10px solid; border-bottom: 10px solid; border-color: transparent; } – Enrico Marchesin Aug 07 '15 at 09:18
  • 1
    Add to table ``border-collapse:separate; border-spacing: 0 1rem;`` – mehmet May 06 '23 at 11:21

18 Answers18

218

The border-spacing property will work for this particular case.

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

Reference.

sandstrom
  • 14,554
  • 7
  • 65
  • 62
Mark
  • 2,961
  • 1
  • 16
  • 24
190

Table rows cannot have margin values. Can you increase the padding? That would work. Otherwise you could insert a <tr class="spacer"></tr> before and after the class="highlighted" rows.

Steve Binder
  • 2,270
  • 1
  • 14
  • 6
  • 35
    Adding any kind of padding to `` doesn't move anything unless you specify `display: block`, at which point the width of the `` is based on content. Adding your suggested spacer `` with a set `height` works perfectly, though. – baacke Jan 22 '14 at 19:08
  • 4
    To be more precise, cannot have margin values since [CSS 2.1](http://www.w3.org/TR/CSS21/box.html#propdef-margin) but it could until [CSS 2](http://www.w3.org/TR/1998/REC-CSS2-19980512/box.html#margin-properties). I have never found the reason behind the change. – Futal Jun 04 '14 at 16:10
  • 2
    Yes, unfortunately `tr` can't have margin values, like Steve wrote. I set margin value to each `td` like replacement for this. :( `padding` isn't solution, by my opinion, especially if rows are different colors (background) and You need some, let say, empty (white) space. – nelek Jul 16 '15 at 19:28
  • That was an interesting solution. No random bad practice. Nice job. – L1ghtk3ira Feb 15 '17 at 16:07
  • 1
    `spacer` still works in Chrome and Firefox, but is [entirely obsolete, and must not be used by authors](https://html.spec.whatwg.org/multipage/obsolete.html#non-conforming-features) (whatwg.org). – Rainald62 May 21 '20 at 19:25
71

You can't style the <tr>s themselves, but you can give the <td>s inside the "highlight" <tr>s a style, like this

tr.highlight td {
  padding-top: 10px; 
  padding-bottom:10px
}
Rifky Niyas
  • 1,737
  • 10
  • 25
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
38

This isn't going to be exactly perfect though I was happy to discover that you can control the horizontal and vertical border-spacing separately:

table
{
 border-collapse: separate;
 border-spacing: 0 8px;
}
John
  • 1
  • 13
  • 98
  • 177
35

line-height can be the possible solution

tr
{
    line-height:30px;
}
Mehmet Eren Yener
  • 2,006
  • 1
  • 23
  • 37
31

I know this is kind of old, but I just got something along the same lines to work. Couldn't you do this?

tr.highlight {
    border-top: 10px solid;
    border-bottom: 10px solid;
    border-color: transparent;
}

Hope this helps.

Jrd
  • 668
  • 6
  • 9
  • 4
    thanks, but had to move properties on the TD elements to have it work: tr.highlight td { border-top: 10px solid; border-bottom: 10px solid; border-color: transparent; } – Enrico Marchesin Aug 07 '15 at 09:21
  • 3
    If you really want a border on top of it, it won't work. – JulienD Nov 17 '16 at 13:37
30

First of all, don't try to put a margin to a <tr> or a <td> because it won't work in modern rendering.

  • Solution 1

Although margin doesn't work, padding does work :

td{
    padding-bottom: 10px;
    padding-top: 10px;
}

Warning : This will also push the border further away from the element, if your border is visible, you might want to use solution 2 instead.

  • Solution 2

To keep the border close to the element and mimic the margin, put another <tr> between each of your reel table's <tr> like so :

<tr style="height: 20px;"> <!-- Mimic the margin -->
</tr>
Antoine Pelletier
  • 3,164
  • 3
  • 40
  • 62
  • This won't necessarily produce the desired effect, though. For example, if the row has a top or bottom border, the space this CSS adds will be inside the border, whereas with a margin you'd expect it to be outside. – Philip Stratford Jan 16 '18 at 10:53
  • @PhilipStratford I'm really glad you forced me to evolve, answer edited. – Antoine Pelletier Jan 18 '18 at 18:13
  • 1
    Glad to have helped. I think 'dummy' rows, as you have described in your second solution, is really the only way to achieve this, just as the accepted answer by Steve Binder says. – Philip Stratford Jan 19 '18 at 11:03
  • 1
    @PhilipStratford All agreed, it's almost a shame that modern css rendering can't accomplish something as simple as separating two table rows... – Antoine Pelletier Jan 19 '18 at 14:43
  • `height` worked for me. What's nice is if the height you specify is too small to show the content, it will still expand to fit the content. – Joshua Pinter Dec 21 '21 at 22:55
10

A way to mimic the margin on the row would be to use the pseudo selector to add some spacing on the td.

.highlight td::before, .highlight td::after
{
  content:"";
  height:10px;
  display:block;
}

This way anything marked with the highlight class will be separated top and bottom.

https://jsfiddle.net/d0zmsrfs/

Alex
  • 865
  • 13
  • 24
9

Because margin is ignored on tr, I usually use a workaround, by setting a transparent border-bottom or border-top and setting the background-clip property to padding-box so the background-color does not get painted underneath the border.

table {
   border-collapse: collapse; /* [1] */
}

th, td {
  border-bottom: 5px solid transparent; /* [2] */
  background-color: gold; /* [3] */
  background-clip: padding-box; /* [4] */
}
  1. Makes sure cells share a common border, but is completely optional. The solution works without it.
  2. The 5px value represents the margin that you want to achieve
  3. Sets the background-color of your row/cell
  4. Makes sure the background get not painted underneath the border

see a demo here: http://codepen.io/meodai/pen/MJMVNR?editors=1100

background-clip is supported in all modern browser. (And IE9+)

Alternatively you could use a border-spacing. But this will not work with border-collapse set to collapse.

meo
  • 30,872
  • 17
  • 87
  • 123
7

You might try to use CSS transforms for indenting a whole tr:

tr.indent {
   -webkit-transform: translate(20px,0);
   -moz-transform: translate(20px,0);
}

I think this is a valid solution. Seems to work fine in Firefox 16, Chrome 23 and Safari 6 on my OSX.

Tomi Mickelsson
  • 199
  • 2
  • 2
4

Here's a neat way I did it:

table tr {
    border-bottom: 4px solid;
}

That will add 4px of vertical spacing between each row. And if you wanted to not get that border on the last child:

table tr:last-child {
    border-bottom: 0;
}

Reminder that CSS3 pseudo-selectors will only work in IE 8 and below with selectivizr.

user1429980
  • 6,872
  • 2
  • 43
  • 53
  • 1
    This is the real way to do it. Simple and very un-annoying. Came to the same conclusion myself. You missed one thing, just give the border a transparent color... `border-bottom: 10px solid transparent` – mangonights Feb 26 '16 at 02:25
  • Thanks! Very simple and even allows specifying border only between certain rows – Oleksandr Danylchenko Dec 10 '21 at 11:49
4

I gave up and inserted a simple jQuery code as below. This will add a tr after every tr, if you have so many trs like me. Demo: https://jsfiddle.net/acf9sph6/

<table>
  <tbody>
     <tr class="my-tr">
        <td>one line</td>
     </tr>
     <tr class="my-tr">
        <td>one line</td>
     </tr>
     <tr class="my-tr">
        <td>one line</td>
     </tr>
  </tbody>
</table>
<script>
$(function () {
       $("tr.my-tr").after('<tr class="tr-spacer"/>');
});
</script>
<style>
.tr-spacer
{
    height: 20px;
}
</style>
Jenny
  • 61
  • 6
4

A hack to give the appearance of margins between table rows is to give them a border the same color as the background. This is useful when styling a 3rd party theme where you can't change the html markup. Eg:

tr{ 
    border: 5px solid white;
}
3

add a div to the cells that you would like to add some extra spacing:

<tr class="highlight">
 <td><div>Value1</div></td>
 <td><div>Value2</div></td>
</tr>
tr.highlight td div {
margin-top: 10px;
}
3

You can create space between table rows by adding an empty row of cells like this...

<tr><td></td><td></td></tr>

CSS can then be used to target the empty cells like this…

table :empty{border:none; height:10px;}

NB: This technique is only good if none of your normal cells will be empty/vacant.

Even a non-breaking space will do to avoid a cell from being targetted by the CSS rule above.

Needless to mention that you can adjust the space's height to whatever you like with the height property included.

1

Another possibility is to use a pseudo selector :after or :before

tr.highlight td:last-child:after
{
  content: "\0a0";
  line-height: 3em;
}

That might avoid issues with browser that don't understand the pseudo selectors, plus background-colors are not an issue.

The downside is however, that it adds some extra whitespace after the last cell.

1

For what is worth, I took advantage that I was already using bootstrap (4.3), because I needed to add margin, box-shadow and border-radius to my row, something I can't do with tables.

<div id="loop" class="table-responsive px-4">
<section>
    <div id="thead" class="row m-0">
        <div class="col"></div>
        <div class="col"></div>
        <div class="col"></div>
    </div>
    <div id="tbody" class="row m-0">
        <div class="col"></div>
        <div class="col"></div>
        <div class="col"></div>
    </div>
</section>
</div>

On css I added a few lines to mantain the table behavior of bootstrap

@media (max-width: 800px){
    #loop{
        section{
            min-width: 700px;
        }
    }
}
Gendrith
  • 196
  • 1
  • 4
  • 13
0

add this style before the class="highlighted" padding-bottom and display is inline-table