Table 固定列位置,不设置 td 和 th 的高度和宽度
Table with fixed position of columns without setting height and width of td and th
我有一个 table 的前三列是固定的。我的前三列是固定的。我想要的是其余列应该根据它们的内容自动计算它们的 height
和 width
。
所以我的 CSS 看起来像这样:
.outer {
position:relative;
background-color: hotpink;
}
.inner {
overflow-x:scroll;
overflow-y: visible;
width: calc(100% - 1500px);
margin-left: 18em;
background-color: greenyellow;
}
table {
table-layout: fixed;
width: 100%;
}
td, th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
width: 150px;
height: 42px;
word-break: break-all;
}
.col1 {
position:absolute;
left: 0em;
width: 6em;
}
.col2 {
position:absolute;
left: 6em;
width: 6em;
}
.col3 {
position:absolute;
left: 12em;
width: 6em;
}
.emptyrow {
position:absolute;
left: 0em;
width: 18em;
}
这是 HTML 的 table:
<div class="outer">
<div class="inner">
<table>
<thead>
<tr>
<th class="col1">Header 1</th>
<th class="col2">Header 2</th>
<th class="col3">Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
<th>Header 7</th>
</tr>
</thead>
<tbody>
<tr>
<td class="emptyrow">This column should have value.</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="col1">col 1 - B</td>
<td class="col2">col 2 - B</td>
<td class="col3">col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
<td>col 7 - B</td>
</tr>
<tr>
<td class="col1">col 1 - C</td>
<td class="col2">col 2 - C</td>
<td class="col3">col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C</td>
<td>col 7 - C</td>
</tr>
</tbody>
</table>
</div>
</div>
是否可以避免在td
、th
中设置宽度和高度?
我的意思是避免 height
和 width
的这种硬编码值:
td, th {
...
width:6em;
height: 4em;
}
是否可以只使用普通 CSS 而不用 JavaScript?如果无法使用此解决方案实施,那么看到另一种方法真的很棒。
要求:
- 一些滚动的列可以为空
- 应该有滚动条来滚动来自 "Header 4"
的列
- Header 1-3 应始终保持在同一位置
所有列中的 Padding
应为 0.8em
Width
和 td
、th
的 Height
不应硬编码。它们应该适合内容。
border-top: 1px solid #ccc;
这个属性应该保留
- 悬停行的突出显示
希望看到的图像:
首先,你重复使用标签,避免这种情况。
第二件事是设置自动宽度和高度使用
th {
width: auto;
height: auto;
}
您应该改用粘性单元格,这会将列保留为文档流的一部分。此外,如果您希望列对内容宽度做出反应,则需要删除 table-layout: fixed
.
如果需要,您也可以删除 max-width
,这是向列添加一些合理的最大宽度的示例,之后它们将获得省略号(请参阅最后一列)。
.scroller {
max-width: 600px;
overflow: auto;
}
table, table * {
box-sizing: border-box;
}
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
th {
text-align: left;
}
/* borders should be on th/td so the table can collapse them */
th, td {
border-top: 1px solid #ccc;
padding: 0; /* Default padding should be removed */
}
/* padding, overflow ellipses etc behaves better if
content is wrapped in an inner element */
.inner-cell {
background: white;
padding: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 260px;
}
.sticky {
position: sticky;
left: 0;
}
.sticky-2 {
left: 6em;
}
.sticky-3 {
left: 12em;
}
/* Behaves better if width is set on inner el (or it moves 1px when scrolling) */
.sticky .inner-cell {
width: 6em;
}
<div class="scroller">
<table>
<thead>
<tr>
<th class="sticky sticky-1"><div class="inner-cell">Stick 1</div></th>
<th class="sticky sticky-2"><div class="inner-cell">Stick 2</div></th>
<th class="sticky sticky-3"><div class="inner-cell">Stick 3</div></th>
<th><div class="inner-cell">Normal 1</div></th>
<th><div class="inner-cell">Normal 2</div></th>
<th><div class="inner-cell">Normal 3</div></th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky sticky-1"><div class="inner-cell">Sticky Val 1</div></td>
<td class="sticky sticky-2"><div class="inner-cell">Sticky Val 2</div></td>
<td class="sticky sticky-3"><div class="inner-cell">Sticky Val 3</div></td>
<td><div class="inner-cell">Sticky Normal 1</div></td>
<td><div class="inner-cell">Sticky Normal 2 looooong</div></td>
<td><div class="inner-cell">Sticky Normal 3 something really long we don't want to display all of this</div></td>
</tr>
</tbody>
</table>
</div>
恐怕没有完美的解决方案。
我会给你不同的选择,你需要决定放弃什么。
绝对定位列。
✅ 纯 CSS - ✅ 老浏览器 - ❌ 灵活的宽度 - ❌ 适当的高亮
关键是前三列设置一个固定的width
然后设置一个.wrapped
元素的margin-left
属性等于总宽度列。
.wrapper {
overflow-x: scroll;
overflow-y: visible;
margin-left: 18em;
width: 15em;
background-color: greenyellow;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th, tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1),
td:nth-of-type(1) {
position: absolute;
left: 0em;
width: 6em;
}
th:nth-of-type(2),
td:nth-of-type(2) {
position: absolute;
left: 6em;
width: 6em;
}
th:nth-of-type(3),
td:nth-of-type(3) {
position: absolute;
left: 12em;
width: 6em;
}
tr:hover td {
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-5</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
绝对定位列 + JavaScript.
❌ 纯 CSS - ✅ 旧浏览器 - ✅ 灵活的宽度 - ❌适当的高亮
这里,我们没有事先硬编码列的width
,而是使用JS计算并设置width
。
更好的 JS 实现是可能的。举个例子吧。
let wrapper = document.querySelector('.wrapper');
let cols = document.querySelectorAll('th');
let widthCol0 = cols[0].offsetWidth;
let widthCol1 = cols[1].offsetWidth;
let widthCol2 = cols[2].offsetWidth;
stylesheet = document.styleSheets[0]
stylesheet.insertRule('th:nth-of-type(1), td:nth-of-type(1) { left: 0px; position: absolute; width: ' + widthCol0 + 'px;}', 0);
stylesheet.insertRule('th:nth-of-type(2), td:nth-of-type(2) { left: ' + widthCol0 + 'px; position: absolute; width: ' + widthCol1 + 'px;}', 0);
stylesheet.insertRule('th:nth-of-type(3), td:nth-of-type(3) { left: ' + (widthCol0 + widthCol1) + 'px; position: absolute; width: ' + widthCol2 + 'px;}', 0);
wrapper.style.marginLeft = (widthCol0 + widthCol1 + widthCol2) + 'px';
.wrapper {
overflow-x: scroll;
overflow-y: visible;
width: 15em;
background-color: greenyellow;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th, tr:nth-of-type(1) td {
height: 1em;
}
tr:hover td {
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-5</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
粘性定位列。
✅ 纯粹 CSS - ❌ 旧浏览器 - ❌ 灵活宽度 - ✅ 适当的高亮
我非常喜欢@Dominic 展示的 position: sticky
解决方案。如果你 don't need to support IE.
放弃 IE 支持是有回报的。你可以有适当的突出显示,前三列的宽度将适应内容。
尽管如此,即使您不需要对 width
进行硬编码,您也需要对 left
属性 进行硬编码以设置列变为黏。这种做法违背了灵活 width
的意义。没有办法。
.wrapper {
width: 40em;
overflow-x: scroll;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th,
tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1), td:nth-of-type(1),
th:nth-of-type(2), td:nth-of-type(2),
th:nth-of-type(3), td:nth-of-type(3) {
background-color: white;
position: sticky;
}
th:nth-of-type(1), td:nth-of-type(1) {
left: 0em;
}
th:nth-of-type(2), td:nth-of-type(2) {
left: 6em;
}
th:nth-of-type(3), td:nth-of-type(3) {
left: 12em;
}
tr:hover td{
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-6</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
</div>
粘性定位列 + JavaScript.
❌ 纯 CSS - ❌ 老浏览器 - ✅ 灵活的宽度 - ✅ 适当的高亮
此示例与上面的示例具有完全相同的 HTML 和 CSS。
和我们第二个例子一样,我们使用JS来计算列的width
。在这种情况下,我们使用它来覆盖 left
属性。另外,JS代码更直接。
为什么要在CSS中设置left
属性,以后用JS设置?因为如果客户端没有 运行 JS,我们不希望列完全折叠,破坏我们的布局。
let cols = document.querySelectorAll('th');
let widthCol0 = cols[0].offsetWidth;
let widthCol1 = cols[1].offsetWidth;
stylesheet = document.styleSheets[0];
stylesheet.insertRule('th:nth-of-type(2), td:nth-of-type(2) { left: ' + widthCol0 + 'px !important;}', 0);
stylesheet.insertRule('th:nth-of-type(3), td:nth-of-type(3) { left: ' + (widthCol0 + widthCol1) + 'px !important;', 0);
.wrapper {
width: 40em;
overflow-x: scroll;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th,
tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1), td:nth-of-type(1),
th:nth-of-type(2), td:nth-of-type(2),
th:nth-of-type(3), td:nth-of-type(3) {
background-color: white;
position: sticky;
}
th:nth-of-type(1), td:nth-of-type(1) {
left: 0em;
}
th:nth-of-type(2), td:nth-of-type(2) {
left: 6em;
}
th:nth-of-type(3), td:nth-of-type(3) {
left: 12em;
}
tr:hover td{
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-6</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
</div>
最后的笔记
由您决定哪种方法最适合您的需要。
就个人而言,我认为第 4 个最强大,因为:
如果禁用 JS,列将折叠到最佳点之外,但一切都会正常工作。只需在 CSS 中使用默认 left
属性 即可。
在 IE11 下,table 会很好地退回到非固定列 table。
我认为这没什么大不了的。当然,如果您正在为选择 IE11 浏览器的 Intranet 编程,请采用第一种或第二种方法。
我有一个 table 的前三列是固定的。我的前三列是固定的。我想要的是其余列应该根据它们的内容自动计算它们的 height
和 width
。
所以我的 CSS 看起来像这样:
.outer {
position:relative;
background-color: hotpink;
}
.inner {
overflow-x:scroll;
overflow-y: visible;
width: calc(100% - 1500px);
margin-left: 18em;
background-color: greenyellow;
}
table {
table-layout: fixed;
width: 100%;
}
td, th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
width: 150px;
height: 42px;
word-break: break-all;
}
.col1 {
position:absolute;
left: 0em;
width: 6em;
}
.col2 {
position:absolute;
left: 6em;
width: 6em;
}
.col3 {
position:absolute;
left: 12em;
width: 6em;
}
.emptyrow {
position:absolute;
left: 0em;
width: 18em;
}
这是 HTML 的 table:
<div class="outer">
<div class="inner">
<table>
<thead>
<tr>
<th class="col1">Header 1</th>
<th class="col2">Header 2</th>
<th class="col3">Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
<th>Header 7</th>
</tr>
</thead>
<tbody>
<tr>
<td class="emptyrow">This column should have value.</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="col1">col 1 - B</td>
<td class="col2">col 2 - B</td>
<td class="col3">col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
<td>col 7 - B</td>
</tr>
<tr>
<td class="col1">col 1 - C</td>
<td class="col2">col 2 - C</td>
<td class="col3">col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C</td>
<td>col 7 - C</td>
</tr>
</tbody>
</table>
</div>
</div>
是否可以避免在td
、th
中设置宽度和高度?
我的意思是避免 height
和 width
的这种硬编码值:
td, th {
...
width:6em;
height: 4em;
}
是否可以只使用普通 CSS 而不用 JavaScript?如果无法使用此解决方案实施,那么看到另一种方法真的很棒。
要求:
- 一些滚动的列可以为空
- 应该有滚动条来滚动来自 "Header 4" 的列
- Header 1-3 应始终保持在同一位置 所有列中的
Padding
应为0.8em
Width
和td
、th
的Height
不应硬编码。它们应该适合内容。border-top: 1px solid #ccc;
这个属性应该保留- 悬停行的突出显示
希望看到的图像:
首先,你重复使用标签,避免这种情况。 第二件事是设置自动宽度和高度使用
th {
width: auto;
height: auto;
}
您应该改用粘性单元格,这会将列保留为文档流的一部分。此外,如果您希望列对内容宽度做出反应,则需要删除 table-layout: fixed
.
如果需要,您也可以删除 max-width
,这是向列添加一些合理的最大宽度的示例,之后它们将获得省略号(请参阅最后一列)。
.scroller {
max-width: 600px;
overflow: auto;
}
table, table * {
box-sizing: border-box;
}
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
th {
text-align: left;
}
/* borders should be on th/td so the table can collapse them */
th, td {
border-top: 1px solid #ccc;
padding: 0; /* Default padding should be removed */
}
/* padding, overflow ellipses etc behaves better if
content is wrapped in an inner element */
.inner-cell {
background: white;
padding: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 260px;
}
.sticky {
position: sticky;
left: 0;
}
.sticky-2 {
left: 6em;
}
.sticky-3 {
left: 12em;
}
/* Behaves better if width is set on inner el (or it moves 1px when scrolling) */
.sticky .inner-cell {
width: 6em;
}
<div class="scroller">
<table>
<thead>
<tr>
<th class="sticky sticky-1"><div class="inner-cell">Stick 1</div></th>
<th class="sticky sticky-2"><div class="inner-cell">Stick 2</div></th>
<th class="sticky sticky-3"><div class="inner-cell">Stick 3</div></th>
<th><div class="inner-cell">Normal 1</div></th>
<th><div class="inner-cell">Normal 2</div></th>
<th><div class="inner-cell">Normal 3</div></th>
</tr>
</thead>
<tbody>
<tr>
<td class="sticky sticky-1"><div class="inner-cell">Sticky Val 1</div></td>
<td class="sticky sticky-2"><div class="inner-cell">Sticky Val 2</div></td>
<td class="sticky sticky-3"><div class="inner-cell">Sticky Val 3</div></td>
<td><div class="inner-cell">Sticky Normal 1</div></td>
<td><div class="inner-cell">Sticky Normal 2 looooong</div></td>
<td><div class="inner-cell">Sticky Normal 3 something really long we don't want to display all of this</div></td>
</tr>
</tbody>
</table>
</div>
恐怕没有完美的解决方案。
我会给你不同的选择,你需要决定放弃什么。
绝对定位列。
✅ 纯 CSS - ✅ 老浏览器 - ❌ 灵活的宽度 - ❌ 适当的高亮
关键是前三列设置一个固定的width
然后设置一个.wrapped
元素的margin-left
属性等于总宽度列。
.wrapper {
overflow-x: scroll;
overflow-y: visible;
margin-left: 18em;
width: 15em;
background-color: greenyellow;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th, tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1),
td:nth-of-type(1) {
position: absolute;
left: 0em;
width: 6em;
}
th:nth-of-type(2),
td:nth-of-type(2) {
position: absolute;
left: 6em;
width: 6em;
}
th:nth-of-type(3),
td:nth-of-type(3) {
position: absolute;
left: 12em;
width: 6em;
}
tr:hover td {
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-5</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
绝对定位列 + JavaScript.
❌ 纯 CSS - ✅ 旧浏览器 - ✅ 灵活的宽度 - ❌适当的高亮
这里,我们没有事先硬编码列的width
,而是使用JS计算并设置width
。
更好的 JS 实现是可能的。举个例子吧。
let wrapper = document.querySelector('.wrapper');
let cols = document.querySelectorAll('th');
let widthCol0 = cols[0].offsetWidth;
let widthCol1 = cols[1].offsetWidth;
let widthCol2 = cols[2].offsetWidth;
stylesheet = document.styleSheets[0]
stylesheet.insertRule('th:nth-of-type(1), td:nth-of-type(1) { left: 0px; position: absolute; width: ' + widthCol0 + 'px;}', 0);
stylesheet.insertRule('th:nth-of-type(2), td:nth-of-type(2) { left: ' + widthCol0 + 'px; position: absolute; width: ' + widthCol1 + 'px;}', 0);
stylesheet.insertRule('th:nth-of-type(3), td:nth-of-type(3) { left: ' + (widthCol0 + widthCol1) + 'px; position: absolute; width: ' + widthCol2 + 'px;}', 0);
wrapper.style.marginLeft = (widthCol0 + widthCol1 + widthCol2) + 'px';
.wrapper {
overflow-x: scroll;
overflow-y: visible;
width: 15em;
background-color: greenyellow;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th, tr:nth-of-type(1) td {
height: 1em;
}
tr:hover td {
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-5</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
粘性定位列。
✅ 纯粹 CSS - ❌ 旧浏览器 - ❌ 灵活宽度 - ✅ 适当的高亮
我非常喜欢@Dominic 展示的 position: sticky
解决方案。如果你 don't need to support IE.
放弃 IE 支持是有回报的。你可以有适当的突出显示,前三列的宽度将适应内容。
尽管如此,即使您不需要对 width
进行硬编码,您也需要对 left
属性 进行硬编码以设置列变为黏。这种做法违背了灵活 width
的意义。没有办法。
.wrapper {
width: 40em;
overflow-x: scroll;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th,
tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1), td:nth-of-type(1),
th:nth-of-type(2), td:nth-of-type(2),
th:nth-of-type(3), td:nth-of-type(3) {
background-color: white;
position: sticky;
}
th:nth-of-type(1), td:nth-of-type(1) {
left: 0em;
}
th:nth-of-type(2), td:nth-of-type(2) {
left: 6em;
}
th:nth-of-type(3), td:nth-of-type(3) {
left: 12em;
}
tr:hover td{
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-6</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
</div>
粘性定位列 + JavaScript.
❌ 纯 CSS - ❌ 老浏览器 - ✅ 灵活的宽度 - ✅ 适当的高亮
此示例与上面的示例具有完全相同的 HTML 和 CSS。
和我们第二个例子一样,我们使用JS来计算列的width
。在这种情况下,我们使用它来覆盖 left
属性。另外,JS代码更直接。
为什么要在CSS中设置left
属性,以后用JS设置?因为如果客户端没有 运行 JS,我们不希望列完全折叠,破坏我们的布局。
let cols = document.querySelectorAll('th');
let widthCol0 = cols[0].offsetWidth;
let widthCol1 = cols[1].offsetWidth;
stylesheet = document.styleSheets[0];
stylesheet.insertRule('th:nth-of-type(2), td:nth-of-type(2) { left: ' + widthCol0 + 'px !important;}', 0);
stylesheet.insertRule('th:nth-of-type(3), td:nth-of-type(3) { left: ' + (widthCol0 + widthCol1) + 'px !important;', 0);
.wrapper {
width: 40em;
overflow-x: scroll;
}
td,
th {
vertical-align: top;
border-top: 1px solid #ccc;
padding: 0.8em;
}
th,
tr:nth-of-type(1) td {
height: 1em;
}
th:nth-of-type(1), td:nth-of-type(1),
th:nth-of-type(2), td:nth-of-type(2),
th:nth-of-type(3), td:nth-of-type(3) {
background-color: white;
position: sticky;
}
th:nth-of-type(1), td:nth-of-type(1) {
left: 0em;
}
th:nth-of-type(2), td:nth-of-type(2) {
left: 6em;
}
th:nth-of-type(3), td:nth-of-type(3) {
left: 12em;
}
tr:hover td{
background-color: yellow;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Header-1</th>
<th>Header-2</th>
<th>Header-3</th>
<th>Header-4</th>
<th>Header-5</th>
<th>Header-6</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>col 1 - A (WITH LONGER CONTENT)</td>
<td>col 2 - A</td>
<td>col 3 - A</td>
<td>col 4 - A (WITH LONGER CONTENT)</td>
<td>col 5 - A</td>
<td>col 6 - A</td>
</tr>
<tr>
<td>col 1 - B</td>
<td>col 2 - B</td>
<td>col 3 - B</td>
<td>col 4 - B</td>
<td>col 5 - B</td>
<td>col 6 - B</td>
</tr>
<tr>
<td>col 1 - C</td>
<td>col 2 - C (WITH_A_LONG_WORD)</td>
<td>col 3 - C</td>
<td>col 4 - C</td>
<td>col 5 - C</td>
<td>col 6 - C (WITH_A_LONG_WORD)</td>
</tr>
</tbody>
</table>
</div>
最后的笔记
由您决定哪种方法最适合您的需要。
就个人而言,我认为第 4 个最强大,因为:
如果禁用 JS,列将折叠到最佳点之外,但一切都会正常工作。只需在 CSS 中使用默认
left
属性 即可。在 IE11 下,table 会很好地退回到非固定列 table。
我认为这没什么大不了的。当然,如果您正在为选择 IE11 浏览器的 Intranet 编程,请采用第一种或第二种方法。