当前位置: 首页 > 知识库问答 >
问题:

前端 - 如何实现表格 行 和 列 各种情况的 sticky ?

小牛23225
2024-09-11

表格图示如下:

在尽量使用 CSS 的情况,如何实现以下需求:

1. 垂直滚动时,当前 Team 的表头部分(绿色整行),在 该Team 没有滚出视口前,保持在 Summary 的下方
2. 垂直滚动时,当前 Team 第一列的 Team Name,能否保持在 该Team 表头同一行位置,不被滚出视口
3. 横向滚动时,如何保持 Head X 表头(4列)冻结,不被滚出视口,表头列需要 宽度自适应,不能写死 `width`
4. 以上需求尽量使用 `CSS`,非必要不使用 `JS`

表格页面基础代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
    .frame {position:relative;width:800px;height:500px;box-shadow:0 0 0 1px #000;overflow:auto;}

    .frame table {border-spacing:0;line-height:2em;}
    .frame table tr th {padding:0 0.5em;font-weight:normal;white-space:nowrap;border:1px solid #CCC;}
    .frame table tr td {padding:0 0.5em;border:1px solid #CCC;background-color:#FFF;}

    .frame table tr.gap td {height:1px;background-color:#000;}

    .frame table thead tr th {color:#369;background-color:#F0F9FF;}

    .frame table tbody tr th {color:#393;background-color:#F0FFF0;}
    .frame table tbody tr td {min-width:200px;color:#999;}

    .frame table tfoot tr th {color:#993;background-color:#FFFFF0;}
    .frame table tfoot tr td {color:#993;background-color:#FFFFF0;}

    .frame table thead.sticky {position:sticky;top:0;}
    .frame table tfoot.sticky {position:sticky;bottom:0;}
    </style>
</head>
<body>
    <div class="frame">
        <table>
            <thead class="sticky">
                <tr>
                    <th rowspan="4">Summary</th>
                    <th>Head A</th>
                    <th>Head B</th>
                    <th>Head C</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th>Head B</th>
                    <th>Head C</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr class="gap">
                    <td colspan="7"></td>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <th rowspan="4">Team 1</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tbody>
                <tr>
                    <th rowspan="4">Team 2</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tbody>
                <tr>
                    <th rowspan="4">Team 3</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tbody>
                <tr>
                    <th rowspan="4">Team 4</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tbody>
                <tr>
                    <th rowspan="4">Team 5</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tbody>
                <tr>
                    <th rowspan="4">Team 6</th>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <th>Head D</th>
                    <th>Head E</th>
                    <th>Head F</th>
                    <th>Head G</th>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
                <tr>
                    <th>Head A</th>
                    <th colspan="2">Head B</th>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                    <td>data</td>
                </tr>
            </tbody>
            <tfoot class="sticky">
                <tr class="gap">
                    <td colspan="7"></td>
                </tr>
                <tr>
                    <th colspan="4">Foot</th>
                    <td>f</td>
                    <td>f</td>
                    <td>f</td>
                    <td>f</td>
                </tr>
            </tfoot>
        </table>
    </div>
</body>
</html>

共有1个答案

索嘉胜
2024-09-11

为了实现你的需求,我们可以使用 CSS 的 position: sticky; 属性。然而,这个属性并不直接支持跨行或跨列的“粘性”定位,特别是当涉及到复杂的表头和行合并时。但是,我们可以通过一些结构和样式调整来尽量接近你的需求。

1. 垂直滚动时,Team 的表头部分保持在 Summary 的下方

对于 Team 的表头(如“Team 1”),我们可以将这些行包装在一个具有 position: sticky;<thead><div> 内,并为其指定一个适当的 top 值(以 px 为单位),使其在滚动时保持在指定位置。但由于表头通常属于 <thead>,我们需要改变 HTML 结构或添加额外的样式类来应用粘性效果。由于结构限制,我们可能需要用额外的 <div> 或通过 JavaScript 动态生成结构。

:在标准的 HTML 表格中,这通常较难实现,因为 <thead> 只应该包含一行的表头。我们可以通过为 <tbody> 的特定行添加类来实现部分效果,但可能不会完全符合需求。

2. 垂直滚动时,Team Name 保持在同一行位置

这个需求更加复杂,因为 CSS position: sticky; 不支持直接粘在某个行旁边。这可能需要使用 JavaScript 来计算并更新位置,或者设计一个完全不同的布局,如使用两个表格或列表项 (<li>) 和分隔线来模拟。

3. 横向滚动时,保持 Head X 表头冻结

这可以通过在 <thead>th 元素上使用 position: sticky; left: 0; 来实现。注意,这需要表格外层容器(如 .frame)具有滚动属性(overflow-x: auto;)。在你的代码中,由于表头已经是 <thead> 的一部分,并应用了 position: sticky; top: 0;,我们需要调整它以包括横向滚动的情况。

.frame th {
    position: -webkit-sticky; /* Safari */
    position: sticky;
    top: 0; /* 对于垂直滚动 */
    left: 0; /* 对于横向滚动 */
    background-color: #f9f9f9; /* 添加背景色以便更容易看到效果 */
    z-index: 1; /* 提高 z-index 以确保它在内容之上 */
}

/* 仅对顶层表头(Summary 下的)进行调整 */
.frame thead th:first-child {
    z-index: 2; /* 更高的 z-index 确保其不会被下面的表头覆盖 */
}

注意:你可能需要调整 z-index 来处理表头之间的覆盖问题。

4. 尽量使用 CSS,非必要不使用 JS

对于大多数情况,你可以使用上述 CSS 方法来尽可能接近你的需求。然而,对于复杂的行为(如将 Team Name 保持在行旁边),可能需要使用 JavaScript 来精确控制位置和响应滚动事件。

由于直接在你的 HTML 结构中完全实现所有需求可能会受到限制,建议重新考虑你的布局或接受一些折衷方案。如果可能的话,考虑使用 CSS Grid 或 Flexbox 来创建更灵活的布局,这些布局可以更容易地实现复杂的粘性行为。

 类似资料:
  • 本文向大家介绍fragment各种情况下的生命周期?相关面试题,主要包含被问及fragment各种情况下的生命周期?时的应答技巧和注意事项,需要的朋友参考一下 由于Fragment的生命周期与Activity的生命周期有着牵扯,所以把两者的图放到一起作为对比理解。   接下来就不同情况下的Fragment生命周期做一简单介绍: Fragment在Activity中replace 新替换的Activ

  • 不确定这是更新还是什么,但目前我有两个F4实例在标准环境(java app)上运行。现在,我在过去12小时内没有做过一个请求,但我的前端实例使用率今天是64.02小时!!我认为只有当请求完成时,使用量才会增加。有什么变化吗?我仍然是一年免费的(我还有大约90天) 我的配置文件的内容:

  • 如图:表格内显示出图片链接,鼠标悬停链接弹出图片,现在希望点击图片能够实现一些预览操作:放大、缩小。 UI 点击图片后,报错:

  • 我在使用fs.readfile进行同步时遇到了一个问题,他们没有在第一次初始化,如果我再次尝试请求,那么我就有结果了。我知道我可以用promise和我从Kriskowal找到一些有用的东西。我试过但没有成功。我不太明白如何实施它。如果有人能帮忙,我将永远感激。 代码:

  • 这种级联是怎么做的 仅有一级的情况下也可以选中

  • 本文向大家介绍JS实现表格数据各种搜索功能的方法,包括了JS实现表格数据各种搜索功能的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS实现表格数据各种搜索功能。可忽略大小写,模糊搜索,多关键搜索。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的javascript程序设计有所帮助。