是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
一个更精致的纯CSS滚动表
到目前为止,我所见过的所有纯CSS解决方案——尽管它们可能很聪明——都缺乏一定程度的优化,或者在某些情况下不能正常工作。所以,我决定创建我自己的…
特点:
It's pure CSS, so no jQuery required (or any JavaScript code at all, for that matter) You can set the table width to a percent (a.k.a. "fluid") or a fixed value, or let the content determine its width (a.k.a. "auto") Column widths can also be fluid, fixed, or auto. Columns will never become misaligned with headers due to horizontal scrolling (a problem that occurs in every other CSS-based solution I've seen that doesn't require fixed widths). Compatible with all of the popular desktop browsers, including Internet Explorer back to version 8 Clean, polished appearance; no sloppy-looking 1-pixel gaps or misaligned borders; looks the same in all browsers
下面是一些显示流体和自动宽度选项的控件:
流体宽度和高度(适应屏幕大小):jsFiddle(注意,在此配置中,滚动条只在需要时显示,因此您可能必须缩小帧才能看到它) 自动宽度,固定高度(更容易与其他内容集成):jsFiddle
自动宽度,固定高度配置可能有更多的用例,所以我将在下面发布代码。
/* The following 'html' and 'body' rule sets are required only if using a % width or height*/ /*html { width: 100%; height: 100%; }*/ body { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0 20px 0 20px; text-align: center; } .scrollingtable { box-sizing: border-box; display: inline-block; vertical-align: middle; overflow: hidden; width: auto; /* If you want a fixed width, set it here, else set to auto */ min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */ height: 188px/*100%*/; /* Set table height here; can be fixed value or % */ min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */ font-family: Verdana, Tahoma, sans-serif; font-size: 16px; line-height: 20px; padding: 20px 0 20px 0; /* Need enough padding to make room for caption */ text-align: left; color: black; } .scrollingtable * {box-sizing: border-box;} .scrollingtable > div { position: relative; border-top: 1px solid black; height: 100%; padding-top: 20px; /* This determines column header height */ } .scrollingtable > div:before { top: 0; background: cornflowerblue; /* Header row background color */ } .scrollingtable > div:before, .scrollingtable > div > div:after { content: ""; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; } .scrollingtable > div > div { min-height: 0/*43px*/; /* If using % height, make this large enough to fit scrollbar arrows */ max-height: 100%; overflow: scroll/*auto*/; /* Set to auto if using fixed or % width; else scroll */ overflow-x: hidden; border: 1px solid black; /* Border around table body */ } .scrollingtable > div > div:after {background: white;} /* Match page background color */ .scrollingtable > div > div > table { width: 100%; border-spacing: 0; margin-top: -20px; /* Inverse of column header height */ /*margin-right: 17px;*/ /* Uncomment if using % width */ } .scrollingtable > div > div > table > caption { position: absolute; top: -20px; /*inverse of caption height*/ margin-top: -1px; /*inverse of border-width*/ width: 100%; font-weight: bold; text-align: center; } .scrollingtable > div > div > table > * > tr > * {padding: 0;} .scrollingtable > div > div > table > thead { vertical-align: bottom; white-space: nowrap; text-align: center; } .scrollingtable > div > div > table > thead > tr > * > div { display: inline-block; padding: 0 6px 0 6px; /*header cell padding*/ } .scrollingtable > div > div > table > thead > tr > :first-child:before { content: ""; position: absolute; top: 0; left: 0; height: 20px; /*match column header height*/ border-left: 1px solid black; /*leftmost header border*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div > div:first-child, .scrollingtable > div > div > table > thead > tr > * + :before { position: absolute; top: 0; white-space: pre-wrap; color: white; /*header row font color*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);} .scrollingtable > div > div > table > thead > tr > * + :before { content: ""; display: block; min-height: 20px; /* Match column header height */ padding-top: 1px; border-left: 1px solid black; /* Borders between header cells */ } .scrollingtable .scrollbarhead {float: right;} .scrollingtable .scrollbarhead:before { position: absolute; width: 100px; top: -1px; /* Inverse border-width */ background: white; /* Match page background color */ } .scrollingtable > div > div > table > tbody > tr:after { content: ""; display: table-cell; position: relative; padding: 0; border-top: 1px solid black; top: -1px; /* Inverse of border width */ } .scrollingtable > div > div > table > tbody {vertical-align: top;} .scrollingtable > div > div > table > tbody > tr {background: white;} .scrollingtable > div > div > table > tbody > tr > * { border-bottom: 1px solid black; padding: 0 6px 0 6px; height: 20px; /* Match column header height */ } .scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;} .scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */ .scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */ <div class="scrollingtable"> <div> <div> <table> <caption>Top Caption</caption> <thead> <tr> <th><div label="Column 1"/></th> <th><div label="Column 2"/></th> <th><div label="Column 3"/></th> <th> <!-- More versatile way of doing column label; requires two identical copies of label --> <div><div>Column 4</div><div>Column 4</div></div> </th> <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW --> </tr> </thead> <tbody> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> </tbody> </table> </div> Faux bottom caption </div> </div> <!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
我用来冻结标题行的方法与d-Pixie的方法类似,因此请参阅他的帖子以获得解释。该技术存在大量错误和限制,只能通过大量额外的CSS和一两个额外的div容器来修复。
其他回答
通过将StickyTableHeaders jQuery插件应用到表格中,当你向下滚动时,列标题将粘在视口的顶部。
例子:
$(function () { $("table").stickyTableHeaders(); }); /*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */ ; (function ($, window, undefined) { 'use strict'; var name = 'stickyTableHeaders', id = 0, defaults = { fixedOffset: 0, leftOffset: 0, marginTop: 0, scrollableArea: window }; function Plugin(el, options) { // To avoid scope issues, use 'base' instead of 'this' // to reference this class from internal events and functions. var base = this; // Access to jQuery and DOM versions of element base.$el = $(el); base.el = el; base.id = id++; base.$window = $(window); base.$document = $(document); // Listen for destroyed, call teardown base.$el.bind('destroyed', $.proxy(base.teardown, base)); // Cache DOM refs for performance reasons base.$clonedHeader = null; base.$originalHeader = null; // Keep track of state base.isSticky = false; base.hasBeenSticky = false; base.leftOffset = null; base.topOffset = null; base.init = function () { base.$el.each(function () { var $this = $(this); // remove padding on <table> to fix issue #7 $this.css('padding', 0); base.$originalHeader = $('thead:first', this); base.$clonedHeader = base.$originalHeader.clone(); $this.trigger('clonedHeader.' + name, [base.$clonedHeader]); base.$clonedHeader.addClass('tableFloatingHeader'); base.$clonedHeader.css('display', 'none'); base.$originalHeader.addClass('tableFloatingHeaderOriginal'); base.$originalHeader.after(base.$clonedHeader); base.$printStyle = $('<style type="text/css" media="print">' + '.tableFloatingHeader{display:none !important;}' + '.tableFloatingHeaderOriginal{position:static !important;}' + '</style>'); $('head').append(base.$printStyle); }); base.setOptions(options); base.updateWidth(); base.toggleHeaders(); base.bind(); }; base.destroy = function () { base.$el.unbind('destroyed', base.teardown); base.teardown(); }; base.teardown = function () { if (base.isSticky) { base.$originalHeader.css('position', 'static'); } $.removeData(base.el, 'plugin_' + name); base.unbind(); base.$clonedHeader.remove(); base.$originalHeader.removeClass('tableFloatingHeaderOriginal'); base.$originalHeader.css('visibility', 'visible'); base.$printStyle.remove(); base.el = null; base.$el = null; }; base.bind = function () { base.$scrollableArea.on('scroll.' + name, base.toggleHeaders); if (!base.isWindowScrolling) { base.$window.on('scroll.' + name + base.id, base.setPositionValues); base.$window.on('resize.' + name + base.id, base.toggleHeaders); } base.$scrollableArea.on('resize.' + name, base.toggleHeaders); base.$scrollableArea.on('resize.' + name, base.updateWidth); }; base.unbind = function () { // unbind window events by specifying handle so we don't remove too much base.$scrollableArea.off('.' + name, base.toggleHeaders); if (!base.isWindowScrolling) { base.$window.off('.' + name + base.id, base.setPositionValues); base.$window.off('.' + name + base.id, base.toggleHeaders); } base.$scrollableArea.off('.' + name, base.updateWidth); }; base.toggleHeaders = function () { if (base.$el) { base.$el.each(function () { var $this = $(this), newLeft, newTopOffset = base.isWindowScrolling ? ( isNaN(base.options.fixedOffset) ? base.options.fixedOffset.outerHeight() : base.options.fixedOffset) : base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0), offset = $this.offset(), scrollTop = base.$scrollableArea.scrollTop() + newTopOffset, scrollLeft = base.$scrollableArea.scrollLeft(), scrolledPastTop = base.isWindowScrolling ? scrollTop > offset.top : newTopOffset > offset.top, notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset)); if (scrolledPastTop && notScrolledPastBottom) { newLeft = offset.left - scrollLeft + base.options.leftOffset; base.$originalHeader.css({ 'position': 'fixed', 'margin-top': base.options.marginTop, 'left': newLeft, 'z-index': 3 // #18: opacity bug }); base.leftOffset = newLeft; base.topOffset = newTopOffset; base.$clonedHeader.css('display', ''); if (!base.isSticky) { base.isSticky = true; // make sure the width is correct: the user might have resized the browser while in static mode base.updateWidth(); } base.setPositionValues(); } else if (base.isSticky) { base.$originalHeader.css('position', 'static'); base.$clonedHeader.css('display', 'none'); base.isSticky = false; base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader)); } }); } }; base.setPositionValues = function () { var winScrollTop = base.$window.scrollTop(), winScrollLeft = base.$window.scrollLeft(); if (!base.isSticky || winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) { return; } base.$originalHeader.css({ 'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop), 'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft) }); }; base.updateWidth = function () { if (!base.isSticky) { return; } // Copy cell widths from clone if (!base.$originalHeaderCells) { base.$originalHeaderCells = $('th,td', base.$originalHeader); } if (!base.$clonedHeaderCells) { base.$clonedHeaderCells = $('th,td', base.$clonedHeader); } var cellWidths = base.getWidth(base.$clonedHeaderCells); base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells); // Copy row width from whole table base.$originalHeader.css('width', base.$clonedHeader.width()); }; base.getWidth = function ($clonedHeaders) { var widths = []; $clonedHeaders.each(function (index) { var width, $this = $(this); if ($this.css('box-sizing') === 'border-box') { width = $this[0].getBoundingClientRect().width; // #39: border-box bug } else { var $origTh = $('th', base.$originalHeader); if ($origTh.css('border-collapse') === 'collapse') { if (window.getComputedStyle) { width = parseFloat(window.getComputedStyle(this, null).width); } else { // ie8 only var leftPadding = parseFloat($this.css('padding-left')); var rightPadding = parseFloat($this.css('padding-right')); // Needs more investigation - this is assuming constant border around this cell and it's neighbours. var border = parseFloat($this.css('border-width')); width = $this.outerWidth() - leftPadding - rightPadding - border; } } else { width = $this.width(); } } widths[index] = width; }); return widths; }; base.setWidth = function (widths, $clonedHeaders, $origHeaders) { $clonedHeaders.each(function (index) { var width = widths[index]; $origHeaders.eq(index).css({ 'min-width': width, 'max-width': width }); }); }; base.resetWidth = function ($clonedHeaders, $origHeaders) { $clonedHeaders.each(function (index) { var $this = $(this); $origHeaders.eq(index).css({ 'min-width': $this.css('min-width'), 'max-width': $this.css('max-width') }); }); }; base.setOptions = function (options) { base.options = $.extend({}, defaults, options); base.$scrollableArea = $(base.options.scrollableArea); base.isWindowScrolling = base.$scrollableArea[0] === window; }; base.updateOptions = function (options) { base.setOptions(options); // scrollableArea might have changed base.unbind(); base.bind(); base.updateWidth(); base.toggleHeaders(); }; // Run initializer base.init(); } // A plugin wrapper around the constructor, // preventing against multiple instantiations $.fn[name] = function (options) { return this.each(function () { var instance = $.data(this, 'plugin_' + name); if (instance) { if (typeof options === 'string') { instance[options].apply(instance); } else { instance.updateOptions(options); } } else if (options !== 'destroy') { $.data(this, 'plugin_' + name, new Plugin(this, options)); } }); }; })(jQuery, window); body { margin: 0 auto; padding: 0 20px; font-family: Arial, Helvetica, sans-serif; font-size: 11px; color: #555; } table { border: 0; padding: 0; margin: 0 0 20px 0; border-collapse: collapse; } th { padding: 5px; /* NOTE: th padding must be set explicitly in order to support IE */ text-align: right; font-weight:bold; line-height: 2em; color: #FFF; background-color: #555; } tbody td { padding: 10px; line-height: 18px; border-top: 1px solid #E0E0E0; } tbody tr:nth-child(2n) { background-color: #F7F7F7; } tbody tr:hover { background-color: #EEEEEE; } td { text-align: right; } td:first-child, th:first-child { text-align: left; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <div style="width:3000px">some really really wide content goes here</div> <table> <thead> <tr> <th colspan="9">Companies listed on NASDAQ OMX Copenhagen.</th> </tr> <tr> <th>Full name</th> <th>CCY</th> <th>Last</th> <th>+/-</th> <th>%</th> <th>Bid</th> <th>Ask</th> <th>Volume</th> <th>Turnover</th> </tr> </thead> <tbody> <tr> <td>A.P. Møller...</td> <td>DKK</td> <td>33,220.00</td> <td>760</td> <td>2.34</td> <td>33,140.00</td> <td>33,220.00</td> <td>594</td> <td>19,791,910</td> </tr> <tr> <td>A.P. Møller...</td> <td>DKK</td> <td>34,620.00</td> <td>640</td> <td>1.88</td> <td>34,620.00</td> <td>34,700.00</td> <td>9,954</td> <td>346,530,246</td> </tr> <tr> <td>Carlsberg A</td> <td>DKK</td> <td>380</td> <td>0</td> <td>0</td> <td>371</td> <td>391.5</td> <td>6</td> <td>2,280</td> </tr> <tr> <td>Carlsberg B</td> <td>DKK</td> <td>364.4</td> <td>8.6</td> <td>2.42</td> <td>363</td> <td>364.4</td> <td>636,267</td> <td>228,530,601</td> </tr> <tr> <td>Chr. Hansen...</td> <td>DKK</td> <td>114.5</td> <td>-1.6</td> <td>-1.38</td> <td>114.2</td> <td>114.5</td> <td>141,822</td> <td>16,311,454</td> </tr> <tr> <td>Coloplast B</td> <td>DKK</td> <td>809.5</td> <td>11</td> <td>1.38</td> <td>809</td> <td>809.5</td> <td>85,840</td> <td>69,363,301</td> </tr> <tr> <td>D/S Norden</td> <td>DKK</td> <td>155</td> <td>-1.5</td> <td>-0.96</td> <td>155</td> <td>155.1</td> <td>51,681</td> <td>8,037,225</td> </tr> <tr> <td>Danske Bank</td> <td>DKK</td> <td>69.05</td> <td>2.55</td> <td>3.83</td> <td>69.05</td> <td>69.2</td> <td>1,723,719</td> <td>115,348,068</td> </tr> <tr> <td>DSV</td> <td>DKK</td> <td>105.4</td> <td>0.2</td> <td>0.19</td> <td>105.2</td> <td>105.4</td> <td>674,873</td> <td>71,575,035</td> </tr> <tr> <td>FLSmidth & Co.</td> <td>DKK</td> <td>295.8</td> <td>-1.8</td> <td>-0.6</td> <td>295.1</td> <td>295.8</td> <td>341,263</td> <td>100,301,032</td> </tr> <tr> <td>G4S plc</td> <td>DKK</td> <td>22.53</td> <td>0.05</td> <td>0.22</td> <td>22.53</td> <td>22.57</td> <td>190,920</td> <td>4,338,150</td> </tr> <tr> <td>Jyske Bank</td> <td>DKK</td> <td>144.2</td> <td>1.4</td> <td>0.98</td> <td>142.8</td> <td>144.2</td> <td>78,163</td> <td>11,104,874</td> </tr> <tr> <td>Københavns ...</td> <td>DKK</td> <td>1,580.00</td> <td>-12</td> <td>-0.75</td> <td>1,590.00</td> <td>1,620.00</td> <td>82</td> <td>131,110</td> </tr> <tr> <td>Lundbeck</td> <td>DKK</td> <td>103.4</td> <td>-2.5</td> <td>-2.36</td> <td>103.4</td> <td>103.8</td> <td>157,162</td> <td>16,462,282</td> </tr> <tr> <td>Nordea Bank</td> <td>DKK</td> <td>43.22</td> <td>-0.06</td> <td>-0.14</td> <td>43.22</td> <td>43.25</td> <td>167,520</td> <td>7,310,143</td> </tr> <tr> <td>Novo Nordisk B</td> <td>DKK</td> <td>552.5</td> <td>-3.5</td> <td>-0.63</td> <td>550.5</td> <td>552.5</td> <td>843,533</td> <td>463,962,375</td> </tr> <tr> <td>Novozymes B</td> <td>DKK</td> <td>805.5</td> <td>5.5</td> <td>0.69</td> <td>805</td> <td>805.5</td> <td>152,188</td> <td>121,746,199</td> </tr> <tr> <td>Pandora</td> <td>DKK</td> <td>39.04</td> <td>0.94</td> <td>2.47</td> <td>38.8</td> <td>39.04</td> <td>350,965</td> <td>13,611,838</td> </tr> <tr> <td>Rockwool In...</td> <td>DKK</td> <td>492</td> <td>0</td> <td>0</td> <td>482</td> <td>492</td> <td></td> <td></td> </tr> <tr> <td>Rockwool In...</td> <td>DKK</td> <td>468</td> <td>12</td> <td>2.63</td> <td>465.2</td> <td>468</td> <td>9,885</td> <td>4,623,850</td> </tr> <tr> <td>Sydbank</td> <td>DKK</td> <td>95</td> <td>0.05</td> <td>0.05</td> <td>94.7</td> <td>95</td> <td>103,438</td> <td>9,802,899</td> </tr> <tr> <td>TDC</td> <td>DKK</td> <td>43.6</td> <td>0.13</td> <td>0.3</td> <td>43.5</td> <td>43.6</td> <td>845,110</td> <td>36,785,339</td> </tr> <tr> <td>Topdanmark</td> <td>DKK</td> <td>854</td> <td>13.5</td> <td>1.61</td> <td>854</td> <td>855</td> <td>38,679</td> <td>32,737,678</td> </tr> <tr> <td>Tryg</td> <td>DKK</td> <td>290.4</td> <td>0.3</td> <td>0.1</td> <td>290</td> <td>290.4</td> <td>94,587</td> <td>27,537,247</td> </tr> <tr> <td>Vestas Wind...</td> <td>DKK</td> <td>90.15</td> <td>-4.2</td> <td>-4.45</td> <td>90.1</td> <td>90.15</td> <td>1,317,313</td> <td>121,064,314</td> </tr> <tr> <td>William Dem...</td> <td>DKK</td> <td>417.6</td> <td>0.1</td> <td>0.02</td> <td>417</td> <td>417.6</td> <td>64,242</td> <td>26,859,554</td> </tr> </tbody> </table> <div style="height: 4000px">lots of content down here...</div>
我一直在寻找一个解决方案,发现大多数答案都不工作或不适合我的情况,所以我用jQuery编写了一个简单的解决方案。
这是解决方案大纲:
克隆需要固定表头的表,并放置 在原拷贝之上的克隆拷贝。 从主表上拆下表体。 从底部表中删除表头。 调整列的宽度。(我们跟踪原始列的宽度)
下面是一个可运行的演示代码。
function scrolify(tblAsJQueryObject, height) { var oTbl = tblAsJQueryObject; // for very large tables you can remove the four lines below // and wrap the table with <div> in the mark-up and assign // height and overflow property var oTblDiv = $("<div/>"); oTblDiv.css('height', height); oTblDiv.css('overflow', 'scroll'); oTbl.wrap(oTblDiv); // save original width oTbl.attr("data-item-original-width", oTbl.width()); oTbl.find('thead tr td').each(function() { $(this).attr("data-item-original-width", $(this).width()); }); oTbl.find('tbody tr:eq(0) td').each(function() { $(this).attr("data-item-original-width", $(this).width()); }); // clone the original table var newTbl = oTbl.clone(); // remove table header from original table oTbl.find('thead tr').remove(); // remove table body from new table newTbl.find('tbody tr').remove(); oTbl.parent().parent().prepend(newTbl); newTbl.wrap("<div/>"); // replace ORIGINAL COLUMN width newTbl.width(newTbl.attr('data-item-original-width')); newTbl.find('thead tr td').each(function() { $(this).width($(this).attr("data-item-original-width")); }); oTbl.width(oTbl.attr('data-item-original-width')); oTbl.find('tbody tr:eq(0) td').each(function() { $(this).width($(this).attr("data-item-original-width")); }); } $(document).ready(function() { scrolify($('#tblNeedsScrolling'), 160); // 160 is height }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> <div style="width:300px;border:6px green solid;"> <table border="1" width="100%" id="tblNeedsScrolling"> <thead> <tr><th>Header 1</th><th>Header 2</th></tr> </thead> <tbody> <tr><td>row 1, cell 1</td><td>row 1, cell 2</td></tr> <tr><td>row 2, cell 1</td><td>row 2, cell 2</td></tr> <tr><td>row 3, cell 1</td><td>row 3, cell 2</td></tr> <tr><td>row 4, cell 1</td><td>row 4, cell 2</td></tr> <tr><td>row 5, cell 1</td><td>row 5, cell 2</td></tr> <tr><td>row 6, cell 1</td><td>row 6, cell 2</td></tr> <tr><td>row 7, cell 1</td><td>row 7, cell 2</td></tr> <tr><td>row 8, cell 1</td><td>row 8, cell 2</td></tr> </tbody> </table> </div>
该解决方案支持Chrome和IE浏览器。因为它是基于jQuery的,所以在其他jQuery支持的浏览器中也能正常工作。
我刚刚完成了一个jQuery插件,将采取有效的单一表使用有效的HTML(必须有一个标题和tbody),并将输出一个表,有固定的标题,可选的固定页脚,可以是一个克隆的标题或任何你选择的内容(分页等)。如果你想利用更大的显示器,它也会在浏览器调整大小时调整表的大小。另一个添加的特性是,如果表列不能全部放入视图,则可以侧滚动。
http://fixedheadertable.com/
在github: http://markmalek.github.com/Fixed-Header-Table/
它非常容易安装,你可以为它创建自己的自定义样式。它还在所有浏览器中使用圆角。请记住,我刚刚发布了它,所以它在技术上仍然是测试版,有一些小问题我正在解决。
它适用于Internet Explorer 7、Internet Explorer 8、Safari、Firefox和Chrome浏览器。
:)
不太干净,但纯粹的HTML/CSS解决方案。
table {
overflow-x:scroll;
}
tbody {
max-height: /*your desired max height*/
overflow-y:scroll;
display:block;
}
针对IE8+更新 JSFiddle例子
一个更精致的纯CSS滚动表
到目前为止,我所见过的所有纯CSS解决方案——尽管它们可能很聪明——都缺乏一定程度的优化,或者在某些情况下不能正常工作。所以,我决定创建我自己的…
特点:
It's pure CSS, so no jQuery required (or any JavaScript code at all, for that matter) You can set the table width to a percent (a.k.a. "fluid") or a fixed value, or let the content determine its width (a.k.a. "auto") Column widths can also be fluid, fixed, or auto. Columns will never become misaligned with headers due to horizontal scrolling (a problem that occurs in every other CSS-based solution I've seen that doesn't require fixed widths). Compatible with all of the popular desktop browsers, including Internet Explorer back to version 8 Clean, polished appearance; no sloppy-looking 1-pixel gaps or misaligned borders; looks the same in all browsers
下面是一些显示流体和自动宽度选项的控件:
流体宽度和高度(适应屏幕大小):jsFiddle(注意,在此配置中,滚动条只在需要时显示,因此您可能必须缩小帧才能看到它) 自动宽度,固定高度(更容易与其他内容集成):jsFiddle
自动宽度,固定高度配置可能有更多的用例,所以我将在下面发布代码。
/* The following 'html' and 'body' rule sets are required only if using a % width or height*/ /*html { width: 100%; height: 100%; }*/ body { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0 20px 0 20px; text-align: center; } .scrollingtable { box-sizing: border-box; display: inline-block; vertical-align: middle; overflow: hidden; width: auto; /* If you want a fixed width, set it here, else set to auto */ min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */ height: 188px/*100%*/; /* Set table height here; can be fixed value or % */ min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */ font-family: Verdana, Tahoma, sans-serif; font-size: 16px; line-height: 20px; padding: 20px 0 20px 0; /* Need enough padding to make room for caption */ text-align: left; color: black; } .scrollingtable * {box-sizing: border-box;} .scrollingtable > div { position: relative; border-top: 1px solid black; height: 100%; padding-top: 20px; /* This determines column header height */ } .scrollingtable > div:before { top: 0; background: cornflowerblue; /* Header row background color */ } .scrollingtable > div:before, .scrollingtable > div > div:after { content: ""; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; } .scrollingtable > div > div { min-height: 0/*43px*/; /* If using % height, make this large enough to fit scrollbar arrows */ max-height: 100%; overflow: scroll/*auto*/; /* Set to auto if using fixed or % width; else scroll */ overflow-x: hidden; border: 1px solid black; /* Border around table body */ } .scrollingtable > div > div:after {background: white;} /* Match page background color */ .scrollingtable > div > div > table { width: 100%; border-spacing: 0; margin-top: -20px; /* Inverse of column header height */ /*margin-right: 17px;*/ /* Uncomment if using % width */ } .scrollingtable > div > div > table > caption { position: absolute; top: -20px; /*inverse of caption height*/ margin-top: -1px; /*inverse of border-width*/ width: 100%; font-weight: bold; text-align: center; } .scrollingtable > div > div > table > * > tr > * {padding: 0;} .scrollingtable > div > div > table > thead { vertical-align: bottom; white-space: nowrap; text-align: center; } .scrollingtable > div > div > table > thead > tr > * > div { display: inline-block; padding: 0 6px 0 6px; /*header cell padding*/ } .scrollingtable > div > div > table > thead > tr > :first-child:before { content: ""; position: absolute; top: 0; left: 0; height: 20px; /*match column header height*/ border-left: 1px solid black; /*leftmost header border*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div > div:first-child, .scrollingtable > div > div > table > thead > tr > * + :before { position: absolute; top: 0; white-space: pre-wrap; color: white; /*header row font color*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);} .scrollingtable > div > div > table > thead > tr > * + :before { content: ""; display: block; min-height: 20px; /* Match column header height */ padding-top: 1px; border-left: 1px solid black; /* Borders between header cells */ } .scrollingtable .scrollbarhead {float: right;} .scrollingtable .scrollbarhead:before { position: absolute; width: 100px; top: -1px; /* Inverse border-width */ background: white; /* Match page background color */ } .scrollingtable > div > div > table > tbody > tr:after { content: ""; display: table-cell; position: relative; padding: 0; border-top: 1px solid black; top: -1px; /* Inverse of border width */ } .scrollingtable > div > div > table > tbody {vertical-align: top;} .scrollingtable > div > div > table > tbody > tr {background: white;} .scrollingtable > div > div > table > tbody > tr > * { border-bottom: 1px solid black; padding: 0 6px 0 6px; height: 20px; /* Match column header height */ } .scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;} .scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */ .scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */ <div class="scrollingtable"> <div> <div> <table> <caption>Top Caption</caption> <thead> <tr> <th><div label="Column 1"/></th> <th><div label="Column 2"/></th> <th><div label="Column 3"/></th> <th> <!-- More versatile way of doing column label; requires two identical copies of label --> <div><div>Column 4</div><div>Column 4</div></div> </th> <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW --> </tr> </thead> <tbody> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> </tbody> </table> </div> Faux bottom caption </div> </div> <!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
我用来冻结标题行的方法与d-Pixie的方法类似,因此请参阅他的帖子以获得解释。该技术存在大量错误和限制,只能通过大量额外的CSS和一两个额外的div容器来修复。