是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。

我希望能够滚动表的内容,但总是能够在顶部看到列标题。


当前回答

派对来的很晚了,但这仍然是一个派对,以下是我对顺风车的看法:

<div class="h-screen overflow-hidden flex flex-col">
  <div class="overflow-y-scroll flex-1">
    <table>
      <thead class="sticky top-0">
        <tr>
          <th>Timestamp</th>
          <th>Species</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>2022-02-09T08:20:39.967Z</td>
          <td>willow</td>
        </tr>
        <tr>
          <td>2022-02-09T08:21:29.453Z</td>
          <td>red osier dogwood</td>
        </tr>
        <tr>
          <td>2022-02-09T08:22:18.984Z</td>
          <td>buttonbush</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

以下是一个关于顺风游戏的完整工作示例。

其他回答

我希望我能早点找到@Mark的解决方案,但在我看到这个SO问题之前,我自己写了一个……

我的是一个非常轻量级的jQuery插件,它支持固定的页眉、页脚、列跨越(colspan)、调整大小、水平滚动,以及滚动开始前可选的显示行数。

jQuery。scrollTableBody (GitHub)

只要你有一个合适的<thead>, <tbody>,和(可选)<tfoot>的表,你所需要做的就是:

$('table').scrollTableBody();
<html>
<head>
    <script src="//cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
    <script>
        function stickyTableHead (tableID) {
            var $tmain = $(tableID);
            var $tScroll = $tmain.children("thead")
                .clone()
                .wrapAll('<table id="tScroll" />')
                .parent()
                .addClass($(tableID).attr("class"))
                .css("position", "fixed")
                .css("top", "0")
                .css("display", "none")
                .prependTo("#tMain");

            var pos = $tmain.offset().top + $tmain.find(">thead").height();


            $(document).scroll(function () {
                var dataScroll = $tScroll.data("scroll");
                dataScroll = dataScroll || false;
                if ($(this).scrollTop() >= pos) {
                    if (!dataScroll) {
                        $tScroll
                            .data("scroll", true)
                            .show()
                            .find("th").each(function () {
                                $(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
                            });
                    }
                } else {
                    if (dataScroll) {
                        $tScroll
                            .data("scroll", false)
                            .hide()
                        ;
                    }
                }
            });
        }

        $(document).ready(function () {
            stickyTableHead('#tMain');
        });
    </script>
</head>

<body>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>

    <table id="tMain" >
        <thead>
        <tr>
            <th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>

        </tr>
        </thead>
        <tbody>
            <tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
        </tbody>
    </table>
</body>
</html>

我喜欢Maximillian Hils的回答,但我有一些问题:

这个变换在Edge或IE中不起作用,除非你把它应用到第th项上 在Edge和IE中滚动时,标题会闪烁 我的表是使用ajax加载的,所以我想附加到窗口滚动事件,而不是包装器的滚动事件

为了摆脱闪烁,我使用一个超时等待,直到用户完成滚动,然后我应用转换-所以在滚动期间头是不可见的。

我还使用jQuery编写了这篇文章,其优点之一是jQuery可以为您处理供应商前缀

    var isScrolling, lastTop, lastLeft, isLeftHidden, isTopHidden;

    //Scroll events don't bubble https://stackoverflow.com/a/19375645/150342
    //so can't use $(document).on("scroll", ".table-container-fixed", function (e) {
    document.addEventListener('scroll', function (event) {
        var $container = $(event.target);
        if (!$container.hasClass("table-container-fixed"))
            return;    

        //transform needs to be applied to th for Edge and IE
        //in this example I am also fixing the leftmost column
        var $topLeftCell = $container.find('table:first > thead > tr > th:first');
        var $headerCells = $topLeftCell.siblings();
        var $columnCells = $container
           .find('table:first > tbody > tr > td:first-child, ' +
                 'table:first > tfoot > tr > td:first-child');

        //hide the cells while returning otherwise they show on top of the data
        if (!isLeftHidden) {
            var currentLeft = $container.scrollLeft();
            if (currentLeft < lastLeft) {
                //scrolling left
                isLeftHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $columnCells.css('visibility', 'hidden');
            }
            lastLeft = currentLeft;
        }

        if (!isTopHidden) {
            var currentTop = $container.scrollTop();
            if (currentTop < lastTop) {
                //scrolling up
                isTopHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $headerCells.css('visibility', 'hidden');
            }
            lastTop = currentTop;
        }

        // Using timeout to delay transform until user stops scrolling
        // Clear timeout while scrolling
        window.clearTimeout(isScrolling);

        // Set a timeout to run after scrolling ends
        isScrolling = setTimeout(function () {
            //move the table cells. 
            var x = $container.scrollLeft();
            var y = $container.scrollTop();

            $topLeftCell.css('transform', 'translate(' + x + 'px, ' + y + 'px)');
            $headerCells.css('transform', 'translateY(' + y + 'px)');
            $columnCells.css('transform', 'translateX(' + x + 'px)');

            isTopHidden = isLeftHidden = false;
            $topLeftCell.css('visibility', 'inherit');
            $headerCells.css('visibility', 'inherit');
            $columnCells.css('visibility', 'inherit');
        }, 100);

    }, true);

表被包装在一个div中,类table-container-fixed。

.table-container-fixed{
    overflow: auto;
    height: 400px;
}

我将border-collapse设置为分开,否则在翻译过程中就会丢失边界,并且我删除了表上的边界,以防止内容在滚动过程中刚好出现在边界所在的单元格上方。

.table-container-fixed > table {
   border-collapse: separate;
   border:none;
}

我将th背景设置为白色以覆盖下面的单元格,并添加了与表格边框相匹配的边框——使用Bootstrap样式并滚动出视图。

 .table-container-fixed > table > thead > tr > th {
        border-top: 1px solid #ddd !important;
        background-color: white;        
        z-index: 10;
        position: relative;/*to make z-index work*/
    }

            .table-container-fixed > table > thead > tr > th:first-child {
                z-index: 20;
            }

.table-container-fixed > table > tbody > tr > td:first-child,
.table-container-fixed > table > tfoot > tr > td:first-child {
    background-color: white;        
    z-index: 10;
    position: relative;
}

所有从CSS规范之外解决这个问题的尝试都是我们真正想要的:按照THEAD的隐含承诺交付。

这个冻结表头的问题长期以来一直是HTML/CSS中的一个开放性问题。

在理想的情况下,应该有一个纯css解决方案来解决这个问题。不幸的是,似乎没有一个合适的。

相关标准-关于此主题的讨论包括:

粘性定位提案网址:http://lists.w3.org/Archives/Public/www-style/2012Jun/0627.html 请在阿特金斯提出的“位置-根”、“位置-包含”或“位置-限制”的建议中打上标签:http://www.xanthir.com/blog/b48H0

更新:Firefox的发货位置:粘在版本32。每个人都会赢!

这是一个用于固定表头的jQuery插件。它允许整个页面滚动,当它到达顶部时冻结标题。它与Twitter Bootstrap表一起工作得很好。

GitHub存储库:https://github.com/oma/table-fixed-header

它不只是滚动表内容。看看其他的工具,就像这些答案中的一个。你来决定最适合你的情况。