45

I have an table in HTML5 that I would like to add a scrollbar to. I want the table to show ten rows and then the user can scroll down to see other songs. How can I add the scrollbar?

Here is my code for the table in HTML5:

<table id="my_table" table border="5">
  <tr>
    <th>URL</th>
  </tr>
  <tr>
    <td>http://www.youtube.com/embed/evuSpI2Genw</td>
  </tr>
  <tr>
    <td>http://www.youtube.com/embed/evuSpI2Genw</td>
  </tr>
</table>

Here is my CSS code:

#my_table {
    border-radius: 20px;
    background-color: transparent;
    color: black;
    width: 500px;
    text-align: center;
}
Fred
  • 12,086
  • 7
  • 60
  • 83
Aaron
  • 1,061
  • 3
  • 14
  • 22

14 Answers14

53

If you have heading to your table columns and you don't want to scroll those headings then this solution could help you:

This solution needs thead and tbody tags inside table element.

table.tableSection {
    display: table;
    width: 100%;
}
table.tableSection thead, table.tableSection tbody {
    float: left;
    width: 100%;
}
table.tableSection tbody {
    overflow: auto;
    height: 150px;
}
table.tableSection tr {
    width: 100%;
    display: table;
    text-align: left;
}
table.tableSection th, table.tableSection td {
    width: 33%;
}

Working fiddle

With comments

Note: If you are sure that the vertical scrollbar is always present, then you can use css3 calc property to make the thead cells align with the tbody cells.

table.tableSection thead {
    padding-right:18px;   /* 18px is approx. value of width of scroll bar */
    width: calc(100% - 18px);
}

You can do the same by detecting presence of scrollbar using javascript and applying the above styles.

Mr_Green
  • 40,727
  • 45
  • 159
  • 271
  • 33
    This assumes fixed-width columns. – Nicolas Nov 02 '13 at 02:34
  • 2
    @NicolasMarchildon I didn't get your point.. I am not using here anywhere fixed width.. if you mean that all the widths are 33% then you can change those by assigning different classes or by using :first-child and sibling selectors. but keep in mind that the sum of the three columns (as here) should be equal to 100%. – Mr_Green Nov 02 '13 at 03:48
  • 6
    If you don't define the column width in the CSS (because f.e. it can vary at runtime depending on actual data), the alignment between header and body columns is lost. – Massimo Mar 14 '14 at 02:21
  • if you look at this exemple ( http://jsfiddle.net/5KJka/482/ ), you can see that the header is miss align by a size of a scroll bar. – darkzangel Apr 22 '14 at 07:57
  • 1
    @user864555 use `overflow-y: scroll` check this [fiddle](http://jsfiddle.net/5KJka/483/) – Mr_Green Apr 22 '14 at 08:05
  • @Massimo In those cases, only `word-break: break-all` could help which is not recommended to preserve content readability. – Mr_Green Apr 22 '14 at 08:08
  • 4
    This solution has the same problem that almost every other pure CSS solution I've seen has: if the table is wider than its container (e.g. because the user resized the browser window), the table body can scroll horizontally and become misaligned with the fixed headers. If you want to see this technique done right, look **[here](http://jsfiddle.net/doctorDestructo/x54uraaq/)**. For more info, see my answer to this **[other post](http://stackoverflow.com/questions/673153/html-table-with-fixed-headers/25818428#25818428)**. – DoctorDestructo Sep 15 '14 at 19:32
  • Why is the float:left necessary? I tried it without it and it broke, but I'm not able to see why the floating would be necessary. – Skitterm Jan 09 '15 at 22:23
  • @Skitterm to make it floating element instead of a table element. – Mr_Green Jan 10 '15 at 12:32
  • 13
    Nice but useless for me. If I have to define a fix width for the header and the columns this solution is not useful for my needs. I want the table to adapt dynamically to it's content and the width of the browser window. Did the browser developers not invent a more intelligent solution for this problem? For me it is obvious that a TH should be displayed over the corresponding TD and not in any other place. This is the SENSE of a table header! – Elmue Jan 29 '15 at 16:25
  • 1
    What If I have multiple TBODYs ? – Martin Jun 15 '15 at 09:38
  • So what if you want to add a horizontal scrollbar? =) – 71GA Dec 06 '15 at 17:10
  • @71GA then no need of doing any of this things. The default Horizontal scroll is fine. – Mr_Green Dec 07 '15 at 07:47
  • 1
    This does not seem to work with colspan. The width set by colspan seem to get ignored. Any fix for this? – Reality-Torrent Feb 08 '16 at 14:03
26

Instead of assuming as fixed width columns.

CSS

table.tableSection {
  display: table;
  width: 100%;
}

table.tableSection thead,
table.tableSection tbody {
  width: 100%;
}

table.tableSection thead {
  overflow-y: scroll;
  display: table;
  table-layout: fixed;
  width: calc(100% - 16px); /* assuming scrollbar width as 16px */
}

table.tableSection tbody {
  overflow: auto;
  height: 150px;
  display: block;
}

table.tableSection tr {
  width: 100%;
  text-align: left;
  display: table;
  table-layout: fixed;
}

Working Fiddle

Mr_Green
  • 40,727
  • 45
  • 159
  • 271
  • 2
    this is actual wizardry! 100% fluid with no extra markup – RozzA Dec 06 '16 at 22:54
  • 1
    This seems to force all of the columns to have the same width instead of adjusting to the content width. – BTJ Jan 18 '17 at 22:09
  • Excellent, excellent. Thanks! This worked for me without setting column widths, as well as setting percentages widths. Also nice that this is a no JS/jQuery, CSS-only solution. But I had to do some modifications in order to get it to work: - No need for the second rule - 100% thead and tbody width - as those will be calculated later. Took it off. - 3rd rule: drop "overflow-y: scroll" as the scroll bar is meant to show in tbody. - 4th rule: here you have to add "overflow-y: scroll;" so the scroll bar shows up, and "width: calc(100% - 16px);" or the body will be wider than the header. – GBU Mar 08 '17 at 19:34
11

This is technique I have used on a number of occasions. It is originally based on this fiddle with a number of modifications. It is also fluid and column widths can be fixed by adding a width style to the <th>.

/* this is for the main container of the table, also sets the height of the fixed header row */
.headercontainer {
  position: relative;
  border: 1px solid #222;
  padding-top: 37px;
  background: #000;
}
/* this is for the data area that is scrollable */
.tablecontainer {
  overflow-y: auto;
  height: 200px;
  background: #fff;
}

/* remove default cell borders and ensures table width 100% of its container*/
.tablecontainer table {
  border-spacing: 0;
  width:100%;
}

/* add a thin border to the left of cells, but not the first */
.tablecontainer td + td {
  border-left:1px solid #eee; 
}

/* cell padding and bottom border */
.tablecontainer td, th {
  border-bottom:1px solid #eee;
  padding: 10px;
}

/* make the default header height 0 and make text invisible */
.tablecontainer th {
    height: 0px;
    padding-top: 0;
    padding-bottom: 0;
    line-height: 0;
    visibility: hidden;
    white-space: nowrap;
}

/* reposition the divs in the header cells and place in the blank area of the headercontainer */
.tablecontainer th div{
  visibility: visible;
  position: absolute;
  background: #000;
  color: #fff;
  padding: 9px 10px;
  top: 0;
  margin-left: -10px;
  line-height: normal;
   border-left: 1px solid #222;
}
/* prevent the left border from above appearing in first div header */
th:first-child div{
  border: none;
}

/* alternate colors for rows */
.tablecontainer tbody  tr:nth-child(even){
     background-color: #ddd;
}
<div class="headercontainer">
  <div class="tablecontainer">
    <table>
      <thead>
        <tr>
          <th>
              Table attribute name
            <div>Table attribute name</div>
          </th>
          <th>
            Value
            <div>Value</div>
          </th>
          <th>
            Description
            <div>Description</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>align</td>
          <td>left, center, right</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
        </tr>
        <tr>
          <td>bgcolor</td>
          <td>rgb(x,x,x), #xxxxxx, colorname</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
        </tr>
        <tr>
          <td>border</td>
          <td>1,""</td>
          <td>Specifies whether the table cells should have borders or not</td>
        </tr>
        <tr>
          <td>cellpadding</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
        </tr>
        <tr>
          <td>cellspacing</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between cells</td>
        </tr>
        <tr>
          <td>frame</td>
          <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
          <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
        </tr>
        <tr>
          <td>rules</td>
          <td>none, groups, rows, cols, all</td>
          <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
        </tr>
        <tr>
          <td>summary</td>
          <td>text</td>
          <td>Not supported in HTML5. Specifies a summary of the content of a table</td>
        </tr>
        <tr>
          <td>width</td>
          <td>pixels, %</td>
          <td>Not supported in HTML5. Specifies the width of a table</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

Also as a JSFiddle

SausageFingers
  • 1,796
  • 5
  • 31
  • 52
  • 1
    This is fantastic and it is the best solution I have ever seen! Thank you for sharing this! – Vlad Frolov Dec 22 '16 at 22:42
  • 1
    Couldn't agree more, this has helped me massively! – Ankh Feb 23 '17 at 09:13
  • 1
    For anyone struggling to get this to work, I finally noticed that there's an extra div added to each element that contains the same header string. Nonetheless, this looks good and is easy to implement. Thanks. – Lee McPherson May 13 '17 at 19:23
7

A year or so has passed since the question was asked, but I wasn't satisfied with the answers. I fiddled for a while, and here is a code that:

  • works in IE8+ and all other browsers;
  • is very easy to understand;
  • lines up the cell borders perfectly (fixed-width cells);
  • fixes the head while the body scrolls;
  • automatically adapts to touch screens.

Live demo here: http://jsbin.com/bagaro/1/edit?html,output.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Scrollabe table</title>
    <!-- Substantially simplified and improved version of the table on
    http://www.cssbakery.com/2010/12/css-scrolling-tables-with-fixed.html -->
    <script>
        if ('ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch)) {
            document.documentElement.className += ' touchScreen';
        }
    </script>
    <style>
        /* BASICS: */
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box; /* in case block elements are used inside table cells */
    }
    html {
        font-size: 62.5%; /* standardizes older IEs */
    }
    body {
        font: normal 1.3em Verdana; /* = 13px */
    }
    table {
        border-collapse: collapse;
        table-layout: fixed;
        empty-cells: show;
    }
    td {
        border: 1px solid black;
        padding: 4px;
    }
        /* SCROLL TABLE ESSENTIALS (+ SOME ADDITIONAL CSS): */
    div#scrollTableContainer {
        width: 617px;
        margin: 40px; /* just for presentation purposes */
        border: 1px solid black;
    }
    .touchScreen div#scrollTableContainer {
        width: 600px; /* touch devices do not form scrollbars (= 17 px wide) */
    }
    #tHeadContainer {
        background: #CC3600;
        color: white;
        font-weight: bold;
    }
    #tBodyContainer {
        height: 240px;
        overflow-y: scroll;
    }
    .touchScreen #tBodyContainer {
        -webkit-overflow-scrolling: touch; /* smooths scrolling on touch screens */
    }
        /* FINER LAYOUT MATTERS: */
    tr:first-child td {
        border-top: 0;
    }
    #tBody tr.lastRow td {
        border-bottom: 0;
    }
    td:first-child {
        min-width: 108px; /* Firefox needs min- and max-widths */
        max-width: 108px;
        border-left: 0;
    }
    td:first-child + td {
        min-width: 125px;
        max-width: 125px;
    }
    td:first-child + td + td {
        min-width: 90px;
        max-width: 90px;
    }
    td:first-child + td + td + td {
        min-width: 95px;
        max-width: 95px;
    }
    td:first-child + td + td + td + td {
        width: 180px; /* here, Firefox messes up with only min- and max-widths */
        border-right: 0;
    }
        /* AND SOME CSS TO INFORM TOUCH SCREEN USERS: */
    p#touchDeviceText {
        display: none;
    }
    .touchScreen p#touchDeviceText {
        display: block;
    }
    </style>
</head>
<body>
    <p id="touchDeviceText">This table is scrollable</p>
    <div id="scrollTableContainer">
        <div id="tHeadContainer">
            <table id="tHead">
                <tr>
                    <td>Name</td>
                    <td>Operator</td>
                    <td>Began operation</td>
                    <td>Tonnage</td>
                    <td>Status</td>
                </tr>
            </table>
        </div><!-- tHeadContainer -->
        <div id="tBodyContainer">
            <table id="tBody">
                <tr>
                    <td>Seabourne Sun</td>
                    <td>Seabourn Cruise Line</td>
                    <td>1988</td>
                    <td>?</td>
                    <td>Ended service in 2002, currently operating as Prinsendam</td>
                </tr>
                <tr>
                    <td>Adventures of the Seas</td>
                    <td>Royal Caribbean International</td>
                    <td>2001</td>
                    <td>138,000</td>
                    <td>Operating</td>
                </tr>
                <tr>
                    <td>Oceanic Independence</td>
                    <td>American Hawaiian Cruises / American Global Line</td>
                    <td>1974</td>
                    <td>23,719</td>
                    <td>Named formerly (1951-1974) and subsequently renamed (1982-2006) the Independence, renamed the Oceanic (2006), sold for scrap in 2008 but remains in mothballs</td>
                </tr>
                <tr>
                    <td>Cunard Ambassador</td>
                    <td>Cunard Line</td>
                    <td>1972</td>
                    <td>14,160</td>
                    <td>Burnt 1974, rebuilt into a livestock carrier, renamed Linda Clausen, later Procyon, Raslan. Scrapped 1984 after a second fire.</td>
                </tr>
                <tr>
                    <td>Aegean Beauty</td>
                    <td>Voyages to Antiquity</td>
                    <td>1973</td>
                    <td>11,563</td>
                    <td>Formerly Aegean Dolphin and Aegean I. Operating</td>
                </tr>
                <tr>
                    <td>Serenade of the Seas</td>
                    <td>Royal Caribbean International</td>
                    <td>2003</td>
                    <td>90,090</td>
                    <td>Operating</td>
                </tr>
                <tr>
                    <td>Queen Elizabeth 2</td>
                    <td>Cunard Line</td>
                    <td>1969</td>
                    <td>70,327</td>
                    <td>Left fleet in November 2008</td>
                </tr>
                <tr>
                    <td>National Geographic Endeavour</td>
                    <td>Lindblad Expeditions</td>
                    <td>1996</td>
                    <td></td>
                    <td>Operating, also known as Endeavour</td>
                </tr>
                <tr class="lastRow">
                    <td>Liberty of the Seas</td>
                    <td>Royal Caribbean International</td>
                    <td>2007</td>
                    <td>154,407</td>
                    <td>Operating</td>
                </tr>
            </table>
        </div><!-- tBodyContainer -->
    </div><!-- scrollTableContainer -->
</body>
</html>
  • This really is the fastest and best scrolling table i've seen so far. I've tested it with 10k rows, and it loads and runs smoothly on all browsers i tested. – fiffy Aug 05 '14 at 14:22
  • @fiffy: thanks for the compliment! A small but significant update, a few minutes ago: the touch screen detection script has been improved, necessary because of different rules in the latest Windows version(s) in combination with Chrome. And I included the link to a live demo, on JSBin (that offers a wide enough result pane). – Frank Conijn - Support Ukraine Aug 06 '14 at 08:11
  • Just noting that it doesn't appear to work (anymore?) on iOS's Safari. – JacobEvelyn May 19 '15 at 23:34
  • @JacobEvelyn - that's JSBin that is disabling it on iOS. I just took the above code, put it in a stand-alone file, tested it, and on my iPad 8.3 it still scrolls perfectly. – Frank Conijn - Support Ukraine May 21 '15 at 19:34
  • Good to know, thanks. (In case the versions of Safari are different, I was on a phone.) – JacobEvelyn May 21 '15 at 19:59
4

use this table into a DIV

<div class="tbl_container">
<table> .... </table>
</div>


.tbl_container{ overflow:auto; width: 500px;height: 200px; }

and beside this if you want to make it more beautiful and attractive use the jscollpane to customized your scrollbar..

jogesh_pi
  • 9,762
  • 4
  • 37
  • 65
4

Using flexboxes, no javascript, and it is responsive.

/* styles */

table {
  font-family: sans-serif;
  border-collapse: collapse;
  max-height: 300px;
  overflow: auto;
}

td,
th {
  border: 1px solid #ddd;
  text-align: left;
  padding: 8px;
  background: #fff;
}

tr:nth-child(odd) td {
  background-color: #eee;
}

/* fixed headers */

table,
thead,
tbody {
  display: block;
}

thead {
  position: sticky;
  top: 0;
}

tr {
  display: flex;
}

th,
td {
  flex: 1;
  min-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
}
<h2>HTML Table</h2>
<div class=wrap>
  <table>
    <thead>
      <tr>
        <th>#</th>
        <th>Firstname</th>
        <th>Lastname</th>
        <th>Age</th>
        <th>City</th>
        <th>Country</th>
        <th>Sex</th>
        <th>Example</th>
        <th>Example</th>
        <th>ExampleReallyReallyLong</th>
        <th>Example</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Example Really Really Long</td>
        <td>ExampleReallyReallyLong</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Anna</td>
        <td>Pitt</td>
        <td>35</td>
        <td>New York</td>
        <td>USA</td>
        <td>Female</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
        <td>Yes</td>
      </tr>
    </tbody>
  </table>
</div>
Matt
  • 2,096
  • 14
  • 20
3

HTML :

    <h1>&darr; SCROLL &darr;</h1>
<table class="blue">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>

<h1 class="scrollMore">&darr; SCROLL MORE &darr;</h1>
<table class="purple">
  <thead>
    <tr>
      <th>Colonne 1</th>
      <th>Colonne 2</th>
      <th>Colonne 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
    <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
       <tr>
      <td>Non</td>
      <td>Mais</td>
      <td>Allo !</td>
    </tr>
  </tbody>
</table>
<h1 class="up scrollMore">&uarr; UP &uarr;</h1>

CSS:

body{
  font:1.2em normal Arial,sans-serif;
  color:#34495E;
}

h1{
  text-align:center;
  text-transform:uppercase;
  letter-spacing:-2px;
  font-size:2.5em;
  margin:20px 0;
}

.container{
  width:90%;
  margin:auto;
}

table{
  border-collapse:collapse;
  width:100%;
}

.blue{
  border:2px solid #1ABC9C;
}

.blue thead{
  background:#1ABC9C;
}

.purple{
  border:2px solid #9B59B6;
}

.purple thead{
  background:#9B59B6;
}

thead{
  color:white;
}

th,td{
  text-align:center;
  padding:5px 0;
}

tbody tr:nth-child(even){
  background:#ECF0F1;
}

tbody tr:hover{
background:#BDC3C7;
  color:#FFFFFF;
}

.fixed{
  top:0;
  position:fixed;
  width:auto;
  display:none;
  border:none;
}

.scrollMore{
  margin-top:600px;
}

.up{
  cursor:pointer;
}

JS (jQuery):

;(function($) {
   $.fn.fixMe = function() {
      return this.each(function() {
         var $this = $(this),
            $t_fixed;
         function init() {
            $this.wrap('<div class="container" />');
            $t_fixed = $this.clone();
            $t_fixed.find("tbody").remove().end().addClass("fixed").insertBefore($this);
            resizeFixed();
         }
         function resizeFixed() {
            $t_fixed.find("th").each(function(index) {
               $(this).css("width",$this.find("th").eq(index).outerWidth()+"px");
            });
         }
         function scrollFixed() {
            var offset = $(this).scrollTop(),
            tableOffsetTop = $this.offset().top,
            tableOffsetBottom = tableOffsetTop + $this.height() - $this.find("thead").height();
            if(offset < tableOffsetTop || offset > tableOffsetBottom)
               $t_fixed.hide();
            else if(offset >= tableOffsetTop && offset <= tableOffsetBottom && $t_fixed.is(":hidden"))
               $t_fixed.show();
         }
         $(window).resize(resizeFixed);
         $(window).scroll(scrollFixed);
         init();
      });
   };
})(jQuery);

$(document).ready(function(){
   $("table").fixMe();
   $(".up").click(function() {
      $('html, body').animate({
      scrollTop: 0
   }, 2000);
 });
});

For beginner programmer: If you don't want to download and host jQuery yourself, you can include it from a CDN (Content Delivery Network).

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head> 

Adding jQuery to Your Web Pages click here.

Reference: HERE

josef
  • 872
  • 9
  • 8
0

You can use a division class with the overflow attribute using the value scroll. Or you can enclose the table inside an iframe. The iframe works well with old and new IE browsers, but it may not work with other browsers and probably not with the latest IE.

 #myid { overflow-x: scroll; overflow-y: hide; width:200px; /* Or whatever the amount of pixels */ }
.myid { overflow-x: scroll; overflow-y: hide; width:200px; /* Or whatever the amount of pixels */ }

<div class="myid">
     <div class="row">Content1</div>
     <div class="row2">Content2</div>
</div>

<table id="myid"><tr><td>Content</td></tr></table>
user2132859
  • 405
  • 3
  • 8
0

you can try this

CSS:

          #table-wrapper {
                height:150px;
                overflow:auto;  
                margin-top:20px;
                  }
          #table-wrapper table {
                 width:100%;
                 color:#000;    
                 }
          #table-wrapper table thead th .text {
                  position:fixed;   
                  top:0px;  
                  height:20px;
                  width:35%;
                  border:1px solid red;
               }

HTML:

<div id="table-wrapper">

    <table>
        <thead>
            <tr>
                <th><span class="text">album</span></th>
                <th><span class="text">song</span></th>
                <th><span class="text">genre</span></th>
            </tr>
        </thead>
        <tbody>
<tr> <td> album 0</td> <td> song0</td> <td> genre0</td> </tr>
<tr> <td>album 1</td> <td>song 1</td> <td> genre1</td> </tr>
<tr> <td> album2</td> <td>song 2</td> <td> genre2</td> </tr>
<tr> <td> album3</td> <td>song 3</td> <td> genre3</td> </tr>
<tr> <td> album4</td> <td>song 4</td> <td>genre 4</td> </tr>
<tr> <td> album5</td> <td>song 5</td> <td>genre 5</td> </tr>
<tr> <td>album 6</td> <td> song6</td> <td> genre6</td> </tr>
<tr> <td>album 7</td> <td> song7</td> <td> genre7</td> </tr>
<tr> <td> album8</td> <td> song8</td> <td>genre 8</td> </tr>
<tr> <td> album9</td> <td> song9</td> <td> genre9</td> </tr>
<tr> <td> album10</td> <td>song 10</td> <td> genre10</td> </tr>
<tr> <td> album11</td> <td>song 11</td> <td> genre11</td> </tr>
<tr> <td> album12</td> <td> song12</td> <td> genre12</td> </tr>
<tr> <td>album 13</td> <td> song13</td> <td> genre13</td> </tr>
<tr> <td> album14</td> <td> song14</td> <td> genre14</td> </tr>
<tr> <td> album15</td> <td> song15</td> <td> genre15</td> </tr>
<tr> <td>album 16</td> <td> song16</td> <td> genre16</td> </tr>
<tr> <td>album 17</td> <td> song17</td> <td> genre17</td> </tr>
<tr> <td> album18</td> <td> song18</td> <td> genre18</td> </tr>
<tr> <td> album19</td> <td> song19</td> <td> genre19</td> </tr>
<tr> <td> album20</td> <td> song20</td> <td> genre20</td> </tr>    
        </tbody>
    </table>
  </div>

Check this fiddle : http://jsfiddle.net/Kritika/GLKxB/1/

this will keep the table head fixed ,and scroll only the table content .

Pbk1303
  • 3,702
  • 2
  • 32
  • 47
0

@jogesh_pi answer is a good solution, i've created a example here http://jsfiddle.net/pqgaS/5/, check it, hope this help

<div id="listtableWrapperScroll">
    <table id="listtable">
        <tr>
            <td>Data Data</td>
            <td>Data Data</td>
            <td>Data Data</td>                
        </tr>
    </table>
</div>

#listtableWrapperScroll{
    height:100px;
    width:460px;
    overflow-y:scroll;
    border:1px solid #777777;
    background:#FFFFF2;
}
#listtableWrapperScroll #listtable{
    width:440px;       
}
#listtableWrapperScroll #listtable tr td{
    border-bottom:1px dashed #444;
}
0
<!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Scrollable Table</title>
    <style type="text/css">
      * { padding: 0; margin: 0; }
      table.my_table { 
        font-family: verdana, arial, helvetica, sans-serif;
        font-size: 11px;
        cellspacing: 0; 
        border-collapse: collapse; 
        width: 283px;    
        }
      table.my_table th, table.my_table td { 
        border-bottom: 1px solid #999; 
        border-right: 1px solid #999; 
        }
      table.my_table th { background: #ffb; }
      table.my_table td { background: #ffe; }

      div.scrollableContainer { 
        height: 100px; 
        overflow: auto;  
        width: 300px; 
        margin: 40px;    
        border: 1px solid #999;
        background: #ffb;     
        }

    </style>
    </head>
    <body>
    <div class="scrollableContainer">
        <table class="my_table scrollable">
          <thead>
            <tr>
              <th>URL</th>
                </tr>
        </thead>

        <tbody>
                <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td> 
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td>                   
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td> 
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td>                   
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td> 
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td>                   
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td> 
                    </tr>

                    <tr>
              <td>http://www.youtube.com/embed/evuSpI2Genw</td>                   
                    </tr>
            </tbody>
          </table>
        </div>
      </body>
    </html>
0

My simplest solution is based on fixed columns layout. You'll have to set the width of each column, for example: 4 columns 100px each is equal to 400px total width.

table {
  table-layout: fixed;
  width: 400px;
}
td, th {
  width: 100px;
}

The fixed table layout algorithm has many advantages over the automatic table layout algorithm (for example: the horizontal layout only depends on the table's width and the width of the columns, not the contents of the cells; allows a browser to lay out the table faster than the automatic table layout; the browser can begin to display the table once the first row has been received; etc.)

Then, you'll have to separate the thead from the tbody by forcing their display style to block rather than to the default table-*

thead tr {
  display: block;
}
tbody {
  display: block;
  height: 256px;
  overflow-y: auto;
}

That what will make the tbody scrollable as a separate box and the thead unrelated from it. And that's the main reason why you had to fix the column widths as done above.

Working JsFiddle: https://jsfiddle.net/angiolep/65q1gdcy/1/

pangiole
  • 981
  • 9
  • 10
0

This was a challenging question. I think I finally have a solution that satisfies complete requirements: a vertical and horizontal scrollable dynamic table (dynamic because you can change the amount of rows and columns, and no cells have fixed width or height).

The HTML and CSS layout is quite simple as other people have mentioned. The key issue is recalculating (JavaScript) cell widths. And to make sure horizontal scrolling works, I also recalculate theader and tbody width.

Here's a fiddle https://jsfiddle.net/jmarcos00/6hv0dsj8/1/

HTML code:

<!--
thead and tbody have identifiers
table is inside a div container
-->
<div>
  <table>
    <thead id="mythead">
      <tr>
        <th>header one</th>
        <th>two</th>
        <th>header three</th>
        <th>header one</th>
        <th>two</th>
        <th>header three</th>
      </tr>
    </thead>
    <tbody id="mytbody">
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
      <tr>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
        <td>one</td>
        <td>data two</td>
        <td>three</td>
      </tr>
    </tbody>
  </table>
</div>

CSS code:

/* table border rule */
table, td, th { border: 1px solid black; }

/* display as block plus display vertical scroll bars */
thead, tbody { display: block; overflow-y: scroll; }

/* sample height */
tbody { height: 100px; }

/* sample width and horizontal scroll bar */
div { width: 200px; overflow-x: auto; }

JavaScript code:

var i, w, wtot, thtot, thw, tdw, theadtr, tbodytr;
var th_rect, td_rect, theadtr_rect, tbodytr_rect;
var safe = new Array();

// get thead and tbody
var mythead = document.getElementById("mythead");
var mytbody = document.getElementById("mytbody");

// get first tr of thead and tbody
theadtr = mythead.children[0];
tbodytr = mytbody.children[0];
theadtr_rect = theadtr.getBoundingClientRect();
tbodytr_rect = tbodytr.getBoundingClientRect();

// get width difference of longer first tr
//   difference between tr and parent
if (tbodytr_rect.width > theadtr_rect.width)
    wtot = mytbody.getBoundingClientRect().width - tbodytr_rect.width;
else
    wtot = mythead.getBoundingClientRect().width - theadtr_rect.width;

// get width difference between tr and total th width (first step)
thtot = theadtr_rect.width;

// get th thead array and td tbody array
theadtr = theadtr.children;
tbodytr = tbodytr.children;

// get loop
for (i = 0; i < theadtr.length; i++)
{
    // second step for width difference between tr and total th width
    th_rect = theadtr[i].getBoundingClientRect();
    td_rect = tbodytr[i].getBoundingClientRect();
    thtot -= th_rect.width;

    // get width of each th and first row td (without paddings etc)
    tdw = parseFloat(window.getComputedStyle(tbodytr[i]).getPropertyValue("width"));
    thw = parseFloat(window.getComputedStyle(theadtr[i]).getPropertyValue("width"));

    // get bigger width
    w = (tdw > thw) ? tdw : thw;
    safe.push(w);

    // add to width total (decimal value with paddings etc)
    w = (tdw > thw) ? td_rect.width : th_rect.width;
    wtot += w;
}

// consider tr width and total th width difference
wtot += thtot;

// set loop
for (i = 0; i < theadtr.length; i++)
{
    // set width to th and first row td
    w = safe[i] + "px";
    theadtr[i].style.width = w;
    tbodytr[i].style.width = w; 
}

// set width for thead and tbody
wtot = wtot + "px";
mythead.style.width = wtot;
mytbody.style.width = wtot;
0

I first tried the accepted answer by Mr Green, but I found my columns didn't align, that float:left seems very suspicious. When I went from no scollbar to scrollbar -- my table body shifted a few pixels and I lost alignment.

CODE PEN https://codepen.io/majorp/pen/gjrRMx

CSS

.width50px {
    width: 100px !important;
}

.width100px {
    width: 100px !important;
}


.fixed_headers {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
}

th {
    padding: 5px;
    text-align: left;
    font-weight:bold;
    height:50px;
}

td {
    padding: 5px;
    text-align: left;
}

thead, tr 
{
    display: block;
    position: relative;
}


tbody {
    display: block;
    overflow: auto;
    width: 100%;
    height: 500px;
}

.tableColumnHeader {
    height: 50px;
    font-weight: bold;
}




.lime {
    background-color: lime;
}
patrick
  • 16,091
  • 29
  • 100
  • 164