Nested table with table-layout: fixed affecting parent table - html

I'm giving my nested table (within a <td> element) the style table-layout: fixed. For some reason, this is affecting my parent table as well:
Demo:
document.getElementById('set-fixed').addEventListener('click', function() {
document.getElementById('result').innerHTML = (
document.getElementById('nested').classList.toggle('fixed')
? 'fixed'
: 'not fixed'
)
})
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 2px;
}
table.fixed {
table-layout: fixed;
}
<p>Set nested table's style <code>table-layout: fixed</code>: <button id="set-fixed">Toggle</button> (current: <span id='result'>not fixed</span>)</p>
<table width="100%">
<tr>
<th>Name</th>
<th>Description</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
<tr>
<td colspan="4">
<table id='nested' width="100%">
<tr>
<td>Foo</td>
<td>Baaaaaaar!</td>
<td>Baz</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>Taco</td>
<td>Beautiful, cheesy, and delicious.</td>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>Marshmallow</td>
<td>Too sweet for my tastes!</td>
<td>A</td>
<td>B</td>
</tr>
</table>
Is this a bug with Firefox, or intentional (according to the relevant official spec)? What can I do to make my nested table's layout fixed without affecting my parent table?

Related

Why is colspan and rowspan not formatting correctly in this table?

I have pasted my code below as well as a picture of what I am trying to accomplish. "Header 2" should span 3 columns instead of 2 and "DataA1",B1,C1 should span 2 columns instead of 1. But when I specify that in my code it doesn't do anything. I am not sure what error I have run into.
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td
{
border: 1px solid black;
border-collapse: collapse;
}
.title
{
padding: 10px;
}
</style>
</head>
<body>
<h1>Table</h1>
<table>
<tr>
<th colspan="4" class="title">A common header for three subheads</th>
<th rowspan="2">Header 3</th>
</tr>
<tr>
<th>Header 1</th>
<th colspan="3">Header 2</th>
</tr>
<tr>
<th>Thing A</th>
<td colspan="2">dataA1</td>
<td>dataA2</td>
<td>dataA3</td>
</tr>
<tr>
<th>Thing B</th>
<td colspan="2">dataB1</td>
<td>dataB2</td>
<td>dataC3</td>
</tr>
<tr>
<th>Thing C</th>
<td colspan="2">dataC1</td>
<td>dataC2</td>
<td>dataC3</td>
</tr>
</table>
</body>
</html>
"data A1" and the two cells below it do span two columns, and "Header2 " does span three columns, but there is no row where you would see this additional divison between column two and three. If you add a row with five cells you see what I mean (I only added that last row, I didn't change your code otherwise):
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
.title {
padding: 10px;
}
<h1>Table</h1>
<table>
<tr>
<th colspan="4" class="title">A common header for three subheads</th>
<th rowspan="2">Header 3</th>
</tr>
<tr>
<th>Header 1</th>
<th colspan="3">Header 2</th>
</tr>
<tr>
<th>Thing A</th>
<td colspan="2">dataA1</td>
<td>dataA2</td>
<td>dataA3</td>
</tr>
<tr>
<th>Thing B</th>
<td colspan="2">dataB1</td>
<td>dataB2</td>
<td>dataC3</td>
</tr>
<tr>
<th>Thing C</th>
<td colspan="2">dataC1</td>
<td>dataC2</td>
<td>dataC3</td>
</tr>
<tr>
<th>Thing D</th>
<td>dataD1a</td>
<td>dataD2</td>
<td>dataD3</td>
<td>dataC4</td>
</tr>
</table>
You need to add a final row that actually contains five cells for the behaviour of colspan="2" to be visible.
Then add a width to th and td to maintain the correct styles, and you can hide the empty row to match your design.
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.title {
padding: 10px;
}
th, td {
width: 20%;
}
<h1>Table</h1>
<table>
<tr>
<th colspan="4" class="title">A common header for three subheads</th>
<th rowspan="2">Header 3</th>
</tr>
<tr>
<th>Header 1</th>
<th colspan="3">Header 2</th>
</tr>
<tr>
<th>Thing A</th>
<td colspan="2">dataA1</td>
<td>dataA2</td>
<td>dataA3</td>
</tr>
<tr>
<th>Thing B</th>
<td colspan="2">dataB1</td>
<td>dataB2</td>
<td>dataC3</td>
</tr>
<tr>
<th>Thing C</th>
<td colspan="2">dataC1</td>
<td>dataC2</td>
<td>dataC3</td>
</tr>
<tr style="visibility: hidden;" aria-hidden="true">
<th></th><td></td><td></td><td></td><td></td>
</tr>
</table>

How to only make tbody vertically scrollable in a table which has dynamic column widths

I have table in the a page where I need to implement a vertical scroll only for the tbody part of the table. My table has columns of dynamic width, there's horizontal scrolling implemented if increase in width of a column causes the table to overflow. What I want is for only the body of the table to scroll on vertical overflow, but want the table header to remain visible. What I have implemented scrolls the entire table vertically
Following is my code for now. It has dummy data, as I cant post the actual code, but the structure is the same(jsfiddle link):
th,
td {
text-align: left;
padding: 5px;
outline: solid 0.5px;
}
table {
table-layout: auto;
width: 100%;
white-space: nowrap;
overflow-x: scroll;
overflow-y: scroll;
height: 100px;
display: block;
}
.container {
width: 300px;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
</table>
</div>
I have checked multitiple solutions on stackoverflow for this problem but they all set a fixed width for their columns and then use wrap the content inside if it exceeds the width. table with fixed thead and scrollable tbody
is the only solution that didn't completely mess up my page, but doesn't work, it gives different column widths for columns in header and body.
All other solutions, even the ones that use nested table use fixed width column, and the ones which don't use js/jQuery which I would rather not use unless its the absolute, last ever option. Can anyone please suggest something?
To make the <tbody> scrollable :
tbody{
display: block;
height: 100px;
width: 100%;
overflow-y: scroll;
}
And if you want to the <thead> to stay fixed while the body scrolls:
thead tr{
display: block
}
I'm unsure whether this is answering your question.
If the y axis is always to have a scroll and the x axis only to have
a scroll if there is too much information
CSS
overflow-x:auto;
overflow-y:scroll;
I came across this issue myself and found an alternate solution to the answer posted by #Abe Caymo
Simple non-ideal solution (by Abe)
The problem with Abe's solution is that it works fine up until you start to use thead and tfoot. Once you add these you will soon realize that the table column layout no longer syncs the column width across tbody, thead and tfoot. See demo below...
th,
td {
text-align: left;
padding: 5px;
outline: solid 0.5px;
}
table {
white-space: nowrap;
display: block;
}
tbody{
display: block;
height: 100px;
overflow-y: auto;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</tfoot>
</table>
</div>
Slightly more ideal solution
A better solution which maintains the auto table-layout is to set the thead and tfoot to position: sticky.
A few caveats and things to understand about this approach.
The overflow or element actually scrolling, is the div container of the table. You must have this and this is what you may use to control the size of the table. As such, the scroll bar will always be the full height of the scrollable table.
The background-color must be set to an opaque value otherwise the rows in the tbody will show behind the header as it passes below when scrolling.
The borders/outlines are much harder to get right but with a little finessing you can find a compatible style. Adding a border or outline to either thead or tfoot will not be sticky.
.container {
height: 140px;
min-height: 100px;
overflow: auto;
resize: vertical; /* only for demo */
}
thead,
tfoot {
/* must background-color otherwise transparent will show rows underneath */
background-color: white;
position: sticky;
}
thead {
margin-bottom: 0;
top: 0;
}
tfoot {
margin-top: 0;
bottom: 0;
}
th,
td {
text-align: left;
padding: 5px;
outline: solid black 0.5px;
}
table {
width: 100%;
}
<div class="container">
<table>
<thead>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Title 2</td>
<td>Jane Doe</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 3</td>
<td>John Doe</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
<tr>
<td>Title 4 is a long title</td>
<td>Name1</td>
<td>dfss</td>
<td>sdffsffsfd</td>
<td>sfsfs</td>
<td>sfsff</td>
</tr>
<tr>
<td>Title 5 is shorter</td>
<td>Name 2</td>
<td>dfsf</td>
<td>sdfsf</td>
<td>dfsf</td>
<td>sdfsf</td>
</tr>
<tr>
<td>Title 6</td>
<td>Name 3</td>
<td>sasas</td>
<td>eeeee</td>
<td>eEe</td>
<td>sfff</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Title 1</th>
<th>Name</th>
<th>Address</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
</tr>
</tfoot>
</table>
</div>
The final result will look something like that below with all columns aligned respectively...
Also see this solution using display: grid on the table element.

CSS - Select table with thead that has specifc class

i have a table as follows
<table class="bordered">
<thead class="info">
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
</tr>
<tbody>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr></tbody></table>
i want to apply borders to to table whose thead class is info
css currently contains
.bordered td{
border: 1px solid #0060a0 !important;
}
You can do this using a sibling selector
.bordered thead.info + tbody td
This selector targets all td elements within a tbody element which is an adjacent sibling to a thead.info element within a .bordered table. That sounds confusing, so here's a demo:
.bordered thead.info + tbody td {
border: 1px solid #0060a0;
}
<table class="bordered">
<thead class="info">
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>
A slightly more robust solution, which would be required if the table contained a tfoot element would be to use the more general sibling selector.
.bordered thead.info ~ tbody td {
border: 1px solid #0060a0;
}
<table class="bordered">
<thead class="info">
<tr>
<th>one</th>
<th>two</th>
<th>three</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="3">Footer</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
</tbody>
</table>

IE9 nested table fill height of parent td

I'm trying to nest tables and I want the nested tables to have heights equal to the heights of their containers.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="wrapper">
<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>a</td>
<td>b</td>
<td>c</td>
<td class="has-nested-table">
<table>
<tbody>
<tr>
<td>d</td>
<td>e</td>
</tr>
</tbody>
</table>
</td>
<td>f</td>
<td>g</td>
</tr>
<tr>
<td>h</td>
<td>i</td>
<td>j with some other letters because he has been so lonely lately</td>
<td class="has-nested-table">
<table>
<tbody>
<tr>
<td>k</td>
<td>l</td>
</tr>
</tbody>
</table>
</td>
<td>m</td>
<td>n</td>
</tr>
<tr>
<td>o</td>
<td>p</td>
<td>q</td>
<td class="has-nested-table">
<table>
<tbody>
<tr>
<td>r</td>
<td>s</td>
</tr>
<tr>
<td>t</td>
<td>u</td>
</tr>
<tr>
<td>v</td>
<td>w</td>
</tr>
</tbody>
</table>
</td>
<td>x</td>
<td>y</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
and here's the CSS
*
{
margin:0;
outline:0;
padding:0
}
html, body
{
font:normal 11px/1.4 Helvetica, Arial, Sans-Serif;
height:100%
}
.wrapper
{
margin:0 auto;
padding:0 10px;
width:940px
}
table
{
border-collapse:collapse;
height:100%;
table-layout:fixed;
width:100%
}
thead
{
background:#595959;
border:1px solid #595959
}
tbody, tr
{
height:100%
}
th
{
color:#f5f5f5
}
th, td
{
padding:5px
}
td
{
border:1px solid #ccc;
text-align:center;
vertical-align:top
}
td.has-nested-table
{
padding:0
}
td table
{
height:100%
}
td td
{
border-bottom:0;
border-left:0;
border-top:0;
vertical-align:top
}
td td:last-child
{
border:0
}
The nested tables expand in firefox and chrome but not in IE9. Help!
Add this css and then try
td.has-nested-table table{
height: auto;
}
The problem is that you are assigning the border to
td td {
and as the text takes in connecting column take more space as in
<td>j with some other letters because .... </td>
the nested table will not expand as it has only one row.
So to fix this, in addition to the #Harshit answer you need to add
td td { border: 0px; }
Check the http://jsfiddle.net/raunakkathuria/8UxbS/
working fine on IE and looks much better if border are not important in nested table, but if border are required then you need to add rowspan and stuff but that will not be full proof

Need a scrolling cell in an html table

I have an html table that contains a cell will a lot of data (maybe 200 lines).
Rather than requiring my page to scroll, I want my cell in the table to scroll.
I understand that I need a div block to do this. I defined a div block in my
css file but it is not taking.
How do I fix the height of my cell and give my data a scrollbar?
--------html table-----------
<table class="cmain">
<tr>
<td> TOP LEFT CELL <p>
<table> <tr> <td> A sub-table goes here </td> </tr> </table>
</td>
<td> TOP RIGHT CELL <p>
<p> A PHOTO GOES HERE.
<p> PHOTO: {{ form.image }}
</td>
<td rowspan="2" valign="top" >
THIS IS THE CELL THAT NEEDS THE SCROLL BAR. <div id="scrollcell">
SCROLLER CELL <hr>
<p> {% for customer in customer_list %}
<p> {{ customer }} </p>
{% endfor %}
</div>
</td>
</tr>
<tr>
<td> Another Sub-table goes here.
<table> <tr> <td> A sub-table goes here </td> </tr> </table>
</td>
<td> A NOTES FORM FIELD GOES HERE <p>
{{ form.notes }} </td>
</tr>
</table> <!-- end of CMAIN table -->
--------css -----------
table, th, td {
border: 1px solid white;
}
table.cmain {
border: 1px solid blue;
}
table.cmain td {
border: 1px solid blue;
font-weight: bold;
/*width: 300;*/
padding: 3px;
font-size: 0.8em;
}
#scrollcell {
width: 50px;
height: 50px;
overflow: auto;
}
I answered a question like this a while back, take a look at the answer here and the demo here.
EDIT
Posting code here for future reference for other posters:
HTML
<table style="text-align: left; width: 100%;" border="1" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th colspan="1" rowspan="5" style="border: medium none ; width: 100px; vertical-align: top;">
<div class="inner-table">
<table style="text-align: left; width: 500px; border:none" border="1" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
</tr>
<tr>
<td>a</td>
<td>a</td>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>c</td>
<td>c</td>
<td>c</td>
<td>c</td>
</tr>
</tbody>
</table>
</div>
</th>
<th>Header 4</th>
</tr>
<tr>
<td>a</td>
<td>a</td>
<td>a</td>
</tr>
<tr>
<td>b</td>
<td>b</td>
<td>b</td>
</tr>
<tr>
<td>c</td>
<td>c</td>
<td>c</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
CSS
.inner-table {
width:100px;
overflow-x:scroll;
}
th {
height:20px;
}
If you wish to make the vertical and horizontal scrollbars appear just replace overflow-x:scroll; with overflow:scroll for the .inner-table class.
The easiest solution would be to put the table into an iframe. Otherwise you can use either javascript or overflow.
give this td an absolute height and 100% width/height to the div
<td rowspan="2" valign="top" >
like
<td rowspan="2" valign="top" style="height:100px;">
and
#scrollcell {
width: 100%;
height: 100%;
overflow: auto;
}