I am attempting to control the height of a table body so that a scrollbar appears when more data than fits in a view is displayed, thead must stay visible. At the same time I'm trying to control the width of the table columns.
The table height can be controlled by setting 'display: block' in the table body css. The table body will now be limited by the container height or any height the table body is set to. This messes up the column widths though.
The column widths can be assured by setting as desired. As long as the tbody isn't set to 'display: block' the columns display properly but the tbody is out of control and ignores any height you may have set.
I'm trying to do this to make it possible for the result to be easily chapter 508 compliant for screen reader technology for those with disabilities. AT this point, I'm planning to convert to jquery.dataTables which puts a view port over top of a table so I can keep the 508 compliance and get the functionality I need. This seems way over the top for what I'm wanting to accomplish but I can't find a simple way to do it with a native table and basic css.
Test code is as follows:
<div id="div1">
<table>
<colgroup>
<col id='col-1'>
<col id='col-2'>
</colgroup>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February is a long month that seems like it could go on forever!</td>
<td>$80</td>
</tr>
<tr>
<td>March</td>
<td>$180</td>
</tr>
<tr>
<td>April</td>
<td>$86</td>
</tr>
<tr>
<td>May</td>
<td>$98</td>
</tr>
<tr>
<td>June</td>
<td>$29</td>
</tr>
<tr>
<td>July</td>
<td>$44</td>
</tr>
<tr>
<td>August</td>
<td>$244</td>
</tr>
</tbody>
</table>
#div1 {
height: 100px;
width: 400px;
padding: .5px;
border: 1px solid red;
}
colgroup {
width: 100%;
}
#col-1 {
width:70%;
}
#col-2 {
width:30%;
}
table {
width: 100%;
table-layout: auto;
}
thead {
background-color: #B2DFFF;
}
tbody {
height: 72px;
overflow-y: scroll;
background-color: #F0F0F0;
/* display:block; This will set column width correctly but it messes up tbody height */
display:block; /* This will allow height to be set but it messes up columns width */
}
Does anyone have any ideas?
Add overflow: auto to your container div's css.
Link to JSFiddle: http://jsfiddle.net/bmarple/NK378/10/
It is possible, just have some considerations:
thead {display: table; width: 100%;}
tbody {display: block; overflow: auto;}
tbody tr {display: table; width: 100%;}
td, th {/* should set a width for each td, th*/}
This is the example: http://jsfiddle.net/NK378/14/
Add overflow:scroll; to #div1 to add scroll beyond a height of 100px.
http://jsfiddle.net/NK378/13/
EDIT:
I could not see from your question that you wanted the header in view at all times. To do this, aply the style to the tbody so it doesn't apply to the header.. So the tbody tag has an id of "scroll", and the css for #scroll is:
#scroll {
display:block;
overflow-y: scroll;
display: block;
height: 20px;
width:400px;
}
http://jsfiddle.net/NK378/17/
Try to change the "display" property to "inline-block" and "max-width", "min-width", "overflow-x", "white-space" like that:
CSS
tbody td {
display: inline-block;
max-width: 100px;
min-width: 100px;
overflow-x: scroll;
white-space: nowrap;
}
JSFIDDLE
Watch the second line in the table.
In the case you want to limit the height of your td:
CSS
tbody td {
display: inline-block;
max-width: 100px;
min-width: 100px;
overflow-y: scroll;
max-height: 30px;
min-height: 30px;
overflow-x: hidden;
}
JSFIDDLE
You shouldn't use display: block on tables. They need their default display: table in order to function correctly.
You can just set the containing div to scroll when it overflows:
#div1 {
height: 100px;
width: 400px;
padding: .5px;
border: 1px solid red;
overflow-y: scroll; /* Added */
}
Demo
UPDATE
I completely missed the requirement for the thead to not scroll. One way to achieve this is to nest another table inside the first to separate it from the thead. You are allowed to place a <div> inside a <td> so that's how you create the scroll.
<div id="div1">
<table>
<thead>
<tr>
<th>Month</th>
<th class="savings">Savings</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2">
<div class="table-body">
<table>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February is a long month that seems like it could go on forever!</td>
<td>$80</td>
</tr>
<tr>
<td>March</td>
<td>$180</td>
</tr>
<tr>
<td>April</td>
<td>$86</td>
</tr>
<tr>
<td>May</td>
<td>$98</td>
</tr>
<tr>
<td>June</td>
<td>$29</td>
</tr>
<tr>
<td>July</td>
<td>$44</td>
</tr>
<tr>
<td>August</td>
<td>$244</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
Some additional styles
th:first-child, td:first-child {
width: 80%;
}
table table td {
padding: 4px 5px;
}
.table-body {
height: 100px;
overflow: auto;
}
UPDATED DEMO
Related
The title is not clear, I know. Let me explain what I mean:
First column has td elements which have varying rowspans. What I want is to keep the td text in first column 'fixed' at the top while scrolling down.
But only as long as the rest of the td elements in the remaining columns are in scope.
Once all the rows (which the first column cell is spanning) is out of table view, the td element should scroll out of the view and the next td should now start fixing.
After Scrolling a bit:
And after All the animal rows are scrolled out, the fixed 'Animal' td would also go up and then 'Cars' would be fixed and then Hats would be fixed like this:
I got it working by setting
vertical-align: top; for the element
and created a div under the td element which contains the actual value for the cell
then applied position: sticky; top:0; z-index: 1; to the div.
Working fiddle: https://jsfiddle.net/ankitkraken/yw0jhzpu/1/
HTML:
<td class="td-class-name" rowspan="3">
<div class="level-1">
"Cars"
</div>
</td>
CSS:
.td-class-names{
vertical-align: top;
}
.level-1{
position: sticky ;
top: 80px;
z-index: -1;
}
I had to use top: 80px;, top:0; was putting the td contents BEHIND the sticky table header.
You can acheive this result with the sticky positioning:
thead tr:first-of-type {
position: sticky;
top: 0px;
z-index: 10;
}
thead tr:first-of-type th {
background: yellow;
}
th {
border: 1px solid;
padding: 6px;
}
td {
border: 1px solid;
padding: 6px;
}
th[rowspan]>.box {
vertical-align: top;
position: sticky;
top: 34px;
}
th[rowspan][data-order='first'] {
background: orange;
}
th[rowspan][data-order='second'] {
background: green;
}
th[rowspan][data-order='third'] {
background: indianred;
}
th[rowspan][data-order='fourth'] {
background: lightblue;
}
.main-container {
position: relative;
}
.table-container {
position: static;
max-height: 180px;
max-width: 350px;
;
overflow-y: scroll;
}
.fake {
width: 100%;
height: 100px;
}
<div class="main-container">
<div class='table-container'>
<table>
<thead>
<tr>
<th>CATEGORY</th>
<th>TYPE</th>
<th>NAME</th>
</tr>
</thead>
<tbody>
<tr>
<th data-order='first' rowspan='5'>
<div class='box'>Animals</div>
</th>
<td>Dog</td>
<td>Bob</td>
</tr>
<tr>
<td>Dog</td>
<td>Flash</td>
</tr>
<tr>
<td>Cat</td>
<td>Mimi</td>
</tr>
<tr>
<td>Dog</td>
<td>Casper</td>
</tr>
<tr>
<td>Horse</td>
<td>Wind Lady</td>
</tr>
<tr>
<th data-order='second' rowspan='5'>
<div class='box'>Cars</div>
</th>
<td>Chrysler</td>
<td>Ann</td>
</tr>
<tr>
<td>Dodge</td>
<td>Christine</td>
</tr>
<tr>
<td>Ford</td>
<td>Foo</td>
</tr>
<tr>
<td>Ferrari</td>
<td>Dandy</td>
</tr>
<tr>
<td>Mercedes</td>
<td>A200</td>
</tr>
<tr>
<th data-order='third' rowspan='5'>
<div class='box'>Food</div>
</th>
<td>Apple</td>
<td>George</td>
</tr>
<tr>
<td>Banana</td>
<td>Rocco</td>
</tr>
<tr>
<td>Strawberry</td>
<td>Liza</td>
</tr>
<tr>
<td>Ananas</td>
<td>Ted</td>
</tr>
<tr>
<td>Avocado</td>
<td>Gary</td>
</tr>
<tr>
<th data-order='fourth' rowspan='5'>
<div class='box'>Phones</div>
</th>
<td>Iphone XXI</td>
<td>ObiWan</td>
</tr>
<tr>
<td>Nokia 8110</td>
<td>Neo</td>
</tr>
<tr>
<td>Ericsson</td>
<td>Dr. Who</td>
</tr>
<tr>
<td>Huawei Mate 40</td>
<td>Dead or Alive</td>
</tr>
<tr>
<td>Xiaomi</td>
<td>Ping</td>
</tr>
</tbody>
</table>
<div class='fake'>
</div>
</div>
</div>
Sticky positioning is not always straightforward, expecially when dealing with overflow properties and display: table. Here are some useful resources about these topics:
Position: stuck; — and a way to fix it
CSS Position Sticky - How It Really Works!
Creating sliding effects using sticky positioning
Position Sticky on <td> with colspan?
I am having trouble with replicating this.
Im trying to make a table that changes based on the window size. When the window is large I want the table to look like the "large screen" graphic, and when the window is small I want the table to look like the "small screen" graphic.
[![enter image description here][1]][1]
What I have right now is this. When the window is large I have the desired layout.
[![enter image description here][2]][2]
When I make the preview window smaller, my table collapses into one column instead of looking like how I want it to look like. IT should loook like the "small screen" graphic on the screenshot above.
[![enter image description here][3]][3]
Make use of display: block for you media query display.
The default display value of table will be display: table; thead will be display: table-header-group;, tbody will be display: table-row-group;, tr will be display: table-row;, th and td will be display: table-cell;.
For the table header and body contents to fold in multiple lines, you have to make use of display: block, float: left, box-sizing: border-box;
To update the content of the header, you should do a tweek. Move the label COMPARISON to as span. On the smaller resolution, make the sapn hidden and add the content to after pseudo element.
.table-container {
display: block;
margin: 1em auto;
width: 100%;
max-width: 600px;
border-collapse: collapse;
}
.flag-icon {
margin-right: 0.1em;
}
.flex-row {
width: 20%;
border: 1px solid palevioletred;
}
.flex-row,
.flex-cell {
text-align: center;
}
#media only screen and (max-width: 600px) {
.table-container {
display: block;
}
th,
td {
width: auto;
display: block;
}
.flex-row {
width: 25%;
float: left;
box-sizing: border-box;
}
.flex-row.first {
width: 100%;
text-align: left;
}
thead,
thead tr,
tbody,
tbody tr {
display: block;
}
.header .flex-row.first span {
display: none;
}
.header .flex-row.first:after {
content: 'HOW THE PLAYERS COMPARE';
}
}
<table class="table-container" width="100%" role="table" aria-label="Destinations">
<thead>
<tr class="flex-table header" role="rowgroup">
<th class="flex-row first" role="columnheader">
<span>COMPARISON</span>
</th>
<th class="flex-row" role="columnheader">player 1</th>
<th class="flex-row" role="columnheader">player 2</th>
<th class="flex-row" role="columnheader">player 3</th>
<th class="flex-row" role="columnheader">player 4</th>
</tr>
</thead>
<tbody>
<tr class="flex-table row" role="rowgroup">
<td class="flex-row first" role="cell"><span class="flag-icon flag-icon-gb"></span>Speed</td>
<td class="flex-row" role="cell">11Sp </td>
<td class="flex-row" role="cell">22Sp</td>
<td class="flex-row" role="cell">33Sp</td>
<td class="flex-row" role="cell">44Sp</td>
</tr>
<tr class="flex-table row" role="rowgroup">
<td class="flex-row first" role="cell"><span class="flag-icon flag-icon-gb"></span>Endurance</td>
<td class="flex-row" role="cell">11E </td>
<td class="flex-row" role="cell">22E</td>
<td class="flex-row" role="cell">33E</td>
<td class="flex-row" role="cell">44E</td>
</tr>
<tr class="flex-table row" role="rowgroup">
<td class="flex-row first" role="cell"><span class="flag-icon flag-icon-gb"></span>Strength</td>
<td class="flex-row" role="cell">11St </td>
<td class="flex-row" role="cell">22S</td>
<td class="flex-row" role="cell">33S</td>
<td class="flex-row" role="cell">44S</td>
</tr>
</tbody>
</table>
There is a table without any settings for <thead> and <tbody>. And it looks like this:
I had to make the table scrollable, so in this case I added to <tbody> this styling:
display: block;
height: 475px;
overflow: scroll;
Now, <tbody> has a height of 475px and it's scrollable. This problem was solved!
But now <thead> doesn't look right:
To solve this problem, I added to <thead>:
display: table;
Now it looks better:
But still, the column headers are not aligned to the columns.
How can be this solved and make the table looks like it was looking before adding the scrolling part?
You can make this basically by setting thead and tbody display as block, and setting a fixed width to both th and td tags.
table {
background: steelblue
}
thead, tbody {
display: block;
}
tbody {
overflow-y: scroll;
height: 100px;
}
thead th:nth-child(1), tbody td:nth-child(1) {
background: pink;
width: 90px;
word-break: break-all;
}
thead th:nth-child(2), tbody td:nth-child(2) {
background: olive;
width: 140px;
word-break: break-all;
}
thead th:nth-child(3), tbody td:nth-child(3) {
background: tomato;
width: 80px;
word-break: break-all;
}
<table>
<thead>
<tr>
<th>Make Payment</th>
<th>Order Number</th>
<th>Order Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>Inserting a long text here just to show it breaks</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
<tr>
<td>V</td>
<td>9598959</td>
<td>2020-05-12</td>
</tr>
</tbody>
</table
as per my project need I made first three columns content and headings of a table be static by using position and left css properties and made remaining columns be scrollable horizontally like below
But when having more content in non static columns then that non static column content is displaying over static column content like below
and notice one more thing if any non static column having more content then other non static columns content moving down(may be because of first three columns be having position:absolute but not sure) from starting point like below but they should be aligned from top only as per my need
source code:
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
width:900px;
}
/*This sets alternating colours on each odd numbered column:*/
table tr:nth-child(odd) td
{
background-color: #fff;
}
/*This sets alternating colours on each even numbered column:*/
table tr:nth-child(even) td
{
background-color: #eee;
}
/* tr:nth-child(add) {
background-color: #eee;
} */
tr th,
td {
padding: 5px;
width:100pt;
height: auto;
}
tr th{
text-align: left;
background-color: black;
color: white;
}
div{
width:700px;
overflow-x: scroll;
}
</style>
</head>
<body>
<div>
<table>
<tr>
<th style="position:absolute;left:0pt;">Heading1</th>
<th style="position:absolute;left:80pt;">Heading2</th>
<th style="position:absolute;left:140pt;">Heading3</th>
<th>Heading4</th>
<th>Heading5</th>
<th>Heading6</th>
<th>Heading7</th>
<tr>
<tr>
<td style="position:absolute;left:0pt;">Content1 Content1 Content1 Content1</td>
<td style="position:absolute;left:80pt;">Content2</td>
<td style="position:absolute;left:140pt;">Content3</td>
<td>Content4</td>
<td>Content5 Content5 Content5 Content5 Content5</td>
<td>Content6</td>
<td>Content7</td>
</tr>
<tr>
<td style="position:absolute;left:0pt;">Content1</td>
<td style="position:absolute;left:80pt;">Content2</td>
<td style="position:absolute;left:140pt;">Content3</td>
<td>Content4</td>
<td>Content5</td>
<td>Content6</td>
<td>Content7</td>
</tr>
<tr>
<td style="position:absolute;left:0pt;">Content1</td>
<td style="position:absolute;left:80pt;">Content2</td>
<td style="position:absolute;left:140pt;">Content3</td>
<td>Content4</td>
<td>Content5</td>
<td>Content6</td>
<td>Content7</td>
</tr>
<tr>
<td style="position:absolute;left:0pt;">Content1</td>
<td style="position:absolute;left:80pt;">Content2</td>
<td style="position:absolute;left:140pt;">Content3</td>
<td>Content4</td>
<td>Content5</td>
<td>Content6</td>
<td>Content7</td>
</tr>
</table>
</div>
</body>
</html>
What things can I try? thank you in advance.
About vertical position, this is the solution :
td {vertical-align:top;}
Is it possible to force the height of the cells ?
If so, height:50px solves the first problem.
So i've been trying to use table-layout fixed so that the content get's it's width by the largest one but i don't want that to happen to all of the data's. Some of them need to have a width by the content itself not by a sibling they have in the same row. Here's the code
<table>
<tbody>
<tr>
<td> </td>
<td> </td>
<th>2012</th>
<th>2011</th>
<th>Var</th>
</tr>
<tr>
<td class="day">M</td>
<td class="date">3</td>
<td>300,500</td>
<td>300,500</td>
<td>0%</td>
</tr>
<tr>
<td class="day">T</td>
<td class="date">4</td>
<td>300,500</td>
<td>300,500</td>
<td>0%</td>
</tr>
</tbody>
And here's the CSS
table {
float: left;
width: 100%;
height: auto;
margin-top: 20px;
table-layout: fixed;
display: table;
}
table tr{
border-bottom: 1px solid #ccc;
width: 100%;
}
table tr th{
text-align: center;
}
table tr td{
display: table-cell;
text-align: center;
}
So the question is that i want the td's with class date and day to have width by their own width like width = auto to avoid the table cell function. What do you guy's suggest i should do. Can i do this in CSS or shall i do a script for that.