Home > Software engineering >  Using position:fixed in a table
Using position:fixed in a table

Time:01-03

I have looked at many other threads related to this issue, but none of them address this specific issue. I have used Excel to create a worksheet that I then saved as a webpage using Excel's Save as function. Excel generates some very strange HTML and CSS, but that isn't an issue. I was able to reduce the CSS file from 612 lines to 58 lines and accomplish the same look and feel. I was also able to reduce the HTML file for the sheet from 60654 lines to 60428 lines. I was also able to reduce the number of characters in the sheet file from 4139575 to 2960747.

Excel saves the entire worksheet as a single table filling the body of the webpage. Also, when the page is created, every TR tag has both a height attribute (in pixels) and a style height property (in points), and every TD tag has a width attribute (in pixels) and a style width property (in points).

Now I am trying to add CSS equivalents of freeze panes to the table. Everything I have tried results in breaking the page. When trying to fix the first two rows, the first row disappears and the second row loses the first 2 columns. When trying to fix the first two columns the second column gets reduced in width by over 50%. In both cases the whole table still scrolls up/down and left/right.

Here is the beginning of the table (including the COL statements for the first two columns) and the first TR/TD row and the first TD row of the second row (the first TD of the first row spans two rows).

<table border=0 cellpadding=0 cellspacing=0 width=6022 style='border-collapse: collapse;table-layout:fixed;width:4512pt'>
 <col width=40 style='width:30pt'>
 <col width=286 style='width:215pt'>
 <tr height=20 style='height:15.0pt'>
  <td colspan=2 rowspan=2 height=40  width=326 style='height:30.0pt; width:245pt'>&nbsp;</td>
  <td colspan=87  width=5696 style='width:4267pt'>&nbsp;</td>
 </tr>
 <tr height=20 style='height:15.0pt'>
  <td colspan=6 height=20  style='height:15.0pt'>Ranabastre</td>

And here is the CSS I have been trying to use:

.posfixtop {
    position:fixed;
    top:0px;
    left:0px;
    height:40px;
    width:100%;
    }
.posfixleft {
    position:fixed;
    top:0px;
    left:0px;
    height:100%;
    width:326px;
    }

I know that virtually every attribute used is not valid HTML according to HTML5. I have not removed them or replaced the ones that have no CSS version in the CSS file simply because they have not posed a problem so far.

Is there something I am missing here? I have thought that maybe you can't freeze columns or rows within a table, but I dread the thought of having to create multiple tables. The table is huge.

Edit: Looking at the HTML again I noticed that I stated something incorrectly above. The TD tags do not have width attributes or style width properties. The COL tags have those. The TR tags have height attributes and style height properties, and the first TD of each row also has a height attribute and a style height property.

New information:

I finally got the frozen rows issue solved. Here's the CSS that worked:

thead {
    position:sticky;
    top:0;
    min-height:120px;
    height:120px;
    z-index:50;
    background-color:black;
    }

I got information that helped me come up with that CSS from Freezing Row and Column in HTML Table Using CSS.

I put thead tags around the rows I wanted frozen to accomplish it. Also, Excel puts a border-collapse:collapse property on the table and I found that my cell borders weren't being preserved. I found an article here on stack overflow that answered the question by stating that border-collapse:separate should be used. I changed it accordingly and the border issue was solved:

Border style do not work with sticky position element

What I still haven't accomplished is frozen columns. When I put the posfixleft class on the td's representing the first two columns (using the first visible row below the headings as a test) what I get is the cell scrolls to the top of the screen and stops,while the rest of the rows disappear behind the header rows in a vertical scroll, and they stay positioned as expected in a horizontal scroll. I had to include the background-color property in the posfixleft class to prevent the data in the row from being visible as it scrolled behind the fixed columns.

So the remaining issue is, how do I get the first two columns to disappear behind the header rows when they are fixed? Also, I know the answer will probably be that I have to use javascript, but is there a simple solution to having to create 2 separate posfixleft classes for each and every row? I broke the big table into smaller tables (row-wise), but the longest resulting tables have 81 rows, 127 rows, 128 rows and 222 rows, not including the header rows.

CodePudding user response:

It turns out I answered my own questions, so here is my answer in the hope that it will benefit someone else in the future.

It is possible to fix rows and columns in a table without using divs or javascript. Below is a sample that shows how it works.

First, the HTML for a table with a 2-row header and 2 columns on the right that are fixed. The remaining columns and rows demonstrate the scrolling capability.

<table >
<col width:20 style="width:15pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<col width:80 style="width:40pt">
<thead>
<tr>
<td >&nbsp;</td>
<td >&nbsp;</td>
<td>header1</td>
<td>header2</td>
<td>header3</td>
<td>header4</td>
<td>header5</td>
<td>header6</td>
<td>header7</td>
<td>header8</td>
<td>header9</td>
</tr>
<tr>
<td >&nbsp;</td>
<td >&nbsp;</td>
<td>header1</td>
<td>header2</td>
<td>header3</td>
<td>header4</td>
<td>header5</td>
<td>header6</td>
<td>header7</td>
<td>header8</td>
<td>header9</td>
</tr>
</thead>
<tr>
<td >1</td>
<td >Item</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td >2</td>
<td >Item</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td >3</td>
<td >Item</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td >4</td>
<td >Item</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td >5</td>
<td >Item</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
</table>

Now for the CSS that handles all the style and freeze-panes:

body {
  margin-top:0;
  margin-right:0;
  margin-bottom:0;
  margin-left:0;
  }
.fixedTable {
    border-collapse:separate;
    table-layout:fixed;
    width:300px;
    height:100px;
    }
thead {
    position:sticky;
    top:0;
    min-height:40px;
    height:40px;
    z-index:50;
  color:white;
    background-color:black;
    }
.posfixleft1 {
    position:sticky;
    top:0;
    left:0;
    height:20px;
    width:20px;
    z-index:20;
  color:white;
    background-color:black;
    }
.posfixleft2 {
    position:sticky;
    top:0;
    left:20px;
    height:20px;
    width:80px;
    z-index:20;
  color:white;
    background-color:black;
    }
.posfixleft3 {
    position:sticky;
    top:0;
    left:0;
    height:20px;
    width:20px;
    z-index:20;
  color:white;
    background-color:black;
    }
.posfixleft4 {
    position:sticky;
    top:0;
    left:20px;
    height:20px;
    width:80px;
    z-index:20;
  color:white;
    background-color:black;
    }

Try it here

There is one issue with the jsfiddle that I am not having on my page. The table is displayed with a border around every cell, and when you scroll horizontally the left column moves slightly left. Likewise, when scrolling vertically the top of the table moves slightly up and there is some trash appearing in the left-most columns of the head section. I tried including a border:0; property in the fixedTable class but it did nothing so I removed it. Again, I am not having these issues on my web page, so I don't know what jsfiddle is doing differently.

  • Related