270

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>
4

18 Answers 18

228

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

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

Reference.

5
  • 1
    but in case of separate border will not work with tr, any workaround? Commented Feb 24, 2020 at 9:40
  • 2
    @PardeepJain A box shadow like box-shadow: 0px 0px 0px 1px black; will achieve the same effect
    – frboud
    Commented Feb 28, 2020 at 20:01
  • It seems I can't set the spacing on one side (top or bottom), only both. Otherwise seems to be working. Thanks! Commented Nov 27, 2020 at 8:39
  • @aexl Try using 4 values instead of 2, and tweak it.
    – Mark
    Commented Nov 27, 2020 at 21:16
  • what if just for a single row?
    – serge
    Commented Oct 19, 2023 at 11:36
192

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.

5
  • 36
    Adding any kind of padding to <tr> doesn't move anything unless you specify display: block, at which point the width of the <tr> is based on content. Adding your suggested spacer <tr> with a set height works perfectly, though.
    – baacke
    Commented Jan 22, 2014 at 19:08
  • 5
    To be more precise, <tr> cannot have margin values since CSS 2.1 but it could until CSS 2. I have never found the reason behind the change.
    – Futal
    Commented Jun 4, 2014 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
    Commented Jul 16, 2015 at 19:28
  • That was an interesting solution. No random bad practice. Nice job.
    – L1ghtk3ira
    Commented Feb 15, 2017 at 16:07
  • 1
    spacer still works in Chrome and Firefox, but is entirely obsolete, and must not be used by authors (whatwg.org).
    – Rainald62
    Commented May 21, 2020 at 19:25
73

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
}
2
  • 12
    This will only visually work if the td background-color is the same as the tr.
    – baacke
    Commented Jan 22, 2014 at 19:10
  • This will work 99% of times and it's more simple and elegant IMHO Commented Jun 6, 2022 at 15:42
40

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;
}
4
  • 1
    Isn't this the same as my answer above?
    – Mark
    Commented Jun 22, 2018 at 13:23
  • @Mark You didn't bother to clarify your answer.
    – John
    Commented Jun 23, 2018 at 2:12
  • 1
    Ok, sorry, not sure which clarification you'd like. Just let me know.
    – Mark
    Commented Jun 25, 2018 at 20:28
  • 1
    @Mark above and below here changes over time and relative to the choosen sorting. Commented Jul 2, 2020 at 9:15
35

line-height can be the possible solution

tr
{
    line-height:30px;
}
2
  • With this I couldn't use vertical-align: bottom.
    – Noumenon
    Commented Sep 11, 2016 at 20:14
  • 3
    Unless there is more than one line in any of the child <td> - each line will be "taller". In this case the answers that style the <td> padding work.
    – RMagauran
    Commented Nov 1, 2018 at 10:56
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.

2
  • 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; } Commented Aug 7, 2015 at 9:21
  • 3
    If you really want a border on top of it, it won't work.
    – JulienD
    Commented Nov 17, 2016 at 13:37
31

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>
5
  • 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. Commented Jan 16, 2018 at 10:53
  • @PhilipStratford I'm really glad you forced me to evolve, answer edited. Commented Jan 18, 2018 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. Commented Jan 19, 2018 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... Commented Jan 19, 2018 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. Commented Dec 21, 2021 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/

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.

1
  • 2
    Broken link (404) to the code pen.
    – ΩmegaMan
    Commented Jun 21, 2017 at 15:35
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.

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.

2
  • 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 Commented Feb 26, 2016 at 2:25
  • Thanks! Very simple and even allows specifying border only between certain rows Commented Dec 10, 2021 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>
1
  • This is a great solution! Especially for large dynamic tables.
    – nathan
    Commented Jun 11, 2018 at 21:11
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;
}
0
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;
        }
    }
}
0

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.