LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   HTML How to get thead and tbody to align (https://www.linuxquestions.org/questions/programming-9/html-how-to-get-thead-and-tbody-to-align-4175649266/)

mfoley 02-28-2019 10:42 AM

HTML How to get thead and tbody to align
 
I'd like to have a scrollable <tbody> in my table with the header staying fixed. None of the "tips" I've found work for me (Firefox or IE). The following:
Code:

<table>
<thead>
  <tr><th> ... </th></tr>
  <tr><th> ... </th></tr>
</thead>

<tbody style="height: 500px; overflow-y: auto">
  <tr><td> ... </td></tr>
  <tr><td> ... </td></tr>
</tbody>
</table>

Does nothing special. The body is not scrollable.

The following:
Code:

<table>
<thead style="display: block">
  <tr><th> ... </th></tr>
  <tr><th> ... </th></tr>
</thead>

<tbody style="display: block; height: 500px; overflow-y: auto">
  <tr><td> ... </td></tr>
  <tr><td> ... </td></tr>
</tbody>
</table>

Does give me a scrollable tbody, but the thead is all compressed to the left, not aligned with tbody. setting thead to width: 100% does nothing. Keeping the "width: 100%", but removing the "display: block" from thead stretches the row all the way across the page, not just to the width of the table. Removing "width: 100%" and adding "display: table-header-group" also stretches the row to full page width.

I can't think of any combinations that will work other than using the 2nd example and hard-coding the width of header elements and body elements -- not what I want to do.

Suggestions?

Turbocapitalist 02-28-2019 11:21 AM

One ham-fisted way would be to force the columns to be certain widths.

Code:

    tr th { width: 10%; }
    tr td { width: 10%; }

Or

Code:

    tr th:nth-child(1) { width: 15%; }
    tr th:nth-child(2) { width: 10%; }
    tr th:nth-child(3) { width: 20%; }
    tr th:nth-child(4) { width: 25%; }
    tr th:nth-child(5) { width: 10%; }

    tr td:nth-child(1) { width: 15%; }
    tr td:nth-child(2) { width: 10%; }
    tr td:nth-child(3) { width: 20%; }
    tr td:nth-child(4) { width: 25%; }
    tr td:nth-child(5) { width: 10%; }

I would hope there is a better way though. Certainly I would have expected the table layout to default to what you are asking, but I guess it's not the case.

Turbocapitalist 02-28-2019 11:37 AM

I got curious and searched a bit. It looks like if you set the scope attribute, it fixes column widths:

Code:

    <thead>
      <tr>
        <th scope="col">One</th>
        <th scope="col">Two</th>
        <th scope="col">Three</th>
        <th scope="col">Four</th>
        <th scope="col">Five</th>
        <th scope="col">Six</th>
      </tr>
    </thead>


Source: https://www.w3.org/TR/WCAG20-TECHS/H63.html

scasey 02-28-2019 11:39 AM

You're putting each cell on a seperate row
Try
Code:

<table>
<thead style="display: block">
  <tr><th> ... </th><th> ... </th></tr>
</thead>

<tbody style="display: block; height: 500px; overflow-y: auto">
  <tr><td> ... </td><td> ... </td></tr>
</tbody>
</table>

Note that the code need not be on a single line
Code:

<tr>
    <th> ... </th>
    <th> ... </th>
</tr>

is equivalent, and is the way I'd usually write it.
Not sure what the CSS is doing for you.

PS: set width on the <table> tag, not on the <tr> tag.
Either
Code:

<table width=500px>
or, better,
Code:

<table style="width: 500px">

mfoley 02-28-2019 03:44 PM

Quote:

Originally Posted by Turbocapitalist (Post 5968233)
One ham-fisted way would be to force the columns to be certain widths.

Yes, I mentioned that, but that's exactly what I'm trying to avoid. Column widths may vary depending on contents.
Quote:

Originally Posted by Turbocapitalist (Post 5968239)
I got curious and searched a bit. It looks like if you set the scope attribute, it fixes column widths:

That didn't work. Using the scope="cols" exactly as you've shown still puts the header row to full-width of the page. Adding "display: block" compacts the header row to the left. This is true on both Firefox and IE. The scope attribute seems to have no effect at all. Your link does no really say that the scope attribute will align header cells with body cells, nor do the examples I looked at use thead and tbody.
Quote:

Originally Posted by scasey (Post 5968241)
You're putting each cell on a separate row
:
PS: set width on the <table> tag, not on the <tr> tag.

Actually, no I'm not. Look again. I am specifying more than one row in <thead>, but the cells are not on separate <tr>'s. I do have a width set on the table. I don't have any widths set on the <tr>.

Hopefully you all, or someone, has some additional ideas. Otherwise, it seems like setting explicit widths on the columns is the only solution -- which I'm not going to do. In which case I think the thead and tbody tags need a bit more work to be really useful.

scasey 02-28-2019 06:42 PM

Quote:

Originally Posted by mfoley (Post 5968212)
I'd like to have a scrollable <tbody> in my table with the header staying fixed. None of the "tips" I've found work for me (Firefox or IE). The following:
Code:

<table>
<thead>
  <tr><th> ... </th></tr>
  <tr><th> ... </th></tr>
</thead>

<tbody style="height: 500px; overflow-y: auto">
  <tr><td> ... </td></tr>
  <tr><td> ... </td></tr>
</tbody>
</table>

Does nothing special. The body is not scrollable.

The following:
Code:

<table>
<thead style="display: block">
  <tr><th> ... </th></tr>
  <tr><th> ... </th></tr>
</thead>

<tbody style="display: block; height: 500px; overflow-y: auto">
  <tr><td> ... </td></tr>
  <tr><td> ... </td></tr>
</tbody>
</table>

Actually, no I'm not. Look again. I am specifying more than one row in <thead>, but the cells are not on separate <tr>'s. I do have a width set on the table. I don't have any widths set on the <tr>.

I'm sorry, but
Code:

<tr><th>content</th></tr>
<tr><th>content</th></tr>

IS specifying two rows (<tr></tr>), each containing one cell (<th></th>)
and the only place you've set width is on the tbody tag, which is NOT the <table> tag

Please try my suggestions to see if they give you what you want...then state specifically why they don't, if they don't.

Does this help?

mfoley 02-28-2019 11:44 PM

Quote:

Originally Posted by scasey (Post 5968431)
I'm sorry, but
Code:

<tr><th>content</th></tr>
<tr><th>content</th></tr>

IS specifying two rows (<tr></tr>), each containing one cell (<th></th>)
and the only place you've set width is on the tbody tag, which is NOT the <table> tag

Please try my suggestions to see if they give you what you want...then state specifically why they don't, if they don't.

Does this help?

Perhaps my meta-syntax is throwing you off. I have elipses in the row description: <tr><th> ... </th></tr>, which was intended to mean multiple columns. The elipses were not intended to indicate <th> content. It would have been more clear had I done, <tr><th>text</th><th>text</th> ... <th>text</th><th>text</th></tr>.

In any case, my actual table <thead> section does have two rows of multiple columns. I've also done one row of multiple columns, makes no difference.

That link you referenced is exactly where I went in the first place, having never done anything with thead or tbody tags before.

As an experiment, if you think you have a handle on how this should work, snag the html below and see if any of your ideas let the thead section line up with the tbody. Never mind explicitly setting column widths. I know I can make that work. They also line up OK if there is no block/height/overflow styling on the tbody, but that, I think, is rather the point of having the thead/tbody tags. Otherwise, it's just a normal table and thead/tbody adds nothing.
Code:

<!DOCTYPE html>
<html>
<body>
<table>
<thead>
<tr><th>The</th><th>rain</th><th>in</th><th>Spain</th></tr>
</thead>
<tbody style="display: block; height: 80px; overflow-y: auto">
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
</tbody>
</table>
</body>
</html>

Thanks --Mark

ondoho 03-01-2019 12:47 AM

started fiddling, then i remembered:
some folks never search before posting.
try this:
HTML How to get thead and tbody to align

mfoley 03-01-2019 06:33 PM

Quote:

Originally Posted by ondoho (Post 5968539)
started fiddling, then i remembered:
some folks never search before posting.
try this:
HTML How to get thead and tbody to align

I'll assume that "never search" comment wasn't directed to me specifically. I visited all those pages previously. None of the ideas worked. The thead and tbody align just fine until you put the height and overflow-y attributes in the tbody. Try it. Copy/paste my simple example and try it in your browser. I've done some additional test settings based on those very suggested sites that don't work for aligning thead and tbody:
Code:

<style>
thead th{ display: table-cell;}   
</style>
</head>
<body>
<table style="table-layout:fixed">
<thead style="display: table-header-group;">
<tr><th>The</th><th>rain</th><th>in</th><th>Spain</th></tr>
</thead>
<tbody align=right style="display: block; height: 80px; overflow-y: auto;">


AnanthaP 03-01-2019 07:22 PM

I had read about javascript code about this topic now googled this.

https://codereview.stackexchange.com...igning-columns
It's got "run script options" to check it out.

Does it help?

mfoley 03-01-2019 08:07 PM

Quote:

Originally Posted by AnanthaP (Post 5968870)
I had read about javascript code about this topic now googled this.

https://codereview.stackexchange.com...igning-columns
It's got "run script options" to check it out.

Does it help?

Yeah, I saw that one too, but wow! He's got javascript, I assume running onload, that compares the width of the th cell in the <thead> (assuming all th's are in <thead>) with the width of the corresponding td cell in the <tbody> and sets both cells' widths to the max of either. This example assume only one table in the page as he gets all th and td elements, but that could be handled by adding names or ids or some other identifier to the elements of the target table.

I was hoping for something a bit less complex, but maybe that's as good as it gets. I'll experiment with that and post back.

Turbocapitalist 03-01-2019 11:26 PM

You might try asking on css-d -at- lists.css-discuss.org before sinking to javascript. That list, if any, would have people who should be able to figure out the answer to getting both the scrolling and the matching columns at the same time. If you do find an answer that is only CSS, please do remember to post it here.

mfoley 03-04-2019 11:14 AM

I'm throwing in the towel on this one. I tried a simplified javascript based on AnanthaP's link:
Code:

function adjusttbody()
{
    thElements = document.getElementsByTagName("th");
    tdElements = document.getElementsByTagName("td");

  for (var i = 0; i < thElements.length; i++)
        tdElements[i].style.width = thElements[i].offsetWidth + "px";
}

But that didn't work. If I need that elaborate set of css definitions the author of that link example has, it's not worth the trouble.

Turbocapitalist, excellent suggestion with the maillist, but I'm done investing time in this. Besides, if there were a css only solution someone would have probably posted it. I'm on a number of lists and normally those list postings are findable.

I suppose <tbody> could be useful for hiding sections of a table given multiple <tbody> statements, but for scrolling it seems near useless.

I'll revert to an easier solution I've used in the past which is to have 2 tables:
Code:

<table style="margin: 0; width: <nnn>px">
<tr><th>head1</th><th>head2</th> ... <th>headN</th></tr>
</table>
<div style="width: <nnn>px; margin: 0; height: <yyy>px; overflow: auto">
  <table style="margin: 0; width: 100%">
<tr><td>col1</td><td>col2></td> ... </td>colN</td></tr>
:
:
</table>
</div>

Then, all I have to do is adjust the column widths as needed. I could probably even use that script to do the width automatically. (I might try that)

mfoley 03-04-2019 11:41 AM

Actually, the <table><div> technique works like a champ with the auto-adjust javascript function. I don't even need to hard-code column widths unless I want to tweak. You do have to set the header table with and the <div> width to line up. To the devil with <thead><tbody>!
Code:

<!DOCTYPE html>
<html>
<head>
<style>
td, th { border: 1px solid red }
table { border-collapse: collapse }
</style>
<script>
function adjusttbody()
{
    thElements = document.getElementsByTagName("th");
    tdElements = document.getElementsByTagName("td");

    for (var i = 0; i < thElements.length; i++)
        thElements[i].style.width = tdElements[i].offsetWidth + "px";
}
</script>
</head>
<body onload="adjusttbody()">

<table style="margin: 0; width: 484px">
<tr><th>The</th><th>rain</th><th>in</th><th>Spain</th></tr>
</table>
<div style="width: 500px; margin: 0; height: 80px; overflow: auto">
<table style="margin: 0; width: 100%">
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
<tr><td>Falls mainly</td><td>In the Plain</td><td>Falls mainly</td><td>In the Plain</td></tr>
</table>
</body>
</html>


Turbocapitalist 03-04-2019 11:46 AM

What were the CSS specialists on the mailing list able to figure out? Or did they not respond?


All times are GMT -5. The time now is 03:59 PM.