How to put spacing between TBODY elements

HtmlCss

Html Problem Overview


I have a table like this:

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>

I'd like to put some spacing between each tbody element, but padding and margin have no effect. Any ideas?

Html Solutions


Solution 1 - Html

Something like this will work, depending on your browser support requirements:

tbody::before
{
  content: '';
  display: block;
  height: 15px;

}

Solution 2 - Html

Try this, if you don't mind not having borders.

<style>
table {
  border-collapse: collapse;
}

table tbody {
  border-top: 15px solid white;
}
</style>

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>

          

Solution 3 - Html

People will always have controversial opinions about using empty table elements to layout a page (as evidenced by this answer's downvote). I recognize this, but sometimes its easier to use them this way when you are working in a "quick and dirty" way.

I've used empty rows in past projects to space groups of table rows. I assigned the spacer rows a css class of their own and defined a height for that class that acted as a top and bottom margin for that group of table rows.

    .separator{
             height: 50px;
    }
    
   <table>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>

           <tr class="separator" colspan="2"></tr>

           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>

           <tr class="separator" colspan="2"></tr>

           tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
           <tr><td>Cell 1</td><td>Cell 2</td></tr>
   </table>

If you don't have borders on your table cells, you could also define a height to your typical cell or row in your style sheet that evenly spaces out all rows of your table.

tr{
   height: 40px;
}

Solution 4 - Html

I had been in trouble spacing properly multiple <tbody> with ::before pseudo, in presence of <tr> containing <td> with rowspan in a couple of browsers.

Basically, if you have a <tbody> structured like this:

<tbody>
	<tr>
		<td>td 1</td>
		<td rowspan"2">td 2</td>
		<td>td 3</td>
		<td>td 4</td>
	</tr>
	<tr>
		<td>td 1</td>
		<td>td 2</td>
		<td>td 4</td>
	</tr>
</tbody>

And you follow who advises to write css on ::before pseudo element like this:

tbody::before
{
	content: '';
	display: block;
	height: 10px;
}

This will affect the rowspan, making table "losing" within the second <tr> how many <td>-rowspan are present in the first one.

So, if anyone encounters that type of problem, the solution is to style ::before pseudo in this way:

tbody::before
{
	content: '';
	display: table-row;
	height: 10px;
}

Here's a fiddle

Solution 5 - Html

Here's another possibility that relies on :first-child which is not available in all browsers:

<style>
table {
  border-collapse: collapse;
}

td {
  border: 1px solid black;
}
  
tbody tr:first-child td {
  padding-top: 15px;
}

</style>

<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>

Solution 6 - Html

Of all of the answers given above, only djenson47's answers retain separation of presentation and content. The drawback of the collapsed border model method is that you can no longer use the table's border or cellspacing attributes to separate the individual cells. You could argue that this is a good thing, and there are some workarounds, but it can be a pain. So I think the first-child method is the most elegant.

Alternatively, you could also set your TBODY class' overflow property to anything other than "visible." This method allows you to retain a separated borders model as well:

<style>
tbody {
    overflow: auto;
    border-top: 1px solid transparent;
}
</style>
<table>
    <tfoot>
        <tr><td>footer</td></tr>
    </tfoot>
    <tbody>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
        <tr><td>Body 1</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
        <tr><td>Body 2</td></tr>
    </tbody>
    <tbody>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
        <tr><td>Body 3</td></tr>
    </tbody>
</table>

Solution 7 - Html

You can use border-spacing in a table with table row groups to add a space between those groups. Though, I don't think there is a way to specify which groups are spaced and which are not.

<table>
  <thead>
    ...
  </head>
  <tbody>
    ...
  </tbody>
  <tbody>
    ...
  </tbody>
  <tfoot>
    ...
  </tfoot>
</table>

CSS

table {
  border-spacing: 0px 10px; /* h-spacing v-spacing */
}

Solution 8 - Html

Just set display as block and it will work.

table tbody{
    display:block;
    margin-bottom:10px;
    border-radius: 5px;
}

Solution 9 - Html

Because padding can be applied to TD's, you can do a trick with the + sign. Then it will be possible to give a top padding to the TD's of the first TR of a tbody:

// The first row will have a top padding
table tbody + tbody tr td {
    padding-top: 20px;
}

// The rest of the rows should not have a padding
table tbody + tbody tr + tr td {
    padding-top: 0px;
}

I have added the "tbody + tbody" so the first tbody won't have a top padding. However, it's not required.

As far as I know there are no drawbacks :), though didn't test the older browsers.

Solution 10 - Html

NEW ANSWER

You can use as many <tbody> tags as you like. I didn't realize that was ok by W3C until now. Not to say my below solution doesn't work (it does), but to do what you're trying to do, assign your <tbody> tags classes and then reference their individual <td> tags through CSS like so:

table tbody.yourClass td {
    padding: 10px;
}

and your HTML thusly:

<table> 
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
<tbody class="yourClass">    
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
</table>

Try that guy out :)

OLD ANSWER

whatever you do, DON'T insert blank rows...

you shouldn't have more than 1 tbody element in your table. what you can do is set the class or id attribute in your <tr> elements and give their corresponding <td> tags padding:

table {
    border-collapse: collapse;
}

tr.yourClass td {
    padding: 10px;
}

You can even assign the top and bottom <tr>'s an additional class so that they only do top or bottom padding, respectively:

tr.yourClass.topClass td {
    padding: 10px 0 0 0;
}

tr.yourClass.bottomClass td {
    padding: 0 0 10px 0;
}

and in your HTML, your <tr> tag would look like this:

<table> 
<tbody>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr class="yourClass topClass"><td>Text</td></tr>
<tr class="yourClass"><td>Text</td></tr>
<tr class="yourClass bottomClass"><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
<tr><td>Text</td></tr>
</tbody>
</table>

Hope this helps!

Solution 11 - Html

djensen47 answer works great for newer browsers, however, as it was pointed out, IE7 it does not work in.

My workaround for this issue to support the older browsers was to wrap each cells contents inside a div. Then add a margin-top to the div.

<table class="tbl">
<tr></tr>
<tr></tr>
<tr></tr>
<tr><td><div></div></td></tr>
</table>

CSS

.tbl tr td div {
    height:30px;
    margin-top:20px;
}

The height setting keeps the cells at least 30px high to prevent any cell coloring used inside the div from collapsing around the text. The margin-top creates the desired space by making the entire row taller.

Solution 12 - Html

Came across this while trying to solve it myself. I had success with putting a <br> tag right before the closing </tbody> tag. It is a purely visual fix, but seems to work on most browsers I tested.

<table>
    <tbody>
        <tr>
            <td></td>
        </tr>
        <br>
    </tbody>
    <tbody>
        <tr>
            <td></td>
        </tr>
    </tbody>
</table>

Should be accessible as well.

Solution 13 - Html

With credit to everyone else who answered first ...

table {
  border-collapse: collapse;
  table-layout: fixed;
  width: 50%;
}
tbody:before {
  content: "";
  display:block;
  border-top: 15px solid white;
}
tbody tr {
  border-color: #000;
  border-style: solid;
}
tbody tr:first-of-type{
  border-width: 2px 2px 0 2px;
}
tbody tr:nth-of-type(1n+2){
  border-width: 0 2px 0 2px;
}
tbody tr:last-of-type{
  border-width: 0 2px 2px 2px;
}
tbody tr:nth-child(odd) {
  background-color: #ccc;
}
tbody tr:hover {
  background-color: #eee;
}
td {
  text-align: right;
}

<table>
  <tbody>
    <tr>
      <th colspan="3">One</th>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="3">Two</th>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
</table>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnickfView Question on Stackoverflow
Solution 1 - HtmlMacNimbleView Answer on Stackoverflow
Solution 2 - HtmlDave JensenView Answer on Stackoverflow
Solution 3 - HtmlkevtroutView Answer on Stackoverflow
Solution 4 - HtmlNineoclickView Answer on Stackoverflow
Solution 5 - HtmlDave JensenView Answer on Stackoverflow
Solution 6 - HtmlCalvinView Answer on Stackoverflow
Solution 7 - HtmlOdraEncodedView Answer on Stackoverflow
Solution 8 - Htmluser007View Answer on Stackoverflow
Solution 9 - HtmlMaartenView Answer on Stackoverflow
Solution 10 - HtmlJasonView Answer on Stackoverflow
Solution 11 - HtmlJereme GuentherView Answer on Stackoverflow
Solution 12 - HtmlIanView Answer on Stackoverflow
Solution 13 - Htmluser2182349View Answer on Stackoverflow