我还没有找到执行以下操作的纯 html/css 解决方案:
- 在语义上使用表格
- 修复了标题和列
- 适用于可变宽度列
- 适用于垂直和水平滚动
这是我一起破解的东西,确实有效
http://codepen.io/saiidi/pen/mePdqo
我不喜欢它的是 header th 元素中的内容是重复的。我认为通过一些额外的黑客攻击可以解决这个问题。
本着将代码放入答案的精神,代码如下:
html:
<div class="scrolly">
<div class="scrollx">
<table>
<thead>
<tr>
<th class="sticky"><div>1</div></th>
<th class="sticky"><div>2</div></th>
<th>header 1<div>header 1</div></th>
<th>header 2<div>header 2</div></th>
<th>header 3<div>header 3</div></th>
<th>header 4<div>header 4</div></th>
<th>header 5<div>header 5</div></th>
<th>header 6<div>header 6</div></th>
<th>header 7<div>header 7</div></th>
<th>header 8<div>header 8</div></th>
<th>header 9<div>header 9</div></th>
<th>header 10<div>header 10</div></th>
<th>header 11<div>header 11</div></th>
<th>header 12<div>header 12</div></th>
<th>header 13<div>header 13</div></th>
<th>header 14<div>header 14</div></th>
<th>header 15<div>header 15</div></th>
<th>header 16<div>header 16</div></th>
<th>header 17<div>header 17</div></th>
<th>header 18<div>header 18</div></th>
<th>header 19<div>header 19</div></th>
<th>header 20<div>header 20</div></th>
<th class="fill"></th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky">hello 1</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 2</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 3</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 4</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 5</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 6</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 7</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
<tr>
<td class="sticky">hello 8</td>
<td class="sticky">hello</td>
<td>world 1</td>
<td>world 2</td>
<td>world 3</td>
<td>world 4</td>
<td>world 5</td>
<td>world 6</td>
<td>world 7</td>
<td>world 8</td>
<td>world 9</td>
<td>world 10</td>
<td>world 11</td>
<td>world 12</td>
<td>world 13</td>
<td>world 14</td>
<td>world 15</td>
<td>world 16</td>
<td>world 17</td>
<td>world 18</td>
<td>world 19</td>
<td>world 20</td>
<td class="fill"></td>
</tr>
</tbody>
</table>
</div>
</div>
css:
td, th {
padding: 5px;
white-space: nowrap;
}
td {
background: linear-gradient(135deg, white 0%, #a80077 99%, black 100%);
}
th {
height: 0;
font-weight: normal;
}
.scrollx {
max-width: 100%;
overflow-x: scroll;
}
.scrolly {
position: relative;
max-height: 150px;
overflow-y: scroll;
margin-bottom: 20px;
}
table {
border-collapse: collapse;
min-width: 100%;
}
table td.fill,
table th.fill {
width: 100%;
min-width: 0;
background: white;
padding: 0;
}
tr {
position: relative;
}
.sticky {
text-decoration: underline;
font-weight: 700;
}
.stuck {
position: absolute;
}
thead th {
position: relative;
}
thead th div {
padding: 5px;
background: linear-gradient(135deg, black 0%, #a80077 99%, white 100%);
color: #ffffff;
position: absolute;
z-index: 2;
top: 0;
left: 0;
right: 0;
}
js:
$(function() {
$("#status").text('loaded');
$("table").each(function(index, table) {
var firstRow = $($(table).find('tr')[0]);
var offset = 0;
var stickies = firstRow.find('.sticky');
firstRow.children().each(function(index, td) {
var width = $(td).width();
$(table).find('tr td:nth-of-type('+(index+1)+')').css({width: width + 'px'});
$(table).find('tr th:nth-of-type('+(index+1)+')').css({width: width + 'px'});
});
stickies.each(function(index, td) {
var column = $(table).find('tr .sticky:nth-of-type('+(index+1)+')');
column.css({left: offset+'px'});
column.addClass('stuck');
offset += $(td).width() + 10;
});
$(table).parent().css({"margin-left": offset+'px'});
$(table).parent().parent().scroll(function(e) {
var top = e.currentTarget.scrollTop;
$(table).find('thead tr th div').css({top:top+'px'});
});
});
});
那么,这是在做什么呢?
它在固定(或“粘性”)列上使用绝对定位来保持卡在左侧。为了支持可变宽度,它在将位置设置为绝对之前计算宽度。然后在表格容器的左侧应用边距以补偿绝对定位的列。
为了修复标题,它绝对将嵌套的 div 定位在第 th 元素上,然后在表格滚动时调整它们的“top”css 属性。为什么重复的内容?它的存在是为了让列宽正确地考虑到标题内容的宽度。
这是一个相当粗略的实现——这里的 jquery 代码是为了证明概念。