I'm trying to create an HTML table where its height is limited and the left side stay fixed while scrolling horizontally (and the table body is scrollable horizontally) but not fixed while scrolling vertically (the left side will be scrollable with the rest of the table).
fixed scrollable
1 body content
2 body content
3 body content
4 body content
. .
. .
. .
I found this solution however, it only addresses an horizontal scrolling. In Eamon Nerbonne jsFiddle example, adding a height: 150px; to the div will demonstrate the bug I'm trying to solve.
I'd like to find a solution that involve only HTML & CSS.
Adding another div to the Eamon Nerbonne's solution, gave me the following solution:
jsFiddle
Basically the solution is, if you add another parent div that controls the flow of the secondary div might give you a go.
<div class="first">
<div class="second">
<table>
<tr><td class="headcol">1</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">2</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">3</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">4</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">5</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">6</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">7</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">8</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
<tr><td class="headcol">9</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td><td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td></tr>
</table>
</div>
</div>
I added style for the outer div like this:
div.first {
width: auto;
overflow-y: scroll;
overflow-x: hidden;
height: 150px; /* this is the height that you expect to contain */
padding-bottom: 1px;
position: absolute;
left:0;
top:auto;
}
A little late but I did run across this thread when trying out solutions for myself. Assuming you're using modern browsers nowadays, I came up with a solution using CSS calc() to help guarantee widths met up.
.table-fixed-left table,
.table-fixed-right table {
border-collapse: collapse;
}
.table-fixed-right td,
.table-fixed-right th,
.table-fixed-left td,
.table-fixed-left th {
border: 1px solid #ddd;
padding: 5px 5px;
}
.table-fixed-left {
width: 120px;
float: left;
position: fixed;
overflow-x: scroll;
white-space: nowrap;
text-align: left;
border: 1px solid #ddd;
z-index: 2;
}
.table-fixed-right {
width: calc(100% - 145px);
right: 15px;
position: fixed;
overflow-x: scroll;
border: 1px solid #ddd;
white-space: nowrap;
}
.table-fixed-right td,
.table-fixed-right th {
padding: 5px 10px;
}
<div class="table-fixed-left">
<table>
<tr>
<th>Normal Header</th>
</tr>
<tr>
<th>Header with extra line
<br/> </th>
</tr>
<tr>
<th>Normal Header</th>
</tr>
<tr>
<th>Normal with extra line
<br/> </th>
</tr>
<tr>
<th>Normal Header</th>
</tr>
<tr>
<th>Normal Header</th>
</tr>
</table>
</div>
<div class="table-fixed-right">
<table>
<tr>
<th>Header</th>
<th>Another header</th>
<th>Header</th>
<th>Header really really really really long</th>
</tr>
<tr>
<td>Info Long</td>
<td>Info
<br/>with second line</td>
<td>Info
<br/>with second line</td>
<td>Info Long</td>
</tr>
<tr>
<td>Info Long</td>
<td>Info Long</td>
<td>Info Long</td>
<td>Info Long</td>
</tr>
<tr>
<td>Info
<br/>with second line</td>
<td>Info
<br/>with second line</td>
<td>Info
<br/>with second line</td>
<td>Info</td>
</tr>
<tr>
<td>Info</td>
<td>Info</td>
<td>Info</td>
<td>Info</td>
</tr>
<tr>
<td>Info</td>
<td>Info</td>
<td>Info</td>
<td>Info</td>
</tr>
</table>
</div>
Hope this helps anyone!
Related
I have table in the a page where I need to implement a vertical scroll only for the tbody part of the table. My table has columns of dynamic width, there's horizontal scrolling implemented if increase in width of a column causes the table to overflow. What I want is for only the body of the table to scroll on vertical overflow, but want the table header to remain visible. What I have implemented scrolls the entire table vertically
Following is my code for now. It has dummy data, as I cant post the actual code, but the structure is the same(jsfiddle link):
th,
td {
text-align: left;
padding: 5px;
outline: solid 0.5px;
}
table {
table-layout: auto;
width: 100%;
white-space: nowrap;
overflow-x: scroll;
overflow-y: scroll;
height: 100px;
display: block;
}
.container {
width: 300px;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
</table>
</div>
I have checked multitiple solutions on stackoverflow for this problem but they all set a fixed width for their columns and then use wrap the content inside if it exceeds the width. table with fixed thead and scrollable tbody
is the only solution that didn't completely mess up my page, but doesn't work, it gives different column widths for columns in header and body.
All other solutions, even the ones that use nested table use fixed width column, and the ones which don't use js/jQuery which I would rather not use unless its the absolute, last ever option. Can anyone please suggest something?
To make the <tbody> scrollable :
tbody{
display: block;
height: 100px;
width: 100%;
overflow-y: scroll;
}
And if you want to the <thead> to stay fixed while the body scrolls:
thead tr{
display: block
}
I'm unsure whether this is answering your question.
If the y axis is always to have a scroll and the x axis only to have
a scroll if there is too much information
CSS
overflow-x:auto;
overflow-y:scroll;
I came across this issue myself and found an alternate solution to the answer posted by #Abe Caymo
Simple non-ideal solution (by Abe)
The problem with Abe's solution is that it works fine up until you start to use thead and tfoot. Once you add these you will soon realize that the table column layout no longer syncs the column width across tbody, thead and tfoot. See demo below...
th,
td {
text-align: left;
padding: 5px;
outline: solid 0.5px;
}
table {
white-space: nowrap;
display: block;
}
tbody{
display: block;
height: 100px;
overflow-y: auto;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</tfoot>
</table>
</div>
Slightly more ideal solution
A better solution which maintains the auto table-layout is to set the thead and tfoot to position: sticky.
A few caveats and things to understand about this approach.
The overflow or element actually scrolling, is the div container of the table. You must have this and this is what you may use to control the size of the table. As such, the scroll bar will always be the full height of the scrollable table.
The background-color must be set to an opaque value otherwise the rows in the tbody will show behind the header as it passes below when scrolling.
The borders/outlines are much harder to get right but with a little finessing you can find a compatible style. Adding a border or outline to either thead or tfoot will not be sticky.
.container {
height: 140px;
min-height: 100px;
overflow: auto;
resize: vertical; /* only for demo */
}
thead,
tfoot {
/* must background-color otherwise transparent will show rows underneath */
background-color: white;
position: sticky;
}
thead {
margin-bottom: 0;
top: 0;
}
tfoot {
margin-top: 0;
bottom: 0;
}
th,
td {
text-align: left;
padding: 5px;
outline: solid black 0.5px;
}
table {
width: 100%;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</tfoot>
</table>
</div>
The final result will look something like that below with all columns aligned respectively...
Also see this solution using display: grid on the table element.
i am working on table structure html and i want to set my design in my stucture!!
i have get issue my table format width is set according to body content !
My question is how can i set width accrding to header ?
here is my code.
<table>
<thead>
<tr>
<td>Document name</td>
<td>Category</td>
<td>Sub category</td>
<td>Status</td>
</tr>
</thead>
<tbody>
<tr>
<td>Indisoft – RX Office and Thinagee- 401K Payment </td>
<td>admin</td>
<td>admin-sub</td>
<td>published</td>
</tr>
</tbody>
</table>
You can see my output:
enter image description here
Set the style on any of the td or th tags in the thead, and it will apply to all the cells in the column.
In the example below I've used an inline style, but that is not necessary. You could use CSS classes for that as well.
Also, you should replace the td's in the thead with th elements.
table td {
border: 1px black solid;
}
<table>
<thead>
<tr>
<td style="width: 50px">Document name</td>
<td>Category</td>
<td>Sub category</td>
<td>Status</td>
</tr>
</thead>
<tbody>
<tr>
<td>Indisoft – RX Office and Thinagee- 401K Payment </td>
<td>admin</td>
<td>admin-sub</td>
<td>published</td>
</tr>
</tbody>
You should set style width for each column, in other case it will resize to body size.
For example:
table {
border: solid 1px #000;
}
table td:nth-child(1) {
width: 200px;
border-right: solid 1px #ccc;
}
table td:nth-child(2) {
width: 100px;
border-right: solid 1px #ccc;
}
table td:nth-child(3) {
width: 150px;
border-right: solid 1px #ccc;
}
table td:nth-child(2) {
width: 50px;
}
<table>
<thead>
<tr>
<td>Document name</td>
<td>Category</td>
<td>Sub category</td>
<td>Status</td>
</tr>
</thead>
<tbody>
<tr>
<td>Indisoft – RX Office and Thinagee- 401K Payment </td>
<td>admin</td>
<td>admin-sub</td>
<td>published</td>
</tr>
</tbody>
I have a big table with about 300 rows and 12 columns. While scrolling through the table by paging through the page the <thead> content is not displayed by default. I would like to see it while scrolling "within" <tbody>. That is, if the top of the screen starts with a row, I want that the header is displayed first. Otherwise it should behave like a regular table.
The common solution I have seen so far is to create a table that can scroll for itself (thus independently of page scrolling). That is, what answers to this question suggest.
But this is not very practical if you have many columns spanning the screen, in particular because there are now two independent scrollbars. On mobile devices the second scrollbar takes away a lot of precious space. And it is also very irritating to use. You cannot simply "leaf through", but you have to concentrate to hit that tiny scroll bar. On other browsers you can scroll touching the data within, but once you move outside, another irritating movement happens...
Is there a clean CSS way to do this?
Hoping that position:sticky will one day be the definitive answer to this problem (see announcement here) like mentioned in the comments above, I was still fascinated at making a simple HTML/CSS proof-of-concept, without the double scrollbars.
My simple solution — not meant to be a perfect one, more as an exercise — without scripting:
Duplicate the thead, one that scrolls with the page, and one that stays fixed
Play with z-indexes to show the appropriate thead
http://jsfiddle.net/willemvb/hEyZh/
What if you:
Create your table as long and wide as necessary without a header. Created another table with your table head. Place your header table inside a separate DIV and float that over your data table (z-index + position:absolute). using JQuery, on window load, resize, scroll or any relevant events, you can reset each TH width to match it's corresponding TD. You can also reposition the table head DIV as you scroll. This should work. Let me know if you need an example. This way you should only see browser scroll bars if and when needed.
Good luck.
This may help you :
Source from
JS Fiddle
HTML
<!-- IE < 10 does not like giving a tbody a height. The workaround here applies the scrolling to a wrapped <div>. -->
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->
<table class="fixed_headers">
<thead>
<tr>
<th>Name</th>
<th>Color</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Grape</td>
<td>Purple / Green</td>
<td>These are purple and green.</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
<td>These are orange.</td>
</tr>
<tr>
<td>Banana</td>
<td>Yellow</td>
<td>These are yellow.</td>
</tr>
<tr>
<td>Kiwi</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Plum</td>
<td>Purple</td>
<td>These are Purple</td>
</tr>
<tr>
<td>Watermelon</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Tomato</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Cherry</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Cantelope</td>
<td>Orange</td>
<td>These are orange inside.</td>
</tr>
<tr>
<td>Honeydew</td>
<td>Green</td>
<td>These are green inside.</td>
</tr>
<tr>
<td>Papaya</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Raspberry</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Blueberry</td>
<td>Blue</td>
<td>These are blue.</td>
</tr>
<tr>
<td>Mango</td>
<td>Orange</td>
<td>These are orange.</td>
</tr>
<tr>
<td>Passion Fruit</td>
<td>Green</td>
<td>These are green.</td>
</tr>
</tbody>
</table>
<!--[if lte IE 9]>
</div>
<!--<![endif]-->
CSS
.fixed_headers {
width: 750px;
table-layout: fixed;
border-collapse: collapse;
}
.fixed_headers th {
text-decoration: underline;
}
.fixed_headers th,.fixed_headers td {
padding: 5px;
text-align: left;
}
.fixed_headers td:nth-child(1),.fixed_headers th:nth-child(1) {
min-width: 200px;
}
.fixed_headers td:nth-child(2),.fixed_headers th:nth-child(2) {
min-width: 200px;
}
.fixed_headers td:nth-child(3),.fixed_headers th:nth-child(3) {
width: 350px;
}
.fixed_headers thead {
background-color: #333333;
color: #fdfdfd;
}
.fixed_headers thead tr {
display: block;
position: relative;
}
.fixed_headers tbody {
display: block;
overflow: auto;
width: 100%;
height: 300px;
}
.fixed_headers tbody tr:nth-child(even) {
background-color: #dddddd;
}
.old_ie_wrapper {
height: 300px;
width: 750px;
overflow-x: hidden;
overflow-y: auto;
}
.old_ie_wrapper tbody {
height: auto;
}
Source from
JS Fiddle
You can use the plugin, it works fine:
http://web-gladiator.com/stickythead/
I want to hide the border for a specific rows of a table.How to do it?
Any Idea?
Sample code is Highly Appreciated.
Use the CSS property border on the <td>s following the <tr>s you do not want to have the border.
In my example I made a class noBorder that I gave to one <tr>. Then I use a simple selector tr.noBorder td to make the border go away for all the <td>s that are inside of <tr>s with the noBorder class by assigning border: 0.
Note that you do not need to provide the unit (i.e. px) if you set something to 0 as it does not matter anyway. Zero is just zero.
table, tr, td {
border: 3px solid red;
}
tr.noBorder td {
border: 0;
}
<table>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr class="noBorder">
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
<tr>
<td>A3</td>
<td>A3</td>
<td>A3</td>
</tr>
</table>
Here's the output as an image:
I use this with good results:
border-style:hidden;
It also works for:
border-right-style:hidden; /*if you want to hide just a border on a cell*/
Example:
<style type="text/css">
table, th, td {
border: 2px solid green;
}
tr.hide_right > td, td.hide_right{
border-right-style:hidden;
}
tr.hide_all > td, td.hide_all{
border-style:hidden;
}
}
</style>
<table>
<tr>
<td class="hide_right">11</td>
<td>12</td>
<td class="hide_all">13</td>
</tr>
<tr class="hide_right">
<td>21</td>
<td>22</td>
<td>23</td>
</tr>
<tr class="hide_all">
<td>31</td>
<td>32</td>
<td>33</td>
</tr>
</table>
Here is the result:
Add programatically noborder class to specific row to hide it
<style>
.noborder
{
border:none;
}
</style>
<table>
<tr>
<th>heading1</th>
<th>heading2</th>
</tr>
<tr>
<td>content1</td>
<td>content2</td>
</tr>
/*no border for this row */
<tr class="noborder">
<td>content1</td>
<td>content2</td>
</tr>
</table>
You can simply add these lines of codes here to hide a row,
Either you can write border:0 or border-style:hidden; border: none or it will happen the same thing
<style type="text/css">
table, th, td {
border: 1px solid;
}
tr.hide_all > td, td.hide_all{
border: 0;
}
}
</style>
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Savings</th>
</tr>
<tr>
<td>Peter</td>
<td>Griffin</td>
<td>$100</td>
</tr>
<tr class= hide_all>
<td>Lois</td>
<td>Griffin</td>
<td>$150</td>
</tr>
<tr>
<td>Joe</td>
<td>Swanson</td>
<td>$300</td>
</tr>
<tr>
<td>Cleveland</td>
<td>Brown</td>
<td>$250</td>
</tr>
</table>
running these lines of codes can solve the problem easily
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?
Something like this will work, depending on your browser support requirements:
tbody::before
{
content: '';
display: block;
height: 15px;
}
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>
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;
}
I had been having trouble with cross-browser support for spacing multiple <tbody>'s using the ::before pseudo-selector if any <td>'s had a rowspan.
Basically, if your <tbody> is 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 your ::before pseudo-selector displays the content as a block like this:
tbody::before
{
content: '';
display: block;
height: 10px;
}
...then this will cause the table to cut off any columns that use rowspan.
The solution is to style ::before pseudo as a table-row:
tbody::before
{
content: '';
display: table-row;
height: 10px;
}
This should have good cross-browser support.
Here's a fiddle
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>
Just set display as block and it will work.
table tbody{
display:block;
margin-bottom:10px;
border-radius: 5px;
}
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>
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 */
}
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.
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!
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.
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.
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>