Table Column width must be same for two tables - html

There are two tables with width 600px and 5 Columns each. But, width has not been set for each column. Here, I want to make columns width must be same in both the tables. You can use CSS or jQuery. And, I dont want to fix the column width manually.
HTML Example:
<table width="600" border="1" cellspacing="0" cellpadding="0">
<tr>
<td>hdng 1</td>
<td>hdng 2</td>
<td>hdng 3</td>
<td>hdng 4</td>
<td>hdng 5</td>
</tr>
</table>
<table width="600" border="1" cellspacing="0" cellpadding="0">
<tr>
<td>content content content</td>
<td>con</td>
<td>content content content</td>
<td>content content content</td>
<td>content content content</td>
</tr>
</table>
Any help would be highly appreciated.

If you want all columns are in the same width, and since you're sure that you'll have exactly five columns in each table, I would suggest:
<table style="table-layout:fixed">
<col style="width:20%" span="5" />
<tr><!--stuffs...--></tr>
</table>

I know this question is a year old, but there is a way to do what you're asking!
Inside the table tag, you can use thead and tbody tags to group rows. You can also have multiple tbody tags, which allows you to keep the width the same (as they will be the same table), but style differently as required (or in my case, show and hide).
Example HTML can be found in this answer, copied for retnension https://stackoverflow.com/a/3076790/89211
<table>
<thead>
<tr><th>Customer</th><th>Order</th><th>Month</th></tr>
</thead>
<tbody>
<tr><td>Customer 1</td><td>#1</td><td>January</td></tr>
<tr><td>Customer 1</td><td>#2</td><td>April</td></tr>
<tr><td>Customer 1</td><td>#3</td><td>March</td></tr>
</tbody>
<tbody>
<tr><td>Customer 2</td><td>#1</td><td>January</td></tr>
<tr><td>Customer 2</td><td>#2</td><td>April</td></tr>
<tr><td>Customer 2</td><td>#3</td><td>March</td></tr>
</tbody>
<tbody>
<tr><td>Customer 3</td><td>#1</td><td>January</td></tr>
<tr><td>Customer 3</td><td>#2</td><td>April</td></tr>
<tr><td>Customer 3</td><td>#3</td><td>March</td></tr>
</tbody>
</table>

I ran into this same issue and I found a kind of unclean, but working method.
Using JavaScript, you can momentarily combine both tables to get the desired auto-adjusted column widths and apply these widths to the elements in the two tables. After applying the widths to both tables in rows that aren't going to be removed, you can remove the rows you added to the combination table.
It's easiest if both tables are selectable individually (I just added ids) and if you can group the rows that you add to one table (I used tbody tags) so you can easily remove what you've added.
Hope this helps someone even though it's eight years late for the original post!
//add table 2 to table 1
$("#table1").append($("#table2 tbody").clone(true));
let table1_elems = $("#table1 tr:first td");
let table2_elems = $("#table2 tr:first td");
$(table1_elems).each(function(i) {
//get the column width from the combined table and apply to both tables
//(first one seems redundant, but is necessary once rows are removed)
$(this).width($(this).width());
$(table2_elems[i]).width($(this).width());
});
//remove the added rows
$("#table1 tbody:last").remove();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table1" width="600" border="1" cellspacing="0" cellpadding="0">
<tr>
<td>hdng 1</td>
<td>hdng 2</td>
<td>hdng 3</td>
<td>hdng 4</td>
<td>hdng 5</td>
</tr>
</table>
<table id="table2" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>content content content</td>
<td>con</td>
<td>content content content</td>
<td>content content content</td>
<td>content content content</td>
</tr>
</tbody>
</table>

You are looking for table-layout:fixed
see example:
http://jsfiddle.net/RsAhk/

Table cell width is dependent on its content if the width is not given via style.
By default, most browsers use an automatic table layout algorithm. The
widths of the table and its cells are adjusted to fit the content.
If you want to have an exact width to table cells of different tables then first understand the following description.
Table and column widths are set by the widths of the table and col
elements or by the width of the first row of cells. Cells in
subsequent rows do not affect column widths. Under the "fixed" layout
method, the entire table can be rendered once the first table row has
been downloaded and analyzed. This can speed up rendering time over
the "automatic" layout method, but subsequent cell content might not
fit in the column widths provided. Cells use the overflow property to
determine whether to clip any overflowing content, but only if the
table has a known width; otherwise, they won't overflow the cells.
CSS
table{
table-layout:fixed; /* same width will be applied to both the tables*/
}
table td {
width:20%; /*20% width for 5 td elements*/
}
for more information https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout

If you know that each table will have exactly 5 columns, applying width: 20% is your best bet:
td {
width: 20%;
}
But if you can have any number of columns, you can instead write a simple JQuery script to figure out how many columns there are and set the widths accordingly.
Here is a JSFiddle demo. I modified the HTML to add id="first" to the first table, so I could get a concrete reference to it. Then the JavaScript is this:
var num = $("table#first tr:first-child > td").length;
var width = (100 / num) + "%";
$("td").css("width", width);​
Basically it grabs the first row of the #first table and counts the number of columns. Then it finds the corresponding percentage width for that number of columns. Then it applies that width to all <td> elements.
This will work as long as there are no colspan defined on the tds, which would throw off the column count. The columns will be equal since you've defined an explicit width on both tables.

We can move all the second table rows to the first table. Then set table cell width style to fix column width. After do this, we can move back the rows to the seconds table.
And if the table has images or fonts, you should do the work after they loaded.
/**
* Align two table column width
* #param {HTMLTableElement} table1
* #param {HTMLTableElement} table2
*/
function fixTableCellWidth (table1, table2) {
// container means `thead` or `tbody`
const sourceContainers = Array.from(table2.children);
const sourceTrs = sourceContainers.map(container => Array.from(container.children));
// move second table rows to first table
sourceTrs.forEach(trs => {
trs.forEach(tr => {
table1.lastElementChild.appendChild(tr);
});
});
// fix table cell width
Array.from(table1.children).forEach(container => {
Array.from(container.children).forEach(tr => {
Array.from(tr.children).forEach(td => {
if (td.style.width) return;
const rect = td.getClientRects()[0];
td.style.width = `${rect.width}px`;
});
});
});
// move back the second table rows
sourceTrs.forEach((trs, index) => {
const container = sourceContainers[index];
trs.forEach(tr => {
container.appendChild(tr);
});
});
}
// Call `fixTableCellWidth` after ready
document.addEventListener('DOMContentLoaded', () => {
fixTableCellWidth(document.getElementById('table1'), document.getElementById('table2'));
});
* {
box-sizing: border-box;
}
table {
border-collapse: collapse;
}
table td {
border: 1px solid;
}
First Table:
<table id="table1" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>hdng 1</td>
<td>hdng 2</td>
<td>hdng 3</td>
<td>hdng 4</td>
<td>hdng 5</td>
</tr>
</tbody>
</table>
Second Table:
<table id="table2" width="600" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>content content content</td>
<td>con</td>
<td>content content content</td>
<td>content content content</td>
<td>content content content</td>
</tr>
</tbody>
</table>

Define any css class and format the it and then use that class on both the tables e-g
your temp.css
.anyClass tr td{
width: 150p;
etc...
}
and in HTML file
<table id="table1" class="anyClass">
......
......
</table>
<table id="table2" class="anyClass">
......
......
</table>

I created this in jQuery for my div tables where I have two tables and table-cells are labels and form fields.
jQuery:
$(".table").last().children().find("label").css("table", $(".table").first().children().find("label").css("width"));
CSS:
.table {display:table;}
.table div {display: table-row;}
.table .formTitle {text-align: center;display: table-caption;}
.table select,
.table input,
.table label {display: table-cell;}
HTML:
<div class="table">
<div class="formTitle"><span id="txtBI"></span></div>
<div class="visTog"><label></label><input type="text" id="EntName"></div>
<div class="visTog opac"><label></label><select id="EntYear"></select></div>
<div class="visTog opac"><label></label><select id="EntMonth"></select></div>
<div class="visTog opac"><label></label><select id="EntDay"></select></div>
</div>
<div class="table">
<div class="visTog locrdsC formTitle"><span id="txtCalVal"></span></div>
<div class="visTog locrdsC"><label></label><input type="text" name="gmt" id="EntposGMT" class="locrds"></div>
<div class="visTog locrdsC"><label></label><input type="text" name="EntJday" id="EntJday" class="locrds"></div>
</div>
</div>
This has a catch though. Could write a script to measure which one is bigger but in my case that isn't necessary.
I tend to make forms more interactive to improve usability; hence the visibility toggle and opacity classes, but are of no consequence to the cell width function.

You can sync the column widths by combining the tables with a tbody for each (as suggested by #Relequestual), and using <th scope="rowgroup"> for the headers:
table {
border-collapse: collapse;
}
table thead,
table tbody {
border-bottom: solid;
}
table tbody th {
text-align: left;
}
<table>
<thead>
<tr> <th> ID <th> Measurement <th> Average <th> Maximum
<tbody>
<tr> <td> <th scope=rowgroup> Cats <td> <td>
<tr> <td> 93 <th scope=row> Legs <td> 3.5 <td> 4
<tr> <td> 10 <th scope=row> Tails <td> 1 <td> 1
<tbody>
<tr> <td> <th scope=rowgroup> English speakers <td> <td>
<tr> <td> 32 <th scope=row> Legs <td> 2.67 <td> 4
<tr> <td> 35 <th scope=row> Tails <td> 0.33 <td> 1
</table>
Source: Example in the HTML spec itself

Related

How to set HTML table column widths as a percentage (without table footer affecting table body)?

I'm really having a hard time understanding how to style column widths in a HTML table. I can't get my head around why percentage widths aren't applying and why columns inside tfoot affect column widths in tbody.
Can anyone shed some light on this and perhaps explain how I can make the columns within the tbody be set to one-third (33.333%) and columns in the tfoot be set to one-half (50%) and actually span the full width of the table (right now they only span across 2 columns above, rather than 3 columns)?
Any help/guidance would be most appreciated.
tbody,
tfoot {
width: 100%;
}
tbody tr td {
width: 33.333%;
}
tfoot tr th,
tfoot tr td {
width: 50%;
}
<table border="1">
<tbody>
<tr>
<td>Body Row 1 Column 1</td>
<td>Body Row 1 Column 2</td>
<td>Body Row 1 Column 3</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Footer Row 1 Column 1</th>
<td>Footer Row 1 Column 2</td>
</tr>
<tr>
<th>Footer Row 2 Column 1</th>
<td>Footer Row 2 Column 2</td>
</tr>
<tr>
<th>Footer Row 3 Column 1</th>
<td>Footer Row 3 Column 2</td>
</tr>
</tfoot>
</table>
If you are not restricted so that you have to use one table, why not just a table inside a table?
<tfoot>
<tr>
<td colspan="3">
<table>
<tbody>
<tr>
<td>First half</td>
<td>Second half</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tfoot>
Just make sure the styling applies just as well and give your table table { width: 100%; }, no border, margin, padding, etc..
I find the best solutions are those where you ignore the problem.

Prevent collapse of empty rows in HTML table via CSS

I have a HTML table as follows:
<table border="1">
<tr>
<td>Row with text</td>
</tr>
<tr>
<td></td><!-- Empty row -->
</tr>
</table>
When you run this you'll see the second row is collapsed, but I'd rather it was rendered uncollapsed, with the same height as the first row. One way of doing this is to put a entity, as follows:
<table border="1">
<tr>
<td>Row with text</td>
</tr>
<tr>
<td> </td><!-- Empty row -->
</tr>
</table>
Is there a way I can achieve the second result, via CSS, using the HTML from the first snippet?
You can use this code:
td:empty::after{
content: "\00a0";
}
It adds escaped after every originally empty td, solving your issue.
td:empty::after{
content: "\00a0";
}
<table border="1">
<tr>
<td>Row with text</td>
</tr>
<tr>
<td></td><!-- Empty row -->
</tr>
<tr>
<td>asd</td>
</tr>
<tr>
<td>dees</td>
</tr>
<tr>
<td></td><!-- Empty row -->
</tr>
</table>
Learn more about escaping HTML entities here.
You can add height to table-cell, in this case it'll work like min-height property for other elements (with display: block, display: inline-block, etc). I added another table row with long text to demonstrate it:
td {
height: 22px;
}
<table border="1">
<tr>
<td>Row with text</td>
</tr>
<tr>
<td></td><!-- Empty row -->
</tr>
<tr>
<td>Very-very long text with many words, Very-very long text with many words, Very-very long text with many words, Very-very long text with many words, Very-very long text with many words</td>
</tr>
</table>
You can't use min-height property, because the specification says:
In CSS 2.1, the effect of 'min-height' and 'max-height' on tables, inline tables, table cells, table rows, and row groups is undefined.
Try adding to your table CSS formatting like
table.someclass tbody td {
white-space:nowrap;
min-width:30px;
vertical-align:top;
}
This will make all empty cells equal and at least 30px wide.
Things like , nowrap and CSS content appending like content: "\00a0"; didn't work for me.

html table colspan not working as expected

HTML concepts are so terrible sometimes.
This is my code using colspan in html table, and doesn't look as I expect.
<table border="1">
<tr>
<td colspan="3">a</td>
</tr>
<tr>
<td colspan="2">b</td>
<td>c</td>
</tr>
</table>
What I want is: cell 'a' should look 3 cell wide, cell 'b' should look 2 cell wide, cell 'c' should look 1 cell wide.
What it is doing is: cell 'a' is 2 cells wide, cell 'b' & 'c' is 1 cell wide.
Any Suggestions thanks.
Attribute colspan determines how many columns a cell overlaps with respect to other cells, not the absolute size of those columns. In your case, span 2 has two spans. how you can say it is not? don't judge it by width of a cell. span is not the width. You have to add another smaller columns to appear it as a column of two spans.
See the solution for your expectation in code snippet last example.
<h3>Example 1</h3>
<table border="1">
<tr><td>col1</td><td>col2</td><td>col3</td></tr>
<tr><td colspan="3">a</td></tr>
<tr><td colspan="2">b</td><td colspan="1">c</td></tr>
</table>
<h3>Example 2</h3>
<table border="1">
<tr><td width="80px">wide col1</td><td>col2</td><td>col3</td></tr>
<tr><td colspan="3">span 3</td></tr>
<tr><td colspan="2">span 2</td><td colspan="1">span 1</td></tr>
</table>
<h3>Your case</h3>
<table border="1">
<tr><td colspan="3">span 3</td></tr>
<tr><td colspan="2" width="66%">span 2</td><td width="33%">span 1</td></tr>
</table>
You have already answered your question as your code is working fine but your max count is only 2. If you add another row you can see the desired results.
table {
width: 300px;
]
<table border="1">
<tr>
<td colspan="3">column 1</td>
</tr>
<tr>
<td colspan="2">column 2</td>
<td>column 3</td>
</tr>
<tr>
<td>column n</td>
<td>column n</td>
<td>column n</td>
</tr>
</table>
table {
width: 200px;
}
<table border="1">
<tr>
<td>column</td>
<td>column</td>
<td>column</td>
</tr>
<tr>
<td colspan="3">column 1</td>
</tr>
<tr>
<td colspan="2">column 2</td>
<td>column 3</td>
</tr>
</table>
Your code will show the desired result just as you will add another row!!!
So colspans do exactly what they're intended for. There are n columns in the table and each table cell <td> is one column wide. Using colspan spans the cell over more columns. This has nothing to do to each column's width.
If you wish for all columns to be of the same width, you have to use some styling.
Even though it might be easier to use some CSS grid, a solution for table is as follows:
/* You can make a separate file where you calculate n dynamically and you just
* link the file with :root { ... } into html <head> */
:root {
--n: 3; /*number of columns */
}
div {
/* container for mobile because max-width only works on block elements */
width: 30em;
max-width: 100%;
}
table {
/* table takes the whole container */
width: 100%;
}
/* the following is enough for this example */
/* td:not([colspan]) {
width: calc(100% / var(--n));
} */
/* if you don't have any (or well enough placed) table cells without colspan
* attribute, then you have to calculate each possibilty like so: */
td {
width: calc(100% / var(--n));
}
td[colspan="2"] {
width: calc(100% * 2 / var(--n));
}
td[colspan="3"] {
width: calc(100% * 3 / var(--n));
}
/* and so forth up to maximum possible n */
<div>
<table border=1>
<tr>
<td colspan=2>b</td>
<td>a</td>
</tr>
<tr>
<td colspan=3>c</td>
</tr>
</table>
</div>

Make borders for nonexistent spaces in table when using ng-repeat

I'm trying to make a table in HTML using bootstrap. The table consists of 2 columns, the first being a string and the other being an array of strings. Each row has it's border but some rows don't have enough elements so that the border goes across the whole table. Here's a screenshot of what I mean ...
Notice how the lines seperating the rows get cut off when the data ends. How would I get the lines that separate the rows to stretch across the whole table? This is a snipet of my code
<div style="overflow:auto; height:150px; width:75%; margin: 0 auto; margin-top:10px" ng-hide="show1">
<table class="table table-hover" style="width:auto">
<thead>
<tr>
<th>Name</th>
<th style="min-width: 150px">Family Members</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="name in names = (family | nameFilter: searchName)">
<td style="min-width: 150px"><a ng-click="findMe(name.Name)">{{name.Name}}</a></td>
<td style="min-width: 150px" ng-repeat="userName in name.User">{{userName.Name}}</td>
</tr>
</tbody>
</table>
</div>
You may want to look at this answer. Then use that info to add a colspan with a very large number (say, 200) to the final <td> of the row. That will make it expand to the length of the longest row in the table.
So your <tbody> will end up something like this:
<tbody>
<tr>
<td>First link</td>
<td>Name 1</td>
<td>Name 2</td>
<td colspan="200">Name 3</td>
</tr>
<tr>
<td>Second link</td>
<td>Name 1</td>
<td colspan="200">Name 2</td>
</tr>
...
</tbody>
I don't think that these should actually be table cells, but no matter. You can create a function to calculate the longest list of usernames.
<td ng-repeat="i in new Array(longestList() - name.User.length)></td>

How to wrap long HTML table cell

I have a table with two rows. The second row consists of a long text in a colspan="2". How can this text be wrapped so the table is not wider then the two first row cells? I can't set a fixed width for the table, because the first two cells are dynamic.
http://jsfiddle.net/qLpuq/1/
<table>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td colspan="2" style="width: 0" >Very long cell that should just be as long as the first two cells and wrap, but not take all the screen width.</td>
</tr>
</table>
I wrongly assumed, that style="width: 0" would work on that cell.
I’m afraid there’s no direct solution. You could play with JavaScript, creating copy of the table containing only the first row, get its width, discard the copy, and use the width to set the width of your real table. Combined with the setting table-layout: fixed, this should handle the situation. You can simplify the approach so that you do not create a copy of the table but instead remove the second row, later add it back. It gets rather ugly:
<!doctype html>
<title>Hack</title>
<style>
table { table-layout: fixed }
tr:first-child td { white-space: nowrap }
</style>
<table id=tbl>
<tbody id=tbody>
<tr>
<td id=cell1>Cell 1</td>
<td id=cell2>Cell 2</td>
</tr>
<tr id=row2><td colspan=2>
Very long cell that should just be as long as the first two cells and
wrap, but not take all the screen width.
</table>
<script>
var tbl = document.getElementById('tbl');
var tbody = document.getElementById('tbody');
var row2 = document.getElementById('row2');
var cell1 = document.getElementById('cell1');
var cell2 = document.getElementById('cell2');
tbody.removeChild(row2);
var width = tbl.clientWidth;
var width1 = cell1.clientWidth;
var width2 = cell2.clientWidth;
tbody.appendChild(row2);
cell1.style.width = width1 + 'px';
cell2.style.width = width2 + 'px';
tbl.style.width = width + 'px';
</script>
A completely different idea is to use a workaround where the long text is not in a cell but in a caption element, placed at the bottom of the table:
<table>
<caption align=bottom style="text-align: left">
Very long cell that should just be as long as the first two cells and
wrap, but not take all the screen width.
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
</table>
It might be usefull for you..
<table style="width:300px;" border="1">
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
<tr>
<td colspan="2" style="width: 70%;" >Very long cell that should just be as long as the first two cells and wrap, but not take all the screen width.</td>
</tr>
</table>
Update after question update
<table style="width:100%;" border="1">
<tr>
<td style="width: 50%;">Cell 1</td>
<td style="width: 50%;">Cell 2</td>
</tr>
<tr>
<td colspan="2" style="width: 70%;" >Very long cell that should just be as long as the first two cells and wrap, but not take all the screen width.</td>
</tr>
</table>
Use max-width with the % of colspan2
<table style="width:100%;" border="1">
<tr>
<td style="width: 50%;">Cell 1</td>
<td style="width: 50%;">Cell 2</td>
</tr>
<tr>
<td colspan="2" style="max-width: ??%;" >Very long cell that should just be as long as the first two cells and wrap, but not take all the screen width.</td>
</tr>
</table>