How can I achieve this kind of table:
Inside the Schedule column, there are sub columns (Jan, Feb and so on).
I tried <th></th> inside a <th></th>
But it is not working.
See my fiddle: http://jsfiddle.net/TAJzY/1/
The solution is colspan="" and rowspan="":
Use colspan="12" on the "Schedule/Milestone of Activities" cell.
And remove the 12 empty trailing cells in the same <tr> row.
Use rowspan="2" on the "Estimated Budget" cell.
And remove the single empty initial <th> cell from the <tr> below.
Don't forget to use explicit <thead>, <tbody>, and optional <tfoot> sections.
While you can use HTML tables without explicit sections, styling HTML tables with CSS is a lot easier and effective this way, and you can use techniques like thead { position: sticky; } for Excel-style "frozen" rows which are otherwise very difficult - or just tedious - to implement otherwise.
Step 1:
First, make a table, without any splitting/merging of cells, so you have something like this (click the "Run code snippet" button below to see the table):
table { border: 1px outset #bbb; }
table > * > tr > * { border: 1px inset #bbb; }
thead { background-color: #7ACABD; text-align: center; }
tbody { background-color: #e0fffa; }
tfoot { background-color: #39c4ae' }
<table>
<thead>
<tr>
<th>Estimated Budget</th>
<th>Schedule/Milestone of Activities</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<th></th>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
<th>Apr</th>
<th>May</th>
<th>Jun</th>
<th>Jul</th>
<th>Aug</th>
<th>Sep</th>
<th>Oct</th>
<th>Nov</th>
<th>Dec</th>
</tr>
</thead>
<tbody>
<tr>
<td>$123</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
<tr>
<td>$456</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
</tbody>
</table>
Step 2:
Then make the "Schedule/Milestone of Activities" cell span all 12 remaining columns (of the 13 total) with colspan="12" - which also means removing the empty trailing <th></th> elements in the same <tr> as those are now represented by the <th colspan="12"> cell:
table { border: 1px outset #bbb; }
table > * > tr > * { border: 1px inset #bbb; }
thead { background-color: #7ACABD; }
tbody { background-color: #e0fffa; }
tfoot { background-color: #39c4ae' }
<table>
<thead>
<tr>
<th>Estimated Budget</th>
<th colspan="12">Schedule/Milestone of Activities</th>
</tr>
<tr>
<th></th>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
<th>Apr</th>
<th>May</th>
<th>Jun</th>
<th>Jul</th>
<th>Aug</th>
<th>Sep</th>
<th>Oct</th>
<th>Nov</th>
<th>Dec</th>
</tr>
</thead>
<tbody>
<tr>
<td>$123</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
<tr>
<td>$456</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
</tbody>
</table>
Step 3:
To make the "Estimated Budget" cell span those 2 rows in <thead> add rowspan="2" and also remove the empty initial <th></th> in the second <tr> (as that empty <th> cell's "slot" is now taken by the <th rowspan="2"> from the previous row).
Like so:
table { border: 1px outset #bbb; }
table > * > tr > * { border: 1px inset #bbb; }
thead { background-color: #7ACABD; }
tbody { background-color: #e0fffa; }
tfoot { background-color: #39c4ae; }
/* Right-align budget numbers in the first column: */
table > tbody > tr > td:first-child { text-align: right; }
<table>
<thead>
<tr>
<th rowspan="2">Estimated Budget</th>
<th colspan="12">Schedule/Milestone of Activities</th>
</tr>
<tr>
<th>Jan</th>
<th>Feb</th>
<th>Mar</th>
<th>Apr</th>
<th>May</th>
<th>Jun</th>
<th>Jul</th>
<th>Aug</th>
<th>Sep</th>
<th>Oct</th>
<th>Nov</th>
<th>Dec</th>
</tr>
</thead>
<tbody>
<tr>
<td>$123</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
<tr>
<td>$456</td>
<td>j</td>
<td>f</td>
<td>m</td>
<td>a</td>
<td>m</td>
<td>j</td>
<td>j</td>
<td>a</td>
<td>s</td>
<td>o</td>
<td>n</td>
<td>d</td>
</tr>
</tbody>
</table>
You use the colspan attribute on the Schedule th. It would make it to span over many columns.
Using rowspan for the Budget th will have the same effect on rows.
Try this (note use of colspan):
<table border="1">
<tr>
<td>budget</td>
<td colspan="3">header</td>
</tr>
<tr>
<td></td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
</table>
You can use my http://blocknote.net editor if you need more complex table layout. Table editor there is pretty convenient.
<table>
<tr>
<td>foo</td>
<td colspan="3">Header</td>
</tr>
<tr>
<td></td>
<td>Content</td>
...
</tr>
<tr>
<td>foo1</td>
<td>foo2</td>
...
</tr>
</table>
Related
I have 2 tables with same class elements like:
/* and css to make number increases in Numbers List col */
.myTbl tbody {
counter-reset: rowNumber;
}
.myTbl tbody tr {
counter-increment: rowNumber;
}
.myTbl tbody tr td:nth-child(1)::before {
content: counter(rowNumber);
min-width: 1em;
margin-right: 0.5em;
}
<div class="tableRow">
<table class="myTbl">
<thead>
<tr>
<td>Numbers List</td>
<td>Content</td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>A</td>
</tr>
<tr>
<td></td>
<td>B</td>
</tr>
<tr>
<td></td>
<td>C</td>
</tr>
</tbody>
</div>
<div class="tableRow">
<table class="myTbl">
<thead>
<tr>
<td>C</th>
<td>D</th>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</div>
I want the css only active in specific table like table 1 , but I'm having duplicate classes. How to do it?
And I cant affect the html table like change class or add id,... cause It's exported from other, only js or jquery to do it.
I tried adding ::nth-child(1) not working, is there a way same like eq() in js?
:first-child or nth-child(1) are actually work, you need to select from the parent
body .myTbl:first-child tbody {
counter-reset: rowNumber;
background: yellow
}
<table class="myTbl">
<thead>
<tr>
<td>Numbers List</td>
<td>Content</td>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
</tbody>
<table class="myTbl">
<thead>
<tr>
<th>C</th>
<th>D</th>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>4</td>
</tr>
</tbody>
First, you had unclosed tags.
Second, Using pseudo selectors is the key. But there is a difference between :first-child & :first-of-type.
/* and css to make number increases in Numbers List col */
.myTbl tbody {
counter-reset: rowNumber;
}
.myTbl tbody tr {
counter-increment: rowNumber;
}
/* OR :first-child */
.myTbl:first-of-type tbody tr:first-of-type td::before {
content: '•';
min-width: 1em;
margin-right: 0.5em;
}
<table class="myTbl">
<thead>
<tr>
<td>Numbers List</td>
<td>Content</td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td>A</td>
</tr>
<tr>
<td></td>
<td>B</td>
</tr>
<tr>
<td></td>
<td>C</td>
</tr>
</tbody>
</table>
<table class="myTbl">
<thead>
<tr>
<td>C</td>
<td>D</td>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
I have a table generated in a backend. My task is to wrap text in each header column and add it to each body column cells by using .html() and .prepend(). It works as expected (you will see text in green).
Problem: If there are 2 independent tables in a page, it will be mess up. Green text in the first table looks as expected, but it will take header text from the first table and add to body column cells of second table as an image below:
The 2 tables should be like the image below
How to fix this issue, please give me a hand. Thanks
$(document).ready(function() {
$("table thead tr th").each(function(i) {
let bodyCode = $("<span>", {
text: $(this).text()
});
$(`table tbody tr td:nth-child(${i+1})`).prepend(bodyCode);
});
});
table {
width: 100%;
border: 1px solid gray
}
span {
color: green
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>
<table>
<thead>
<tr>
<th>Day</th>
<th>Earn</th>
</tr>
</thead>
<tbody>
<tr>
<td>Monday</td>
<td>$100</td>
</tr>
<tr>
<td>Tuesday</td>
<td>$80</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
</p>
<table>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
<td>$200</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
<td>$180</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
The main issue is that you need to loop through each table first.
So this code:
Gets each table element in the each.
Gets the th elements in that specific table using each
Gets the text you want from the th element and sets it to <span> tag
Then gets the current th element, finds its parent (table), and then finds each td element.
$(document).ready(function() {
// Loop through each table
$("table").each(function() {
// find all the tds in each table
let th = $(this).find('thead tr th');
// Loop through each th in the table
th.each(function(i) {
let bodyCode = $("<span>", {
text: $(this).text()
});
// find the td elements in this specific table.
$(this).parents('table').find(`tbody td:nth-child(${i+1})`).prepend(bodyCode);
});
});
});
table {
width: 100%;
border: 1px solid gray
}
span {
color: green
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Day</th>
<th>Earn</th>
</tr>
</thead>
<tbody>
<tr>
<td>Monday</td>
<td>$100</td>
</tr>
<tr>
<td>Tuesday</td>
<td>$80</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
<br>
<table>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
<td>$200</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
<td>$180</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
<p> added extra tables for proof of concept</p>
<table>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
<td>$200</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
<td>$180</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
<br>
<table>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
I made a table inside a div to make it scrollable;
<div style="overflow-y: scroll; height:100px; width:100px;">
<table
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
</tbody>
</table>
</div>
This table is scrollable from top to bottom. How can I make the table's overflow start at the bottom and make it scroll upwards?
You need to use javascript for this. Using scrollTop for accessing the scroll offset from the top (default is 0). So you have to get the div's height and set the scrollTop of the div to its height. To get the height, I used getBoundingClientRect().height
let tableDiv = document.getElementById('main');
tableDiv.scrollTop = tableDiv.getBoundingClientRect().height;
<div id="main" style="overflow-y: scroll; height:100px; width:100px;">
<table
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
</tbody>
</table>
</div>
Your HTML content:
<div class="scorllable-table" id="scrollTable">
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
<tr>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>t</td>
<td>t</td>
</tr>
</tbody>
</table>
</div>
Your CSS content:
.scorllable-table {
overflow-y: scroll;
height: 100px;
width: 100px;
}
If you want to do this using JavaScript only, then please try with this.
var scrollableDiv = document.getElementById("scrollTable");
scrollableDiv.scrollTop = scrollableDiv.scrollHeight;
If you want to do this using jQuery, then use the below code.
$("#scrollTable").scrollTop($("#scrollTable")[0].scrollHeight);
If you want to smooth scroll, then try with this.
$('#scrollTable').stop().animate({
scrollTop: $('#scrollTable')[0].scrollHeight
}, 500);
Enjoy, Thanks. :)
I have a very basic table, made up of 3 rows and 3 columns, and i'm trying to make it look like in this picture
(that is, the thead should be wider than the other rows). How do i achieve this effect? I tried with colspan but i can't get it right. The basic table is something like:
<table>
<thead>
<tr>
<th>Extra details</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>
Thanks!
You need to add colspan="3" to the th (number of cols must be identical in all tr in a table). Then make every last td in each tr much wider than the first two (using :last-child pseudo selector, see https://developer.mozilla.org/en-US/docs/Web/CSS/:last-child).
table {
width: 100%;
}
thead th {
background-color: #ddd;
}
td:last-child {
width: 60%;
}
<table>
<thead>
<tr>
<th colspan="3">Extra details</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>
you may use colspan and add a virtual forth col of 50% width:
tbody tr:after {
content: '';
display: table-cell;
width:50%
}
th {
background: gray;
border: solid;
}
table {
width: 100%;
}
<table>
<thead>
<tr>
<th colspan="4">Extra details</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>
You can use the caption element, which spans the table's width and is more semantically correct in your situation since it describes the entire table. Then use a pseudo-element to fill the remaining space in the rows and collapse the other columns.
table {
width: 100%;
}
caption {
border: 2px solid darkgray;
background-color: lightgray;
}
tr:after {
display: table-cell;
content: "";
width: 100%;
}
<table>
<caption>Extra details</caption>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>
How can I make the table header appear on the left side of the table as a column instead on the top as a row? I have this markup:
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
Just use <th> as the first element in the row. Then add the scope attribute, which has no visual impact, but you could use it e.g. in CSS.
<table>
<tbody>
<tr>
<th scope="row">A</th>
<td>b</td>
</tr>
<tr>
<th scope="row">C</th>
<td>d</td>
</tr>
</tbody>
</table>
See also http://www.w3.org/TR/WCAG20-TECHS/H63
How's this?
Example
CSS
thead {
float: left;
}
thead th {
display: block;
}
tbody {
float: right;
}
jsFiddle.
Update
Well, the 1, 2 should also be as column, obviously.
jsFiddle.
It also looks like IE baulks at this. You may have to trade semantic-ness for cross browser compatibility.
You can see the result here. You mean like this?
<table border="1">
<thead>
<tr>
<th></th>
<th colspan="2">Letters</th>
</tr>
<tr>
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">Numbers</td>
<td>1</td>
<td>4</td>
</tr>
<tr>
<td>2</td>
<td>5</td>
</tr>
<tr>
<td>3</td>
<td>6</td>
</tr>
</tbody>
</table>
You usually use rowspan and colspan for cells spanning multiple columns/rows.
I needed something a little different, but the answers by #alex and #marion got me started in the right direction. The problem was that when you needed many items in the table, the "columns" started stacking funny on smaller screens.
Thanks to Serge for his answer here that led me in this solution. This solution allows for scrolling horizontally and doesn't stack funny regardless of the size of the screen/window. I tested it in Chrome, Firefox, Opera, Edge, and IE11. Here's the fiddle with the correct alignment for the new "rows" and "columns": https://jsfiddle.net/berrym/6r3zvaef/21/
And just in case it disappears from JSFiddle:
<style>
table{
display:block;
white-space:nowrap;
width:100%;
}
td, th {
border-bottom: 1px solid red;
border-collapse: collapse;
}
thead {
float: left;
background: yellow;
width: 10%;
}
thead tr {
width:100%;
float:left;
}
thead th {
display: block;
}
tbody {
float: left;
width: 90%;
}
tbody tr {
display: inline-block;
}
tbody td {
float:left;
width:100%;
}
</style>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
</tbody>
</table>
This worked perfectly for me : (inspired from the first answer)
Example here
html :
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
</tr>
</thead>
<tbody>
<tr>
<td>a1</td>
<td>b1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
</tr>
<tr>
<td>a3</td>
<td>b3</td>
</tr>
</tbody>
</table>
css :
table, td, th {
border: 1px solid red;
}
thead {
float: left;
}
thead th {
display: block;
background: yellow;
}
tbody {
float: left;
}
tbody tr {
display: block;
float: left;
}
tbody td {
display: block;
}
If you use bootstrap, you can achieve this easily with the table-reflow style: http://v4-alpha.getbootstrap.com/content/tables/#reflow