My friends in the comments informed me there is an old Firefox bug that causes the "visibility: collapse" CSS property to act like the "visibility: hidden" CSS property. This causes the table to be the full size with all of the visible columns shifted to the left and extra space to the right.
With larger tables this undesired behavior is even more drastic.
I just want to be able to toggle the visibility of the table columns and have it look the same on Chrome, Edge, and Firefox which leads to my question: What are some good work arounds to deal with the "Visiblility: Collapse" bug in Mozilla Firefox?
Here is the fiddle:
https://jsfiddle.net/jado66/pgyLm86e/18/
Here is the code in the fiddle:
<html lang="en">
<head>
<meta charset="utf-8">
<style>
th{
border-bottom: 1px solid grey;
}
td{
text-align: center;
}
col{
border: 1px solid grey;
width: 55px;
}
</style>
</head>
<body>
<div style="text-align: center;">
<table style="margin: auto; border: 1px solid black; border-spacing: 0; border-collapse: collapse;">
<colgroup>
<col id = "col_1">
<col id = "col_2">
<col id = "col_3">
<col id = "col_4" style="visibility: collapse">
<col id = "col_5" style="visibility: collapse">
<col id = "col_6">
</colgroup>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
</tr>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
<td>1.6</td>
</tr>
</table>
</div>
</div>
</body>
</html>
As @Richard Deeming has pointed out, this rendering issue is related to the border-collapse: collapse;
property.
If you can do without it and centering is also negligible –
removing the border-collapse: collapse;
property from your table might be a valid compromise.
function hideColumn(columns) {
columns.forEach(function(num, i) {
columns[i] = "#col_" + columns[i];
});
let selectors = columns.join(", ");
// reset previously hidden
let hidden = document.querySelectorAll(".collapsed-col");
hidden.forEach(function(el) {
el.classList.remove("collapsed-col");
});
// hide cells by class
let cells = document.querySelectorAll(selectors);
cells.forEach(function(item, i) {
item.classList.add("collapsed-col");
});
}
// test input
let inputHideColumns = document.querySelector(".inputHideColumns");
inputHideColumns.addEventListener("change", function(e) {
let value = e.target.value.replaceAll(", ", ",");
let columns = value.split(",");
hideColumn(columns);
});
.collapsed-col {
visibility: collapse;
}
table {
border-spacing: 0;
/*
border-collapse: collapse;
margin: auto;
*/
border: 1px solid black;
table-layout: fixed;
}
th {
border-bottom: 1px solid grey;
}
td {
text-align: center;
}
<body>
<div style="text-align: center;">
<table>
<colgroup>
<col id="col_1">
<col id="col_2">
<col id="col_3">
<col id="col_4" class="collapsed-col">
<col id="col_5" class="collapsed-col">
<col id="col_6">
</colgroup>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
</tr>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
<td>1.6</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td>2.3</td>
<td>2.4</td>
<td>2.5</td>
<td>2.6</td>
</tr>
</table>
</div>
<p>
<label>hide columns (comma seperated)</label>
<input class="input inputHideColumns" type="text" placeholder="hide columns (comma seperated)" value="5,4">
</p>
</div>
An alternative approach might be to apply a 'collapsed-col' class to every th/td according to their column.
This approach would require your th
and td
elements to have a dedicated column class like col_1
, col_2
etc.
function indexColumns(table) {
let rows = table.querySelectorAll("tr");
rows.forEach(function (row, r) {
let cols = row.querySelectorAll("th, td");
cols.forEach(function (col, c) {
col.classList.add("tr_" + r);
col.classList.add("col_" + (c + 1));
});
});
}
function hideColumn(columns) {
columns.forEach(function (num, i) {
columns[i] = ".col_" + columns[i];
});
let selectors = columns.join(", ");
// reset previously hidden
let hidden = document.querySelectorAll(".collapsed-col");
hidden.forEach(function (el) {
el.classList.remove("collapsed-col");
});
// hide cells by class
let cells = document.querySelectorAll(selectors);
cells.forEach(function (item, i) {
item.classList.add("collapsed-col");
});
}
// index th/td elements by setting class
let table = document.querySelector('table');
indexColumns(table);
hideColumn([4, 5]);
// test input
let inputHideColumns = document.querySelector(".inputHideColumns");
inputHideColumns.addEventListener("change", function (e) {
let value = e.target.value.replaceAll(", ", ",");
let columns = value.split(",");
hideColumn(columns);
});
.layout {
width: 50%;
margin: 0 auto;
}
table {
border-spacing: 0;
border-collapse: collapse;
margin: auto;
border: 1px solid black;
}
th {
border-bottom: 1px solid grey;
}
td {
text-align: center;
}
.collapsed-col {
display: none;
}
<body>
<div class="layout">
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
</tr>
</thead>
<tbody>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
<td>1.6</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td>2.3</td>
<td>2.4</td>
<td>2.5</td>
<td>2.6</td>
</tr>
</tbody>
</table>
</div>
<p>
<label>hide columns (comma seperated)</label>
<input class="input inputHideColumns" type="text" placeholder="hide columns (comma seperated)" value="5,4">
</p>
</div>