Problem:
I have a <table> element that I want to dynamically fill 100% of a container's height, without exceeding.
Background:
When the <table> exceeds the container height, I want to be able to scroll through the table-rows. I do not want information above the table to be scrolled off the page.
When my <table> height exceeds the container, the container gets the scroll-bar, and not the <table> itself. This scrolls information above the table off of the page.
Limitations:
I am using <table> elements and do not want to use the <div> display: table approach.
I would also like this to be dynamic, and not set the height to a hard pixel count.
HTML:
<div class="demo-container">
<div class="demo-header">Don't scroll me off the page please</div>
<div class="demo-container>
<div class="table-container">
<table>
<thead>
<tr>
<th>Table Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Rows are populated via API and will expand the table height</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
CSS:
.demo-container {
height: 100%
display: grid;
grid-area: body;
grid-template-areas:
'demo-header'
'demo-container';
grid-template-rows: 60px 1fr;
}
.demo-header {grid-area: demo-header;}
.demo-container {grid-area: demo-container;}
.table-container {
height: 100%
overflow-y: auto;
}
I know that if I set the .table-container's height to pixels, and set overflow-y: auto, I can achieve the desired look.
However, I do not want to do this with pixel heights, and would like a more responsive solution in case things change on the page. Is there any way to do this without exact pixel heights?
Thanks
Here's how you might go about it. How you set up the outer element depends on your overall page structure.
html,
body {
height: 100vh;
margin: 0;
padding: 0;
}
.demo-container {
display: flex;
flex-direction: column;
max-height: 100%;
}
.demo-header {
flex: none;
}
.table-container {
overflow: auto;
}
table {
background: pink;
}
td {
padding: 15px;
border: 1px solid #fff;
}
<div class="demo-container">
<div class="demo-header">Don't scroll me off the page please</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Table Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
<tr>
<td>Pretend that this expands the table height past the container</td>
</tr>
</tbody>
</table>
</div>
</div>
Related
I made a simple table with HTML and CSS, however, the items don't display evenly when you resize your browser.
Screenshot:
As you can see, there is a lot of empty space.
How can I made it so these three rows evenly display across the div box no matter how the user resizes the browser?
I made a jsfiddle:
https://jsfiddle.net/5nm9m9pL/ (looks fine until your stretch the browser)
Code:
HTML
<div class="bet-ids" id="bet-ids">
<table>
<tr>
<th>Username</th>
<th>ID</th>
<th>Profit</th>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>232</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>523</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>4352</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>5234</td>
<td>+0.32423</td>
</tr>
</table>
</div>
CSS:
.bet-ids {
height: auto;
padding: 20px;
width: 60%;
font-family: Helvetica Neue;
color: black;
background-color: white;
}
If by "lots of white space" you mean you want to center it, then you can just add margin: auto to both the table and the div, since your div has a fixed width of 60%
Otherwise if you mean that you want to stretch out the table, then obviously you can't have a width of 60%;
.bet-ids {
height: auto;
padding: 20px;
width: 60%;
margin:auto;
font-family: Helvetica Neue;
color: black;
background-color: white;
}
table {
margin: auto;
}
<div class="bet-ids" id="bet-ids">
<table>
<tr>
<th>Username</th>
<th>ID</th>
<th>Profit</th>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>232</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>523</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>4352</td>
<td>+0.32423</td>
</tr>
<tr>
<td>bitcoincryptopro</td>
<td>5234</td>
<td>+0.32423</td>
</tr>
</table>
</div>
Just add .bet-ids table {width: 100%;} to your CSS: Tables set their width by their content unless you tell them otherwise.
So say I have the following HTML:
<table>
<tr>
<th>Heading:</th><td>text</td>
</tr>
<tr>
<th>Heading 2:</th><td>text</td>
</tr>
<tr>
<th colspan="2">Really long heading:</th>
</tr>
<tr>
<td></td><td>text</td>
</tr>
</table>
This creates a table with two columns, one for headers (left) and one for values (right) - except for one row, where a long header is taking up both columns, and the value is showed in the right most column on the next row. Along with this, I have some styling; most importantly:
td:last-child {
width: 100%;
}
th, td {
white-space:nowrap;
}
This makes it so the right most column takes any extra space. And what I have is working, even though the "really long" header is longer/wider than the header column. However, when I add a few more words to the really long header (but not making it long enough to increase the width of the whole table), after a certain point the width of the left column starts to increase with the length of the long header, decreasing the width of the right column. What's going on?
You can't define width:100% of an cell of a table with multiple column.
You should use colgroup tag to define width of cell:
.col-left {
width: 20%;
}
.col-right {
width: 80%;
}
<table>
<colgroup>
<col class="col-left">
<col class="col-right">
</colgroup>
<tr>
<th>Heading:</th><td>text</td>
</tr>
<tr>
<td colspan="2">Really long heading:</td>
</tr>
<tr>
<th>lorem ispum dolores hello</th><td>text</td>
</tr>
</table>
Another tricks to set a cell at the minimum and obviously the another cell take the rest of the width, are to set the first one at 1px:
table {
width: 200px;
}
th, td {
border: 1px solid #000;
}
th {
width:1px;
}
<table>
<tr>
<th>hello</th>
<td>world</td>
</tr>
<tr>
<td colspan="2">hi</td>
</tr>
<tr>
<td></td>
<td>text</td>
</tr>
</table>
On my website I have a CSS table with two table cells.
One is 400px wide, and I want the other one to take up the rest of the page.
How do I do that? I have tried applying width 100% to it, but that doesn't work on chrome, and width: auto doesn't work at all.
.wrapper{
display: table;
width: 100vw;
max-width: 100vw;
}
[...]
.sidebar{
display: table-cell;
border-right: 1px solid #707070;
width: 400px;
}
[...]
.content{
display: table-cell;
width: 100%;
}
HTML:
<div class="wrapper">
<div class="sidebar">
<!-- Stuff -->
</div>
<div class="content">
<!-- Titles and text, all that usual blog stuff. Oh, and a big, wide header. -->
</div>
</div>
Set your wrapper to be display:table and not display:table-cell because otherwise the wrapper gets an anonymous table wrapper at auto width (shrink to fit for tables).
.wrapper{
display: table;
width: 100%;
table-layout:fixed;
}
I wouldn't use vw for the width either as that includes the scrolbar and will cause a horizontal scrollbar when content is below the fold.
Apply style="width:100%" to the table element, keeping the 400px limit on the first cell. The second cell will expand to meet the table's width.
The table should automatically scale to full width (assuming it's width is 100%), even with one column fixed and the other(s) flexible. I threw up a little test/example # http://jsfiddle.net/41uc6Lsq/1/
<table width="100%">
<thead>
<tr>
<th width="20px">Col 1</th>
<th>Col 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
<table width="100%">
<tbody>
<tr>
<td width="20px">1</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
</tr>
</tbody>
</table>
EDIT: just saw your CSS edit - could you post the HTML too please?
I am trying to design a page where there are some tables. It seems that styling tables is much more painful than it ought to be.
The problem is the following: The tables should have a fixed height and display either white space at the bottom (when there is too little content) or a vertical scrollbar (when there is too much). Add to this that the tables have a header which should not scroll.
As far as I know, the thead not scrolling is the default behaviour for tables. And a stretching tfoot could serve well for the purpose of filling with white space. Sadly, it seems that every constraint I can put on the table height is cheerfully ignored. I have tried
table {
height: 600px;
overflow: scroll;
}
I have tried with max-height. I have tried to position the table absolutely and give both the top and bottom coordinates. I have tried to manually edit the height in Firebug to see if it was a problem with CSS specificity. I have tried to set the height on the tbody too. Fact is, the table always stays exactly the same height as its content, regardless of my efforts.
Of course I could fake a table with a div structure, but it actually is a table, and I fear using divs I may run into an issue where some columns may not be properly aligned.
How am I supposed to give a table a height?
NOTE this answer is now incorrect. I may get back to it at a later time.
As others have pointed out, you can't set the height of a table unless you set its display to block, but then you get a scrolling header. So what you're looking for is to set the height and display:block on the tbody alone:
<table style="border: 1px solid red">
<thead>
<tr>
<td>Header stays put, no scrolling</td>
</tr>
</thead>
<tbody style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
<tr>
<td>cell 1/1</td>
<td>cell 1/2</td>
</tr>
<tr>
<td>cell 2/1</td>
<td>cell 2/2</td>
</tr>
<tr>
<td>cell 3/1</td>
<td>cell 3/2</td>
</tr>
</tbody>
</table>
Here's the fiddle.
Set display: block; for the table
Set position: sticky; top: 0; for the header row
<table style="display: block; height: 100px; overflow: auto;">
<thead>
<tr>
<td style="position: sticky; top: 0;">Header stays put</td>
<td style="position: sticky; top: 0;">Layout aligned</td>
</tr>
</thead>
<tbody>
<tr>
<td>foo1</td>
<td>Header stays put</td>
</tr>
<tr>
<td>foo2</td>
<td>Header stays put</td>
</tr>
</tbody>
</table>
https://jsfiddle.net/0zxk18fp/
Tested on Chrome, Firefox, Safari, Edge
Add display:block; to the table's css. (in other words.. tell the table to act like a block element rather than a table.)
fiddle here
You can do this by using the following css.
.scroll-thead{
width: 100%;
display: inline-table;
}
.scroll-tbody-y
{
display: block;
overflow-y: scroll;
}
.table-body{
height: /*fix height here*/;
}
Following is the HTML.
<table>
<thead class="scroll-thead">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody class="scroll-tbody-y table-body">
<tr>
<td>Blah</td>
<td>Blah</td>
</tr>
</tbody>
</table>
JSFiddle
I had a coworker ask how to do this today, and this is what I came up with. I don't love it but it is a way to do it without js and have headers respected. The main drawback however is you lose some semantics due to not having a true table header anymore.
Basically I wrap a table within a table, and use a div as the scroll container by giving it a max-height. Since I wrap the table in a parent table "colspanning" the fake header rows it appears as if the table respects them, but in reality the child table just has the same number of rows.
One small issue due to the scroll bar taking up space the child table column widths wont match up exactly.
Live Demo
Markup
<table class="table-container">
<tbody>
<tr>
<td>header col 1</td>
<td>header col 2</td>
</tr>
<tr>
<td colspan="2">
<div class="scroll-container">
<table>
<tr>
<td>entry1</td>
<td>entry1</td>
</tr>
........ all your entries
</table>
</div>
</td>
</tr>
</tbody>
</table>
CSS
.table-container {
border:1px solid #ccc;
border-radius: 3px;
width:50%;
}
.table-container table {
width: 100%;
}
.scroll-container{
max-height: 150px;
overflow-y: scroll;
}
Seems very similar to this question. From there it seems that this should do the trick:
table {
display: block; /* important */
height: 600px;
overflow-y: scroll;
}
A simple workaround that is available in most of the cases it to wrap the table in a div and then give a max-height to that div:
.scrollable-wrapper {
max-height: 400px;
overflow: auto;
}
/* Add also the following code if sticky header is wanted */
.scrollable-wrapper table thead th {
background: #afa;
position: sticky;
top: 0;
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4);
}
<div class="scrollable-wrapper">
<table>
<thead>
<tr>
<th>Id</th>
<th>Text</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
Codepen: https://codepen.io/Conejoo/pen/NWpjmYw
In Tables, For minimum table cells height or rows height use css height: in place of min-height:
AND
For Limiting max-height of all cells or rows in table with Javascript:
This script is good for horizontal overflow tables.
This script increase the table width 300px each time (maximum 4000px) until rows shrinks to max-height(160px) , and you can also edit numbers as your need.
var i = 0, row, table = document.getElementsByTagName('table')[0], j = table.offsetWidth;
while (row = table.rows[i++]) {
while (row.offsetHeight > 160 && j < 4000) {
j += 300;
table.style.width = j + 'px';
}
}
Source: HTML Table Solution Max Height Limit For Rows Or Cells By Increasing Table Width, Javascript
Use divs with max height and min height around the content that needs to scroll.
<tr>
<td>
<div>content</div>
</td>
</tr>
td div{
max-height:20px;
}
https://jsfiddle.net/ethanabrace/4w0ksczr/
Just try this.
<div style="max-height: 400px; overflow: scroll">
<!--This is your table-->
<table style="border: 1px solid red">
<thead>
<tr>
<td>Header stays put, no scrolling</td>
</tr>
</thead>
<tbody style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
<tr>
<td>cell 1/1</td>
<td>cell 1/2</td>
</tr>
<tr>
<td>cell 2/1</td>
<td>cell 2/2</td>
</tr>
<tr>
<td>cell 3/1</td>
<td>cell 3/2</td>
</tr>
</tbody>
</table>
</div>
<table style="border: 1px solid red">
<thead>
<tr>
<td>Header stays put, no scrolling</td>
</tr>
</thead>
<tbody id="tbodyMain" style="display: block; border: 1px solid green; height: 30px; overflow-y: scroll">
<tr>
<td>cell 1/1</td>
<td>cell 1/2</td>
</tr>
<tr>
<td>cell 2/1</td>
<td>cell 2/2</td>
</tr>
<tr>
<td>cell 3/1</td>
<td>cell 3/2</td>
</tr>
</tbody>
</table>
Javascript Section
<script>
$(document).ready(function(){
var maxHeight = Math.max.apply(null, $("body").map(function () { return $(this).height(); }).get());
// alert(maxHeight);
var borderheight =3 ;
// Added some pixed into maxheight
// If you set border then need to add this "borderheight" to maxheight varialbe
$("#tbodyMain").css("min-height", parseInt(maxHeight + borderheight) + "px");
});
</script>
please, refer How to set maximum possible height to your Table Body Fiddle Here
I have a HTML table consisting of 3 columns. It has a fixed width of 600px.
<table>
<tr>
<td>Name</td>
<td>Qty</td>
<td>Actions</td>
</tr>
</table>
I want the Qty and Actions columns to be as small as possible (keeping the content to one line) and the Name column to take up the rest of the available space. The size of the Qty and Actions column change depending on content/font size so fixed widths will not work in this case.
Is there a way of doing this in HTML/CSS? Or is this something I need to break out the Javascript for?
You can apply width="99%" on that column. For example:
<table>
<tr>
<td width="99%">Name</td>
<td>Qty</td>
<td>Actions</td>
</tr>
</table>
you can use max-width:99%; on the first column and give fixed sizes on the other columns (I used pixels sized columns).
<table style="width: 100%;">
<tr>
<td style="max-width: 99%">
Will max
</td>
<td style='width:110px;'>
fixed size here
</td>
</tr>
</table>
For every column you want to be the minimum width: (1) set the CSS width to zero and (2) use white-space: nowrap to prevent the text from wrapping onto multiple lines.
table {
width: 100%;
}
:where(th, td):not(.max) {
width: 0;
white-space: nowrap;
}
/* For demo purposes */
table, th, td {
border: 1px solid gray;
}
<table>
<tr>
<th class="max">Name</th>
<th>Qty</th>
<th>Actions</th>
</tr>
<tr>
<td class="max">Victoria Adelaide Mary Louisa</td>
<td>233,546,443</td>
<td>Abort Retry Fail</td>
</tr>
</table>