I tried to create a table in AngularJS with sticky header and footer. I've managed to do that; here's a Plunker demo and code:
<body ng-controller="MainCtrl as ctrl">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
Column1
</th>
<th>
Column2
</th>
<th>
Column3
</th>
<th>
Column4
</th>
<th>
Column5
</th>
</tr>
</thead>
<tbody>
<tr class="info" ng-repeat="item in items">
<td>
{{item.name}}
</td>
<td>
{{item.type}}
</td>
<td>
{{item.value}}
</td>
<td>
{{item.code}}
</td>
<td>
{{item.id}}
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>
Column1
</th>
<th>
Column2
</th>
<th>
Column3
</th>
<th>
Column4
</th>
<th>
Column5
</th>
</tr>
</tfoot>
</table>
</body>
But the only problems are:
The column width isn't dynamic, as you can see, in the first row the data overflows into the 2nd column.
The columns are misaligned.
Any idea how to fix this?
The criteria for success of this question are:
Pure CSS.
Dynamically sized columns.
Sticky header and footer that size with the columns.
What you want is impossible.
The reason why the cells are almost right is because the table is semi-there, but there are actually multiple tables in the document. By overriding the <table> elements display type to flex, you've rendered the page in several different groups. The <thead> and <tfoot> are their own table, and their <tbody> is its own table. They do not size to one another, rather to other table cells in their own group.
Other CSS guides about this topic require a fixed width. http://joshondesign.com/2015/05/23/csstable
After playing around with it (specifically, trying to move the thead and tfoot to fixed positions), I've decided that any attempt to give specific rules to the header/footer breaks the table layout and will cause the sizing to work differently, which is why fixed width is required on the cells. Even in the examples, they are broken in this way, but the fixed width nullifies the problem.
Your absolute easiest fix is to fix the widths and give them overflow-x properties.
The alternative is to use JavaScript. With JS, all bets are off, and you can do anything you imagine. Specifically, you could use JS to autosize cells. I remember having success with a jQuery plugin that accomplished that.
https://www.datatables.net/
Otherwise, no. I cannot find any example online that does what you need it to do. Any attempts to get this specific layout working is a hack and you're better off making a no-JS version with overflow-x cells and fixed widths, and a JS-enabled version that autosizes cells.
As you already know from the other answers, you should remove white-space: nowrap;, but there's also something you can do about the scrollbar:
table thead, table tfoot {
width: calc(100% - 17px);
}
Updated Plunker
this looks perfect on my PC because the Windows scrollbars are 17px broad. If you want to be safe and check the scrollbar width, use this:
window.onload = function() {
var tr = document.getElementById("__tbody").children[0];
var scrWidth = window.innerWidth - tr.clientWidth - 3;
var width = "calc(100% - " + scrWidth + "px)";
document.getElementById("__thead").style.width = width;
document.getElementById("__tfoot").style.width = width;
}
This calculates how broad the scrollbars are and then adjusts thead and tfoot. Of course then you have to set the ids <thead id="__thead">, <tbody id="__tbody"> and <tfoot id="__tfoot">.
In order to return the table back to its normal, dynamically-resizing self, there are a few steps to follow. Each step mentioned will give freedom back to its respective table elements, making their lives much simpler.
First, remove all instances of flex. You want the table to act like a table, right? Next, let your thead, tr, and tfoot be themselves as well. Why make them display as a table? Lastly, your tbody is being set to display as a block. This, in a sense, segregates it from its other table friends, namely thead and tfoot. This creates a lonely situation for everyone involved.
Your final code will look like this:
table {
table-layout: auto;
max-height: 300px;
}
table thead, table tfoot,
table tbody tr {
table-layout: fixed;
}
tbody td,
thead th,
tfoot td{
border-right: 1px solid transparent;
vertical-align: middle;
white-space: nowrap;
}
table thead {
width: 100%;
}
table tfoot {
width: 100%;
}
table tbody {
overflow-y: auto;
}
table tbody tr {
width: 100%;
}
This will allow your table cells to be themselves--dynamically resizing as they see fit.
Remove
white-space: nowrap;
and add
word-wrap: break-word;
tfoot td{
border-right: 1px solid transparent;
vertical-align: middle;
word-wrap: break-word;
}
1st answer: add the below css to td element
td{
white-space: normal;
word-wrap: break-word;
}
2nd answer: you need to create seperate table for header and footer and assign 20 % width to each td and th. It should work.
Answer of first question:
td {
text-overflow: ellipsis !important;
overflow: hidden !important;
}
text-overflow: ellipsis is very useful because the user can copy the whole value.
Answer of second question:
Have a look at the answer of this question: Table scroll with HTML and CSS
It seems you need either javascript or inner table solution.
UPDATED for second answer:
Use following styles on your table and tbody (working on Chrome):
table {
overflow-y: visible !important;
}
tbody {
overflow-y: overlay !important;
}
Plunker Demo
Your misalignment is coming because of followings
overflowing text
width of scrollbar in tbody
solution:
give overflow-x:auto to 'td' and and some max-width/width
make your last th as much extra bigger then others as your scroll-bar width is.
for better look to scrollbars put custom css for scroll-bar
Add following css to your page and enjoy plunkerLink
th,td {
width: 20%!important;
overflow-x: auto;
padding: 10px;
}
th:last-of-type {
width: calc(20% + 6px)!important;
}
::-webkit-scrollbar {
width: 3px!important;
height: 6px!important;
}
::-webkit-scrollbar-button {
width: 0;
height: 0;
}
::-webkit-scrollbar-thumb {
border: 2px solid #ccc;
background: #ccc;
border-radius: 8px;
}
::-webkit-scrollbar-track-piece {
width: 3px!important;
border: 1px solid #fff;
}
Use bootstrap classes for the purpose of styling. Your custom styling(style.css) is creating the problem. Also, the <table> tag provides dynamic width of columns by default. An excerpt from How to create a dynamic width column in Twitter Bootstrap answer:
<table class="table">
<tr><th>Id</th> <th>Name</th> <th>Email address</th></tr>
<tr><td>100001</td> <td>Joe</td> <td>MamiePVillalobos#teleworm.us</td></tr>
<tr><td>100</td> <td>Christine</td> <td>ChristineJWilliams#dayrep.com</td></tr>
<tr><td>1001</td> <td>John</td> <td>JohnLMiley#dayrep.com</td></tr>
This will give you the desired output
Here is your answer:
https://plnkr.co/edit/cyN0qDuxIs8LjkxIhur5?p=preview
tbody td,
thead th,
tfoot td{
word-wrap:break-word;
table-layout:fixed;
white-space:normal;
}
https://plnkr.co/edit/3hYms9hRqzF2DV9yTBCG?p=preview
Added this in your css:
tr.info td {word-wrap: break-word; white-space: normal;}
I have simply altered your style.css in Plunker demo as follows
/* Put your css in here */
table {
table-layout: auto;
display: flex;
flex-flow: column;
max-height: 300px;
}
table thead, table tfoot,
table tbody tr {
display: table;
table-layout: fixed;
}
tbody td,
thead th,
tfoot td{
border-right: 1px solid transparent;
vertical-align: middle;
text-align: center;
white-space: normal;
word-wrap: break-word;
text-wrap: normal;
}
table thead {
/*flex: 0 0 auto;*/
width: 100%;
}
table tfoot {
/*flex: 0 0 auto;*/
width: 100%;
}
table tbody {
flex: 1 1 auto;
display: block;
overflow-y: auto;
}
table tbody tr {
width: 100%;
}
thead { display: table-header-group }
tfoot { display: table-row-group }
tr { page-break-inside: avoid }
this is working fine.. pls try
Related
I'm working on a react js project again after awhile. I need to show a table that won't exceed the viewport when the content has a very long string.
I tried the solution in this answer successfully on jsfiddle like in this code:
<div className="simple-table">
<Table striped bordered hover>
<thead>
<tr>
<th>Nama Barang</th>
<th>Jumlah</th>
<th>Harga</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lolipop Strawberry</td>
<td>20</td>
<td>Rp 5.000</td>
<td>Rp 100.000</td>
</tr>
</tbody>
</Table>
</div>
.simple-table {
width: 100%;
display: flex;
flex-direction: column;
}
.simple-table table {
width: 100%;
table-layout: fixed; /* add table layout fixed */
overflow: hidden; /* add overflow hidden */
border-collapse: collapse;
}
.simple-table > table td,
.simple-table > table th {
word-wrap: break-word !important;
}
the result on jsfiddle:
but when I try to apply the same code on my react js project, the result is like this:
what am I doing wrong? any help is appreciated.
On jsfiddle word-wrap: break-word is applied, in your project - for some reason - not. You have to check why. Try to debug the application and look if the css rule is applied or not.
it turns out I just needed to add a white-space:normal rule
.simple-table > Table th,
.simple-table > Table td {
white-space:normal !important; /* added this */
word-wrap: break-word !important;
}
I upload data in table using ajax. so when I received response - data will be filled to table and it will be visible on the screen. when data contain some small text example it looks ok. but if I upload file with 40 records which contains full text then width of screen increases in few times, scroll-x is going visible but it looks like table and huge empty space on screen.
I've checked all text and data in table. everything is inside table. someone know what can be the reason of problem?
I can fix this if add property overflow-x: hidden; on my div that wrap table. but this solution really bad)
It works the same on Chrome and Mozila
<div id="trainData" style="display: none" class="my-table">
<table class="table table-striped" id="trainTable">
<thead class="thead-inverse-blue">
<th class="inputText" >Input</th>
<th data-field="comment" >Comment</th>
</thead>
</table>
</div>
.table{
margin-top: 10px;
table-layout: fixed;
width: 100%;
margin-bottom: 0 !important;
border-bottom: 1px solid #dddddd;
border-collapse: collapse !important;
border-radius: 1px;
}
.table > tbody > tr > td {
width: 1px;
white-space: pre-wrap;
word-wrap: break-word;
}
.fresh-table .table > tbody > tr > td >content{
text-overflow:ellipsis;
overflow:hidden;
}
The problem was in decision to add white-space: pre-wrap; property. It occur scrolling and huge width. Changed to white-space: pre-line; and problem missed :)
I am using Google Chrome to render this HTML page:
<html>
<style>
table {
width: 100%;
}
table, td, th {
border: 1px solid black;
text-align: left;
}
td {
vertical-align: top;
}
</style>
<body>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Bobby</td>
<td>100</td>
</tr>
</table>
</body>
</html>
Above code works fine. Problem is, I want the first column to not resize its width past the width of the longest content width in any row hosted in that column. For example, when I resize the window, I get this:
*---------------------------*---------------------------*
|Name |Value |
*---------------------------*---------------------------*
|Bobby |100 |
*---------------------------*---------------------------*
But I want it to be like this:
*-----*-------------------------------------------------*
|Name |Value |
*-----*-------------------------------------------------*
|Bobby|100 |
*-----*-------------------------------------------------*
How can this be done?
PS: I still want to preserve the way the entire table takes up 100% width of the window.
Just set the width of the :first-child to 1px and it should update the width according to the content.
table th:first-child,
table td:first-child {
width: 1px;
}
http://jsfiddle.net/sbeliv01/ehpvrzk0/
Could try tinkering with percentage based widths to adhere to the table's width
tr th,
tr td {
width: 90%;
/* adjust this if the "label" column needs to be longer */
}
tr th:first-child,
tr td:first-child {
width: auto;
}
http://jsfiddle.net/25pjqva4/
Just add to your first-child column width:auto property.
table tr td:first-child {
width:auto;
}
Hello all I'm just trying to have my border around my table cell right around the text...not stretched the length of the entire table. Its the section with the border around it
CSS:
table.content_table {
width: 100%;
margin: 0px;
border-collapse: collapse;
}
table.content_table > tbody > tr > td.results {
border: 2px solid;
background-color: #eeeecc;
font-size: 8pt;
font-weight: bold;
PADDING: 0px;
}
HTML:
<table class="content_table">
<br/><br/>
<h1>Planned Vs Actual Productions Drilldown</h1>
<tr>
<td class="results">
Number of results returned: ${fn:length(beans)}
</td>
</tr>
give the text a simple span or any other block element like div p ... span with inline-block is also a block element which can have a border.
table.content_table {
width: 100%;
margin: 0px;
border-collapse: collapse;
}
.border {
border: 2px solid;
background-color: #eeeecc;
font-size: 8pt;
font-weight: bold;
PADDING: 0px;
display: inline-block;
}
Any Element inside a table needs to be in TD so that is is valid html... put another tr > td into your table like this
<table class="content_table">
<tr>
<td>
<h1>Planned Vs Actual Productions Drilldown</h1>
</td>
</tr>
<tr>
<td class="results">
<span class="border">Number of results returned: ${fn:length(beans)}</span>
</td>
</tr>
</table>
The answer lies in the fact that you have table width as 100%. Without any of styling at the TD level, the TD is automatically going to take the most width it can.
The bigger question though, is why you are using a table at all. This is a single column of data, no need for a table here, just use div's.
I had a similar problem with a WordPress theme. The "collapse" wasn't entirely working on the first column, because my theme's style.css "reset" had set the table width to 100%. At least for me, the "auto" width solved the problem.
<style>
table#donations { border-collapse: collapse; width:auto; }
</style>
<table id="donations">
<tr><td>Bitcoin BTC</td><td>1Prh5VnUJRQV3sARhEfQAMKv9UzGqgAMXg</td></tr>
</table>
So I am styling a table, and I'd like to make quite a fancy underline for the table headings.
I've though hard and had a look on the internet but couldn't find anything.
This is the table structure:
<table>
<thead>
<tr>
<td>Number</td>
<td>Name</td>
<td>Address</td>
</tr>
</thead>
<tbody></tbody>
</table>
And my current styling:
table {
width: 100%;
}
table thead {
font-weight: bold;
}
table thead td {
margin-right: 5px;
border-collapse: separate;
border-spacing: 10px 5px;
border-bottom: 2px solid #427AA8;
}
table tbody {
font-size: 90%;
}
table tbody tr {
line-height: 2em;
border-bottom: 1px solid #CCC;
}
table tbody td {
padding: 0 5px;
}
Here is a jsfiddle of the code: http://jsfiddle.net/tYA4e/1/
What I am looking for is a break in the border between the columns, but only in the thead.
And an example of what I am trying to achieve: http://i.imgur.com/OHrhJ.jpg
Is there a way to achieve this with some simple CSS?
A border will, necessarily, extend the full width of its element; therefore to extend a border only partially across the width of an element that border must be applied to a child element, sized accordingly.
That said, the only way this is achievable would seem to be with nesting an element within the td (in this case a span), and using the following CSS:
table thead td span {
display: inline-block;
width: 80%;
border-bottom: 2px solid #427AA8;
}
JS Fiddle demo.
As an aside, though, it's worth noting that, for table-headings, the th (table-heading) element might be more appropriate for your use in this case.
On further thought it is, of course, also possible to use styled hr elements, which allows you to give pixel-level control over the hr's width in that it can extend up to, in this example, 10px from the right edge of the parent td):
table thead td hr {
width: 80%;
margin: 0 10px 0 0;
border-bottom: 2px solid #427AA8;
}
JS Fiddle demo.
You could also use th for heading cells -> no more need for seperating the rows into groups with thead and tbody - less markup and less css.
<table>
<tr>
<th>headlinecell</th>
</tr>
<tr>
<td>contentcell</td>
</tr>
</table>
now just style the th and td.