Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pure CSS scrolling UL LI table with fixed header

I'm trying to implement a pure CSS scrolling UL-LI table with fixed header.

My requirements:

  • using table CSS (table, table-row, table-cell, table-header-group...)
  • all cells have to be list items (LI)
  • header has to be fixed when table content is scrolling
  • when table column changes width, appropriate header width should be changed

Currently I have HTML:

<ul class="testTable">
    <div class="testHeader">
        <li class="testRow">
            <span>ID</span>
            <span>Name</span>
            <span>Description</span>
            <span>Other details 1</span>
            <span>Other details 2</span>
        </li>
    </div>
    <div class="testBody">
        <li class="testRow">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
        </li>
        <li class="testRow">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
        </li>
    </div>
</ul>

...and CSS...

.testTable {
  display: table;
  margin: 0px;
  padding: 0px;
}

.testRow {
  display: table-row;
}

.testRow > span {
  list-style:none;
  display: table-cell;
  border: 1px solid #000;
  padding: 2px 6px;
}

.testHeader {
  display: table-header-group;
  /*position: absolute;*/
}

.testHeader span {
  background-color: #ccc;
}

.testBody {
  display: table-row-group;
}

Fiddle is here: http://jsfiddle.net/ozrentk/QUqyu/1/

BUT! The moment I try to fix position of the header using position: absolute or fixed, the table falls apart. I tried several techniques, but to no avail. Also, there is zero to none examples how to do this using pure table CSS.

This was close, but not exactly what I require.

Is there a CSS guru that can help me?

EDIT

Now, why the hell did I want to display this list as a table?

In my dynamic ASP.NET MVC driven site I have a number of places where I return unordered lists to the browser. Browser will then take this markup and display it to the reader. But the display format itself can actually depend on context, like users display-related preferences or the device format itself. CSS is used for the display formatting, as it should be. At last, if there is some display-light-n-magic-effect to be used, jQuery and/or a plugin should be used for that, and hopefully only for that.

You see, I want my server to remain display-format agnostic. That is, I don't want my server to care about how the particular client want his display to look like. I don't want if-blocks that return unordered-list-items in one case and table-cells in the other. Of course I could have two return points, one which returns ul/li/span format and the other which returns table/tr/td, but that would be violating DRY principle.

Another thing is that I'm using a really nice jQuery plugin that displays tabular data and can be fed with list-items, but not table markup. And I decided to stick with the plugin. because I like it, it's great and supports the way my site should work.

I hope this sorts things out. You see, using one paradigm can be in contrast with the other. It turns out I have to give away general-tabular-data-semantics to have a DRY code.

P.S. The more I think about this situation, the more it looks like a pragmatic, not a semantic problem.

like image 388
OzrenTkalcecKrznaric Avatar asked Jul 31 '13 14:07

OzrenTkalcecKrznaric


3 Answers

You can try this: DEMO

I got these correct in pure css:

  • using table CSS (table, table-row, table-cell, table-header-group...)
  • all cells have to be list items (LI)
  • header has to be fixed when table content is scrolling

The last requirement I had to use some jquery.

Anyway what I did was create two <li class="testRow"> for <div class="testHeader">. One of them has an id with css position:fixed

That trick accomplishes your first 3 requirements. The last one is really tricky for css alone so what I did was add jquery:

$(document).ready(function(e) {
    adjustHeader();
});

function adjustHeader(){
    //get width of the NOT fixed header spans
    var a = $("span#tid").width();
        b = $("span#tname").width();
        c = $("span#tdesc").width();
        d = $("span#tod1").width();
        e = $("span#tod2").width();

    //Change the width of the fixed header spans
    //with the other headers spans
    $("span#fid").width(a);
    $("span#fname").width(b);
    $("span#fdesc").width(c);
    $("span#fod1").width(d);
    $("span#fod2").width(e);
}

Hope it helped!

EDIT

Run function adjustHeader() everytime you add new data so that the headers will realign.

Here is a DEMO

like image 59
Jo E. Avatar answered Oct 18 '22 02:10

Jo E.


As soon as you specify either position: absolute or position: fixed on .testHeader, it sets display: block which overrides display: table-header-group.

See this thread for details.

like image 25
André Dion Avatar answered Oct 18 '22 04:10

André Dion


I believe I have solved this issue by creating a second header section. To start I duplicated the "testHeader" html:

    <div class="testHeader">
        <li class="testRow">
            <span>ID</span>
            <span>Name</span>
            <span>Description</span>
            <span>Other details 1</span>
            <span>Other details 2</span>
        </li>
    </div>
    <div class="secondHeader">
        <li class="testRow">
            <span>ID</span>
            <span>Name</span>
            <span>Description</span>
            <span>Other details 1</span>
            <span>Other details 2</span>
        </li>
    </div>

Note that the new "secondHeader" has a new class. This class is set to position absolute.

.secondHeader {
  display: table-header-group;
  position: fixed;
  top: 0px;
}

Then set the original header (that gives the table its structure) to visibility hidden.

.testHeader {
  display: table-header-group;
  visibility: hidden;
}

You should now have a list displayed as a table, with a fixed header element that stay in position when you re size. I updated your fiddle as a demo.

like image 22
Martyn0627 Avatar answered Oct 18 '22 02:10

Martyn0627