我需要一个简单的解决方案。我知道这和其他一些问题类似,比如:

固定标题和固定列的HTML表? 我如何锁定表的第一行和第一列时滚动,可能使用JavaScript和CSS?

但我只需要一个单独的左列被冻结,我更喜欢一个简单的和无脚本的解决方案。


当前回答

下面是对最流行答案的另一种修改,但在第一列标签中处理了可变长度的文本: http://jsfiddle.net/ozx56n41/

基本上,我用第二列来创建行高,就像前面提到的。但我的小提琴实际上不像上面提到的那样。

HTML:

<div id="outerdiv">
    <div id="innerdiv">
        <table>
            <tr>
                <td class="headcol"><div>This is a long label</div></td>
                <td class="hiddenheadcol"><div>This is a long label</div></td>
                <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
                <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
            </tr>
            <tr>
                <td class="headcol"><div>Short label</div></td>
                <td class="hiddenheadcol"><div>Short label</div></td>
                <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
                <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td>
            </tr>
        </table>
    </div>
</div>

CSS:

body {
    font: 16px Calibri;
}
#outerdiv {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    border-top: 1px solid grey;
}
#innerdiv {
    overflow-x: scroll;
    margin-left: 100px;
    overflow-y: visible;
    padding-bottom: 1px;
}
table {
    border-collapse:separate;
}
td {
    margin: 0;
    border: 1px solid grey;
    border-top-width: 0;
    border-left-width: 0px;
    padding: 10px;
}
td.headcol {
    /* Frozen 1st column */
    position: absolute;
    left: 0;
    top: auto;
    border-bottom-width: 1px;
    padding: 0;
    border-left-width: 1px;
}
td.hiddenheadcol {
    /* Hidden 2nd column to create height */
    max-width: 0;
    visibility: hidden;
    padding: 0;
}
td.headcol div {
    /* Text container in the 1st column */
    width: 100px;
    max-width: 100px;
    background: lightblue;
    padding: 10px;
    box-sizing: border-box;
}
td.hiddenheadcol div {
    /* Text container in the 2nd column */
    width: 100px;
    max-width: 100px;
    background: red;
    padding: 10px;
}
td.long {
    background:yellow;
    letter-spacing:1em;
}

其他回答

在HTML5中,你可以使用CSS style.transform。 但是,我建议你“在页面之间滑动”关闭,如果你在Mac上实现。

查看样本codePen

let l = 0; let t = 0; const MouseWheelHandler = (e) => { // vertical scroll if (e.deltaX == -0) { // t = t - e.deltaY // horizonal scroll } else if (e.deltaY == -0) { l = l - e.deltaX if (l >= 0) { l = 0; document.getElementById("gantt_task").style.transform = "translateX(1px)" document.getElementById("gantt_task_header").style.transform = "translateX(1px)" return false } document.getElementById("gantt_task").style.transform = "translateX(" + l.toString() + "px)" document.getElementById("gantt_task_header").style.transform = "translateX(" + l.toString() + "px)" } return false; } window.addEventListener("wheel", MouseWheelHandler, false); .row { border-bottom: 1px solid #979A9A } #gantt_grid_header { height: 30px; width: 100px; position: fixed; z-index: 3; top: 0px; left: 0px; border: 1px solid #cecece; background-color: #F08080; } #gantt_task_header { height: 30px; width: 400px; position: fixed; z-index: 2; top: 0px; left: 100px; border: 1px solid #cecece; background-color: #FFC300; } #gantt_grid { width: 100px; height: 400px; position: absolute; left: 0px; top: 0px; z-index: 1; border: 1px solid #cecece; background-color: #DAF7A6; } #gantt_task { width: 400px; height: 400px; position: absolute; left: 100px; top: 0px; border: 1px solid #cecece; background-color: #FF5733; } <html> <div id="gantt_grid_header"> HEADER </div> <div id="gantt_grid"> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> <div class="row">V Scroll OK</div> </div> <div id="gantt_task_header"> DATA HEADER </div> <div id="gantt_task"> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> <div class="row">Vertical,Horizenal Scroll OK</div> </div> </html>

如果您想要一个只有列水平滚动的表,您可以定位:绝对第一列(并显式指定其宽度),然后将整个表包装在一个overflow-x: scroll块中。但是,不要在IE7中尝试这个…

相关的HTML和CSS:

table { border-collapse: separate; border-spacing: 0; border-top: 1px solid grey; } td, th { margin: 0; border: 1px solid grey; white-space: nowrap; border-top-width: 0px; } div { width: 500px; overflow-x: scroll; margin-left: 5em; overflow-y: visible; padding: 0; } .headcol { position: absolute; width: 5em; left: 0; top: auto; border-top-width: 1px; /*only relevant for first row*/ margin-top: -1px; /*compensate for top border*/ } .headcol:before { content: 'Row '; } .long { background: yellow; letter-spacing: 1em; } <div> <table> <tr> <th class="headcol">1</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> <tr> <th class="headcol">2</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> <tr> <th class="headcol">3</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> <tr> <th class="headcol">4</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> <tr> <th class="headcol">5</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> <tr> <th class="headcol">6</th> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> <td class="long">QWERTYUIOPASDFGHJKLZXCVBNM</td> </tr> </table> </div>

小提琴

我没有检查这个问题的每个答案,但在分析了大部分答案后,我发现在单元格或头部的多行数据情况下,设计会失败。我使用Javascript来解决这个问题。我希望有人觉得这有帮助。

https://codepen.io/kushagrarora/pen/zeYaoY

var freezeTables = document.getElementsByClassName("freeze-pane"); [].forEach.call(freezeTables, ftable => { var wrapper = document.createElement("div"); wrapper.className = "freeze-pane-wrapper"; var scroll = document.createElement("div"); scroll.className = "freeze-pane-scroll"; wrapper.appendChild(scroll); ftable.parentNode.replaceChild(wrapper, ftable); scroll.appendChild(ftable); var heads = ftable.querySelectorAll("th:first-child"); let maxWidth = 0; [].forEach.call(heads, head => { var w = window .getComputedStyle(head) .getPropertyValue("width") .split("px")[0]; if (Number(w) > Number(maxWidth)) maxWidth = w; }); ftable.parentElement.style.marginLeft = maxWidth + "px"; ftable.parentElement.style.width = "calc(100% - " + maxWidth + "px)"; [].forEach.call(heads, head => { head.style.width = maxWidth + "px"; var restRowHeight = window .getComputedStyle(head.nextElementSibling) .getPropertyValue("height"); var headHeight = window.getComputedStyle(head).getPropertyValue("height"); if (headHeight > restRowHeight) head.nextElementSibling.style.height = headHeight; else head.style.height = restRowHeight; }); }); @import url("https://fonts.googleapis.com/css?family=Open+Sans"); * { font-family: "Open Sans", sans-serif; } .container { width: 400px; height: 90vh; border: 1px solid black; overflow: hidden; } table, th, td { border: 1px solid #eee; } .table { width: 100%; margin-bottom: 1rem; table-layout: fixed; border-collapse: collapse; } .freeze-pane-wrapper { position: relative; } .freeze-pane-scroll { overflow-x: scroll; overflow-y: visible; } .freeze-pane th:first-child { position: absolute; background-color: pink; left: 0; top: auto; max-width: 40%; } <div class="container"> <table class="freeze-pane"> <tbody> <tr> <th> <p>Model</p> </th> <th> <p>Mercedes Benz AMG C43 4dr</p> </th> <th> <p>Audi S4 Premium 4dr</p> </th> <th> <p>BMW 440i 4dr sedan</p> </th> </tr> <tr> <th> <p>Passenger capacity</p> </th> <td> <p>5</p> </td> <td> <p>5</p> </td> <td> <p>5</p> </td> </tr> <tr> <th> <p>Front (Head/Shoulder/Leg) (In.)</p> </th> <td> <p>37.1/55.3/41.7</p> </td> <td> <p>38.9/55.9/41.3</p> </td> <td> <p>39.9/54.8/42.2</p> </td> </tr> <tr> <th> <p>Second (Head/Shoulder/Leg) (In.)</p> </th> <td> <p>37.1/55.5/35.2</p> </td> <td> <p>37.4/54.5/35.7</p> </td> <td> <p>36.9/54.3/33.7</p> </td> </tr> </tbody> </table> </div>

注意:“container”div只是为了演示代码与mobile-view兼容。

在左列宽度固定的情况下,Eamon Nerbonne提供了最佳解决方案。

在可变宽度左列的情况下,我发现的最佳解决方案是制作两个相同的表,并将一个放在另一个上面。演示:http://jsfiddle.net/xG5QH/6/。

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
/* important styles */

.container {
   /* Attach fixed-th-table to this container,
      in order to layout fixed-th-table
      in the same way as scolled-td-table" */
   position: relative;

   /* Truncate fixed-th-table */
   overflow: hidden;
}

.fixed-th-table-wrapper td,
.fixed-th-table-wrapper th,
.scrolled-td-table-wrapper td,
.scrolled-td-table-wrapper th {
   /* Set background to non-transparent color
      because two tables are one above another.
    */
   background: white;
}
.fixed-th-table-wrapper {
   /* Make table out of flow */
   position: absolute;
}
.fixed-th-table-wrapper th {
    /* Place fixed-th-table th-cells above 
       scrolled-td-table td-cells.
     */
    position: relative;
    z-index: 1;
}
.scrolled-td-table-wrapper td {
    /* Place scrolled-td-table td-cells
       above fixed-th-table.
     */
    position: relative;
}
.scrolled-td-table-wrapper {
   /* Make horizonal scrollbar if needed */
   overflow-x: auto;
}


/* Simulating border-collapse: collapse,
   because fixed-th-table borders
   are below ".scrolling-td-wrapper table" borders
*/

table {
    border-spacing: 0;
}
td, th {
   border-style: solid;
   border-color: black;
   border-width: 1px 1px 0 0;
}
th:first-child {
   border-left-width: 1px;
}
tr:last-child td,
tr:last-child th {
   border-bottom-width: 1px;
}

/* Unimportant styles */

.container {
    width: 250px;
}
td, th {
   padding: 5px;
}
</style>
</head>

<body>
<div class="container">

<div class="fixed-th-table-wrapper">
<!-- fixed-th-table -->
<table>
    <tr>
         <th>aaaaaaa</th>
         <td>ccccccccccc asdsad asd as</td>
         <td>ccccccccccc asdsad asd as</td>
    </tr>
    <tr>
         <th>cccccccc</th>
         <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
         <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
    </tr>
</table>
</div>

<div class="scrolled-td-table-wrapper">
<!-- scrolled-td-table
     - same as fixed-th-table -->
<table>
    <tr>
         <th>aaaaaaa</th>
         <td>ccccccccccc asdsad asd as</td>
         <td>ccccccccccc asdsad asd as</td>
    </tr>
    <tr>
         <th>cccccccc</th>
         <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
         <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
    </tr>
</table>
</div>

</div>
</body>
</html>
.div1 {
    width: 600px;
    height: 400px;
    overflow: scroll;
    border: 1px solid #777777;
}

.div1 table {
    border-spacing: 0;
}

.div1 th {
    border-left: none;
    border-right: 1px solid #bbbbbb;
    padding: 5px;
    width: 80px;
    min-width: 80px;
    position: sticky;
    top: 0;
    background: #727272;
    color: #e0e0e0;
    font-weight: normal;
}

.div1 td {
    border-left: none;
    border-right: 1px solid #bbbbbb;
    border-bottom: 1px solid #bbbbbb;
    padding: 5px;
    width: 80px;
    min-width: 80px;
}

.div1 th:nth-child(1),
.div1 td:nth-child(1) {
    position: sticky;
    left: 0;
    width: 150px;
    min-width: 150px;
}

.div1 th:nth-child(2),
.div1 td:nth-child(2) {
    position: sticky;
    /* 1st cell left/right padding + 1st cell width + 1st cell left/right border width */
    /* 0 + 5 + 150 + 5 + 1 */
    left: 161px;
    width: 50px;
    min-width: 50px;
}

.div1 td:nth-child(1),
.div1 td:nth-child(2) {
    background: #ffebb5;
}

.div1 th:nth-child(1),
.div1 th:nth-child(2) {
    z-index: 2;
}

HTML,

<div class="div1">
    <table>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
            <th>Column 3</th>
            <th>Column 4</th>
            <th>Column 5</th>
            <th>Column 6</th>
        </tr>
        <tr>
            <td>Row Data 1</td>
            <td>Row Data 2</td>
            <td>Row Data 3</td>
            <td>Row Data 4</td>
            <td>Row Data 5</td>
            <td>Row Data 6</td>
        </tr>
        <tr>
            <td>Row Data 1</td>
            <td>Row Data 2</td>
            <td>Row Data 3</td>
            <td>Row Data 4</td>
            <td>Row Data 5</td>
            <td>Row Data 6</td>
        </tr>
    </table>
</div>

Youtube视频演练:https://www.youtube.com/watch?v=_dpSEjaKqSE

例1:固定宽度和高度

https://adriancs.com/demo/freeze_table_column_row.html

示例2:响应宽度和高度(通过使用viewport进行调整)

https://adriancs.com/html-css-js/298/html-table-freeze-row-and-column-with-css/

完整的教程解释:

https://adriancs.com/demo/freeze_table_column_row_responsive_viewport.html