简体   繁体   中英

Table with frozen header with vertical text

I wish to create a table where the thread is frozen and the labels in the thead are orientated in a vertical manner. My attempt is below, however there are a number of issues with this implementation since I am very new to css.

  1. One thing I don't like about my solution is that it is not obvious that there are more rows to be scrolled into view as the scroll bar is hidden until you start scrolling the table. Is there a way of making the scroll bar permanently visible?

  2. There is also a large scape at the top of the thead above where the party names are displayed. I can make this gap bigger by playing around with the values in th.vertical but I cant eliminate it. How can I force the thead to be only as high as the text it contains?

  3. Finally, I would like the vertical text in the thead to be centred with respect to the column values but I haven't figured out how to do this. How might I do this?

  4. I would also like to be able to sort on any column.

 table thead tr { display: block; } table th, table td { width: 75px; //fixed width } div.vertical { margin-left: -100px; position: absolute; width: 210px; transform: rotate(-90deg); -webkit-transform: rotate(-90deg); /* Safari/Chrome */ -moz-transform: rotate(-90deg); /* Firefox */ -o-transform: rotate(-90deg); /* Opera */ -ms-transform: rotate(-90deg); /* IE 9 */ } th.vertical { height: 60px; line-height: 14px; padding-bottom: 100px; text-align: left; } table tbody { display: block; height: 500px; overflow: auto; } 
 <table class='vrt-header'> <thead> <tr> <th></th> <th class="vertical"> <div class="vertical">Republican</div> </th> <th class="vertical"> <div class="vertical">Democrat</div> </th> <th class="vertical"> <div class="vertical">Libertarian</div> </th> <th class="vertical"> <div class="vertical">Green</div> </th> </tr> </thead> <tbody> <tr> <td> Alabama </td> <td> 65 </td> <td> 25 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> Alaska </td> <td> 75 </td> <td> 15 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> Arizona </td> <td> 55 </td> <td> 40 </td> <td> 5 </td> <td> 0 </td> </tr> <tr> <td> Arkansas </td> <td> 65 </td> <td> 25 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> California </td> <td> 25 </td> <td> 65 </td> <td> 3 </td> <td> 7 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> </tbody> </table> 

I've played with your code…

  1. I don't know about another way to always show the scrollbar than overflow-y: scroll; .
  2. I modified all the styling of your headers, but I couldn't find an easy way to automatically adjust the height after your transform . I used a fixed value.
  3. The new styling is correcting this point.
  4. I suggest you to try and read about the Stupid-Table-Plugin for jQuery to easily sort a table.

… Plus, I added:

  • Some styling on :hover to highlight the action on the th s.
  • An alternation of color for the rows, using the :nth-of-type() selector.

… and I ended-up with this snippet:

 // Doc here: https://joequery.github.io/Stupid-Table-Plugin/ $("#simpleTable").stupidtable(); 
 table thead, table tbody { display: block; } table tbody { height: 500px; overflow-y: scroll; /* To make the scroll bar always visible */ } thead th { position: relative; cursor: pointer; /* change cursor to show we can do an action */ height: 90px; background: #ccc; border-bottom: 2px solid black; } thead th:hover { background: #ccf; /* Styling on hover */ } thead th p { position: absolute; bottom: 20px; transform: rotate(-90deg); text-align: left; } table th, table th p, table td { width: 75px; } table td { text-align: center; } table tr td:first-of-type { text-align: left; } table tr:nth-of-type(odd) td { background: #eee; } table tr:nth-of-type(even) td { background: #ddd; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/stupidtable/1.1.3/stupidtable.min.js"></script> <table id="simpleTable" class='vrt-header'> <thead> <tr> <th data-sort="string"></th> <th data-sort="int"> <p>Republican</p> </th> <th data-sort="int"> <p>Democrat</p> </th> <th data-sort="int"> <p>Libertarian</p> </th> <th data-sort="int"> <p>Green</p> </th> </tr> </thead> <tbody> <tr> <td> Alabama </td> <td> 65 </td> <td> 25 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> Alaska </td> <td> 75 </td> <td> 15 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> Arizona </td> <td> 55 </td> <td> 40 </td> <td> 5 </td> <td> 0 </td> </tr> <tr> <td> Arkansas </td> <td> 65 </td> <td> 25 </td> <td> 10 </td> <td> 0 </td> </tr> <tr> <td> California </td> <td> 25 </td> <td> 65 </td> <td> 3 </td> <td> 7 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> <tr> <td> ? </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> <td> 0 </td> </tr> </tbody> </table> 

Hope it helps.

1) This is probably on a mac, which uses overlay scrollbars by default. Chrome and Safari support webkit-scroll properties that let you make it always visible, but not sure if you can override that in Firefox.

2) You may be running into the UA style sheet 's th entry: td, th { padding: 1px; } td, th { padding: 1px; } You can override it with th { padding: 0px; } th { padding: 0px; }

3) What you want is actually the default behavior of a table. But it isn't working for two reasons. This might be the toughest to tackle on your own, without using an off-the-shelf component. So unless you're doing this as an exercise I suggest not trying to reinvent the wheel. Instead, find a jquery plugin or angular component or something that provides this. I don't think it's possible to do all this (including rotating the headers) in a cross-browser compatible way without writing a bunch of javascript.

First reason is that setting div.vertical { position:absolute } takes them out of normal flow; the th positions its normal-flow children to align with the whole column, but not position:absolute stuff.

Second is you subtly created 3 tables because of tr { display:block } and the tbody {display:block} that allows scrolling. The layout code (approximately) sees them as a regular <div> s so sees <table><thead><div>...</div></thead><div>....</div></table> and creates a table cell, row, and section (aka tbody) to hold each <div> . Then inside that div it sees tr so creates a table to hold them.

So the columns in the table that lives under thead > tr aren't the same columns that hold your data. So even if you fixed the first reason, you'd still be contending with this.

Here's chrome's layout tree (ignore the hex):

 LayoutBlockFlow 0x23e069224010         HTML
    LayoutBlockFlow 0x23e069224138      BODY
      LayoutTable 0x23e069230010        TABLE class="vrt-header"
        LayoutTableSection 0x23e069240010   THEAD
          LayoutTableRow (anonymous) 0x23e06924c010
            LayoutTableCell (anonymous) 0x23e069254010
              LayoutBlockFlow 0x23e069224260    TR
                LayoutTable (anonymous) 0x23e0692301b0
                  LayoutTableSection (anonymous) 0x23e069240188
                    LayoutTableRow (anonymous) 0x23e06924c128
                      LayoutTableCell 0x23e069254150    TH
                      LayoutTableCell 0x23e069254290    TH class="vertical"
                        LayoutBlockFlow (positioned) 0x23e069224388 DIV class="vertical"
                          LayoutText 0x23e069264010 #text "Republican"
                      LayoutTableCell 0x23e0692543d0    TH class="vertical"
                        LayoutBlockFlow (positioned) 0x23e0692244b0 DIV class="vertical"
                          LayoutText 0x23e0692640e0 #text "Democrat"
                      LayoutTableCell 0x23e069254510    TH class="vertical"
                        LayoutBlockFlow (positioned) 0x23e0692245d8 DIV class="vertical"
                          LayoutText 0x23e0692641b0 #text "Libertarian"
                      LayoutTableCell 0x23e069254650    TH class="vertical"
                        LayoutBlockFlow (positioned) 0x23e069224700 DIV class="vertical"
                          LayoutText 0x23e069264280 #text "Green"
        LayoutTableSection (anonymous) 0x23e069240300
          LayoutTableRow (anonymous) 0x23e06924c240
            LayoutTableCell (anonymous) 0x23e069254790
              LayoutBlockFlow 0x23e069224828    TBODY
                LayoutTable (anonymous) 0x23e069230350
                  LayoutTableSection (anonymous) 0x23e069240478
                    LayoutTableRow 0x23e06924c358   TR
                      LayoutTableCell 0x23e0692548d0    TD
                        LayoutText 0x23e069264350   #text "\nAlabama\n"
                      LayoutTableCell 0x23e069254a10    TD
                        LayoutText 0x23e069264420   #text "\n65\n"
                      LayoutTableCell 0x23e069254b50    TD
                        LayoutText 0x23e0692644f0   #text "\n25\n"
                      LayoutTableCell 0x23e069254c90    TD
                        LayoutText 0x23e0692645c0   #text "\n10\n"
                      LayoutTableCell 0x23e069254dd0    TD
                        LayoutText 0x23e069264690   #text "\n0\n"
                    LayoutTableRow 0x23e06924c470   TR
                      LayoutTableCell 0x23e069254f10    TD
                        LayoutText 0x23e069264760   #text "\nAlaska\n"

I did everything you requested, all 4 here, nearly with css-only.

I could also code the 3rd question with only CSS! I set the height using padding and a div wrapper for th. Like this:

th.vertical {
  height: 0;
  vertical-align: bottom;
  text-align: left;
  cursor: pointer;
}
div.verticalWrapper {
    height: 0;
    padding-top: 100%;
    position: relative;
}

Note the padding-top: 100%

1) I created a table container div for this one.

.tableContainer {
  height: 400px;
  width: 500px;
  overflow: scroll;
}

For iOS it is simply a matter of preference: https://heresthethingblog.com/2015/03/10/mac-tip-macs-scroll-bars/

2) Since we are rotating the element, we need a height that is equal to width. I used css to do that and you can read related answer here

3) I used css transform.

4) Used the same method as @takit-isy

What you want to do is not an easy task. I would replace your tables with divs.

i wrote an example so you have an idea how it could look:

    <div class='table'>
  <div class='header'>
  <div ><p class="vertical first">&nbsp;</p></div>
  <div ><p class="vertical">Republican</p></div>
      <div ><p class="vertical">Democrat</p></div>
      <div ><p class="vertical">Libertarian</p></div>
      <div ><p class="vertical">Green</p></div>
  </div>
  <div class='scroller'>
 <div class='content'>
    <div>
      <div>Alabama</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Alaska</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arizona</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
      <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
  <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
    <div>
      <div>Arzkansas</div>
      <div>65</div>
      <div>25</div>
      <div>10</div>
      <div>0</div>
    </div>
  </div>
</div>
  </div>

.table{
  height:300px;
  width:500px;

}
.vertical{
  transform: rotate(-90deg);
  width:56px;
  margin:0px;
}
.first{
  padding-right: 268px;
}
.header{
  height:150px;
  width:500px;
  display:flex;
}
.header>div{
    display:flex;
  }
  .scroller{
     height:calc(100% - 50px);
     overflow-y:scroll;
  }
  .content{
    width:100%;
    display:table;
  }
.content>div{
  display:table-row;
  width:500px;
}
.content>div>div{
  display:table-cell;
}

http://jsfiddle.net/xjhun7zf/6/ `

(it is not perfect, because i wrote that in 20 minutes)

if you have 2 container, one for the head and one for the body, then you can set the head to a static position with a fixed height and your body with the rest height;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM