visibility: collapse within a scrollable container produces unwanted scrollbar in Firefox/Edge - html

It seems like wrapper's div height is incorrectly calculated when thead's visibility is set to collapsed in Firefox/Edge. In Chrome there is no scrollbars. Any idea how to fix it?
.table-wrapper {
overflow: auto;
background-color: green;
border: 2px solid black;
}
thead {
visibility: collapse
}
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Head</th>
<th>Head</th>
<th>Head</th>
</tr>
</thead>
<tbody>
<tr><td>Content</td></tr>
<tr><td>Content</td></tr>
<tr><td>Content</td></tr>
</tbody>
</table>
</div>

I think it's likely because the scrollbar's existence is determined before the thead is removed from the flow in those browsers. When I scroll down, the amount of space after the table is about that of the hidden thead.
Best you could do is give your table-wrapper a fixed height larger than the table with the header (hard to determine ahead of time, and likely needs JavaScript).
Or, give the table a max-height of 100% and set its overflow to hidden:
.table-wrapper {
overflow: auto;
background-color: green;
border: 2px solid black;
}
table {
max-height: 100%;
overflow: hidden;
}
thead {
visibility: collapse;
}
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Head</th>
<th>Head</th>
<th>Head</th>
</tr>
</thead>
<tbody>
<tr><td>Content</td></tr>
<tr><td>Content</td></tr>
<tr><td>Content</td></tr>
</tbody>
</table>
</div>
But that kind of defeats the purpose of having overflow: auto on the table-wrapper… You'll need to pick your poison. Or wait until someone smarter than me answers :).

Related

How do I prevent a table from extending past its containers height

I have a table and whenever there are too many rows it goes off the bottom of the page and exceeds its containers height.
<body>
<div class="myContainer">
<table class="scrolldown">
<!-- Table head content -->
<thead class="test1">
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
</tr>
</thead>
<!-- Table body content -->
<tbody class="test2">
<tr>
<td>Content</td>
<td>Content</td>
</tr>...
</tbody>
</table>
</div>
<body>
CSS
.myContainer {
outline-style: solid;
outline-color: #c7d2fe;
height: 100px
}
tbody td,
thead th {
width: 200px;
border-right: 2px solid black;
}
td {
text-align: center;
}
How can I make it so that the table becomes scrollable once it would extend past its containers height?
Fiddle
You can do this by adding overflow: auto; to the wrapper div .myContainer.
This will add a scrollbar to the container when the table is taller.
Fiddle

CSS: How to set minimum and maximum height according to inside?

Suppose I have a table with 100vh height, how to set minimum height for thead according to inside and maximum tbody?
<table style="height: 100vh;">
<thead>...</thead>
<tbody>...</tbody>
</table>
Is this what you look for?
Updated
Did a few tests and noticed giving height to the body didn't work properly cross browser, which below update does (tested on Chrome, Firefox, Edge, IE11)
html, body {
margin: 0;
}
table {
width: 100%;
height: 100vh;
}
table thead tr {
height: 80px; /* on table elements, height works kind of like min-height */
background: yellow;
}
table tbody tr {
background: lime;
}
<table>
<thead>
<tr>
<td>
HEAD<br>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>
BODY
</td>
</tr>
</tbody>
</table>
you can follow the hack to achieve your goal.
Use least height for thead, but not 0.Use 0% for tbody
html,body{
margin:0;
}
table{
width:100%;
height: 100vh;
border: 1px solid black;
}
thead{
background: red;
height:1px;
}
tbody{
background: blue;
height:0%;
}
<table>
<thead>
<tr>
<td colspan="4">
<img src="http://dummyimage.com/100x100/eb00eb/fff">
</td>
</tr>
</thead>
<tbody>
<tr>
<td>BODY</td>
<td>BODY</td>
<td>BODY</td>
<td>BODY</td>
</tr>
</tbody>
</table>

Centered text in fully clickable table cell

This one is driving me mad, unfortunately I'm not very good in CSS yet.
How can I get a horizontally and vertically centered text-link into a table cell which is fully clickable?
I researched, tried several solutions, none of them worked. Here is my best approach so far:
HTML
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
CSS
.dataTable td a {
width: 100%;
height: 100%;
text-align: center;
vertical-align: middle;
display:block;
text-decoration: none;
}
.dataTable td {
display:inline-block;
}
This one gives me centered text, but the link only covers the width of the cell, not the height. If I change the css for the link to display:inline-block, then the full cell is clickable, but the text is not vertically centered anymore.
I need both. Help!
i think you should remove this :
.dataTable td {
display:inline-block;
}
see this fiddle
I think that's what you want:
.dataTable {
text-align: center;
}
.dataTable a {
display: inline-block;
width: 100%;
height: 100%;
}
/* Just for better visualization */
.dataTable td {
background: red;
}
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
If you want to increase td's height, you should do it by modifying a's height. Otherwise, the link will not occupy the whole cell's height. You can achieve that with height property or also with line-height.
.dataTable {
text-align: center;
}
.dataTable a {
display: inline-block;
width: 100%;
height: 100%;
line-height: 5; /* To get a 5 text lines high cell */
}
.dataTable td {
/* Just for better visualization */
background: red;
}
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
Wrap your text in a
div style="padding-top:5px;".
That will center it approximately.

Setting column width in html table doesn't display scrollbar

I'm trying to create an HTML table where the column widths are changed dynamically, and in case the table width becomes larger than the container, a horizontal scrollbar appears.
However, I can't seem to get this to work - when I set the container width, it acts as an upper bound for the table and even though I set a column's width explicitly (either using CSS or Jquery) the table refuses to display the correct width. Even when I set "overflow: scroll", the scrollbar never becomes active.
The table width should also decrease when the column widths become smaller, which is why I can't use table width = 100%.
Note: I know this issue can be bypassed if I explicitly set the table width (e.g. table width=500px) every time a column width changes. I am hoping there is a more elegant solution...
Here is the code:
JFiddle: http://jsfiddle.net/sangil/NdY22/
HTML
<div class="container">
<table>
<thead>
<tr>
<th class="a">th 1</th>
<th>th 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>td 1</td>
<td>td 2</td>
</tr>
</tbody>
</table>
</div>
CSS
table {
table-layout: fixed;
border: 1px solid black;
border-collapse: collapse;
}
table td {
border: 1px solid black;
}
table th {
border: 1px solid black;
background-color: lightsteelblue;
}
.container{
border: 1px solid lightsteelblue;
width: 300px;
overflow: auto;
}
JS
$(function() {
$('.a').width(500);
});
​
Not sure if I understood your question correctly. If you are after scrollbars in table then you can simple do that by using display: block on .a class:
.a {
width: 400px;
display:block;
}
Working DEMO
EDIT:
<div STYLE=" height: 100px; width: 100px; font-size: 12px; overflow: auto;">
<table bgcolor="green">
<tr><td bgcolor="blue">testing </td></tr>
<tr><td>free php scripts;/td></tr>
<tr><td bgcolor="blue">free php scripts</td></tr>
<tr><td>free php scripts</td></tr>
<tr><td bgcolor="blue">free php scripts</td></tr>
</table>
</div>
see reference

HTML Table, first and last column fixed width and columns between dynamic, but equal width

Is it possible to have a table with width 100% (so the table fits the screen size), where the first and the last column have a fixed width, and the columns between take the rest, both 50%.
Like:
+--------------------+--------------------------------------+--------------------------------------+------------+
| width:300px; | with dynamic, equals next column | width dynamic, equals prevous column | width:50px;|
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
Try this:
As you can see the two centre column remain equal sized, due to the table-layout:fixed, even when the content is of different length. Try adding more and less content to the two centre columns.
JSFiddle: http://jsfiddle.net/RtXSh/
CSS
table {
width:100%;
border-collapse:collapse;
table-layout:fixed;
}
td {
border: 1px solid #333;
}
HTML
<table>
<tr>
<td style="width:300px;">
test
</td>
<td>
test test tes test test
</td>
<td>
test
</td>
<td style="width:50px;">
test
</td>
</tr>
</table>
Try using the pseudo element first-child and last-child
If I'm not mistaken the other columns will align equally by themselves. You might need to use the !important statement behind the first-child and last-child widths.
table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
td:first-child{ width: 100px; }
td:last-child{ width: 100px; }
<table>
<tr>
<td>100px</td>
<td>some text</td>
<td>some text</td>
<td>100px</td>
</tr>
</table>
However, as nurettin pointed out, if you use a thead and tbody section you have to style the header. Styling the td:first-child and td:last-child will not work.
table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
th:first-child{ width: 100px; }
th:last-child{ width: 100px; }
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>100px</td>
<td>some text</td>
<td>some text</td>
<td>100px</td>
</tr>
</tbody>
</table>
In my opinion, the simple, nice and easy way is that don't use the px and % together. If you are using table width 100%, then define width of first and last column in % as well. If you are interested in that, here is how you can do:
CSS:
.mytable {
width:100%;
border: 1px solid green;
}
.left{
width:30%;
border-right:1px dashed blue;
}
.mid1{
width:30%;
border-right:1px dashed blue;
}
.mid2{
width:30%;
border-right:1px dashed blue;
}
.right{
width: 10%;
border-left:1px dashed blue;
}
HTML:
<table class="mytable">
<tr>
<td class="left">Left Column, 30%</td>
<td class="mid1">Mid 1, 30% </td>
<td class="mid2">Mid 2, 30% </td>
<td class="right">Right, 10%</td>
</tr>
</table>
This can be handled by adding the style table-layout:fixed to the table element, and simply not specifying any width value for the columns you wish to evenly divide the width remaining after the fixed columns have been accounted for.
Further, using combinations of <colgroup> can provide robust variable-width scenarios.
I've created an example at JSFiddle: https://jsfiddle.net/3bgsfnuL/1/
<div style="position:relative; height:500px; width:100%;">
<table style="height:100%; width:100%; table-layout:fixed; text-align:center; border-collapse:collapse;">
<colgroup colspan="1" style="width:200px"></colgroup>
<colgroup colspan="3">
<col/>
<col style="width:30px"/>
<col/>
</colgroup>
<colgroup colspan="1" style="width:200px"></colgroup>
<tbody>
<tr>
<td style="background-color:silver;">left fixed</td>
<td style="border-right:1px solid black;">col 1</td>
<td style="background-color:red; color:white; border:1px solid black;">col 2</td>
<td style="border-left:1px solid black;">col 3</td>
<td style="background-color:silver;">right fixed</td>
</tr>
</tbody>
</table>
</div>
Nobody mentioned this one here <th> trick:
table{ table-layout: fixed; width: 100%; }
th:first-child{ width: 300px; }
<table>
<thead>
<tr>
<th>yourfirst300pxcolumn</th>
<th>fixedwidth</th>
<th>fixedwidth also</th>
</tr>
</thead>
<tbody>
<tr><td>300</td><td>something</td><td>something else</td></tr>
</tbody>
</table>
Note that in HTML5/CSS3, you can use grid layout to have more control over your tables. It's not that useful for this specific example, with pixel widths, where you can use table-layout:fixed as in Bazzz's answer, but it is useful if you want to use something like min-content.
The following works out of the box on Chrome and Firefox, but not in Safari:
table {
width: 100%;
display: grid;
grid-template-columns: 300px 1fr 1fr 50px;
/* Or, more usefully: */
/* grid-template-columns: min-content 1fr 1fr min-content; */
}
td {
display: block;
}
/* ignore <tr> when laying out the grid; just lay out the cells */
tr {
display: contents;
}
/* browsers can inject <tbody> into the DOM even if it's not in the HTML */
tbody {
display: contents;
}
(Note though that the table border-collapse property doesn't work in this layout, so you may have to fiddle with CSS pseudo-classes like :last-child in order to get your borders to behave the way you want.)
In Safari this doesn't work -- the rows don't break properly. (Although it does work if you use nested <div> elements instead of a <table> and apply similar styles.) However, a simpler layout with just one dynamic 1fr column does work in Safari:
table {
display: grid;
grid-template-columns: 300px 1fr 50px;
}
tbody {
display: contents;
}
tr {
display: contents;
}
td {
border: 1px solid #c0c0c0;
}
What about using jQuery for this and calling javascript function once your table is created or some other event (like click) happens?
See here (I created jsfiddle playground for this)
What it does is that it checks the width of fixed elements (width of the whole table, first and last cell). Then it calculates and assigns the width for the rest of the cells which should have the remaining width divided between them (based on how many there are and how much space is left). Of course this is just quick example of possible solution. It needs polishing (checking null objects, if remaining width is greater than 0, ...)