Raf*_*res 6 html javascript css html-table
我制作了一个带有标题和最后一列的表格,使用position: sticky. 我想当滚动条水平位于末尾时删除最后一列的阴影,并当滚动条垂直位于开头时删除标题中的阴影。在 AntDesign 中有一个所需结果的示例,但在这种情况下,表格仅在固定列中有阴影,而在标题中没有。
虽然由于性能原因我不想要使用滚动事件侦听器的解决方案(请参阅滚动链接效果),但如果有人以这种方式解决它,他们可以分享它以供参考并帮助其他人。
该代码也可从CodeSandbox获取。
main {
display: flex;
max-height: 20rem;
overflow: auto;
}
table {
border-spacing: 0;
}
th {
text-align: left;
}
th,
td {
border-bottom: 1px solid #c6c6c6;
height: 5rem;
white-space: nowrap;
padding-right: 2rem;
}
.fixed {
background-color: white;
position: sticky;
}
.fixed-top {
box-shadow: 4px 3px 5px 0px rgba(0, 0, 0, 0.2);
top: 0;
z-index: 1;
}
.fixed-right {
border-left: 1px solid #c6c6c6;
box-shadow: -5px 0px 5px 0px rgba(0, 0, 0, 0.2);
padding-left: 1rem;
right: 0;
z-index: 1;
}
.fixed-top.fixed-right {
box-shadow: 4px 3px 5px 0px rgba(0, 0, 0, 0.2), -5px 0px 5px 0px rgba(0, 0, 0, 0.2);
z-index: 2;
}Run Code Online (Sandbox Code Playgroud)
<table>
<thead>
<tr>
<th class="fixed fixed-top">Animal</th>
<th class="fixed fixed-top">Age</th>
<th class="fixed fixed-top">Country</th>
<th class="fixed fixed-top">Sentence</th>
<th class="fixed fixed-top">Color</th>
<th class="fixed fixed-top fixed-right">Programming Language</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sable</td>
<td>15 yo</td>
<td>Japan</td>
<td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
<td>Purple</td>
<td class="fixed fixed-right">Kotlin</td>
</tr>
<tr>
<td>Toco toucan</td>
<td>35 yo</td>
<td>Brazil</td>
<td>
Sed tortor erat, imperdiet a enim quis, placerat rhoncus nisl.
</td>
<td>Orange</td>
<td class="fixed fixed-right">Swift</td>
</tr>
<tr>
<td>Bull</td>
<td>42 yo</td>
<td>Spain</td>
<td>Donec vitae risus urna.</td>
<td>Red</td>
<td class="fixed fixed-right">JavaScript</td>
</tr>
<tr>
<td>Brown bear</td>
<td>17 yo</td>
<td>Russia</td>
<td>Proin gravida et velit ut congue.</td>
<td>Green</td>
<td class="fixed fixed-right">Python</td>
</tr>
</tbody>
</table>Run Code Online (Sandbox Code Playgroud)
首先,您需要有一个 CSS 类来移除td和th元素的阴影。
.noShadow {
box-shadow: none !important;
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以通过 javscript 通过两种方式执行此操作:
您需要td通过 的两个实例观察两个元素InterSectionObserver:每个实例观察一个td元素。当观察到的td元素进入视图时,我们想要将noShadowCSS 类添加到表格行或列。类似地,当观察到的元素移出视图noShadow时,类将被删除。td
observed-column我在其中一个元素上添加了类td,将在最后一列中添加或删除阴影,并observed-row在其中一个td元素上添加类以添加或删除标题中的阴影。
这是您需要的 JavaScript 代码
const lastColumn = document.querySelectorAll(".fixed-right");
const header = document.querySelectorAll(".fixed-top");
const tableContainer = document.querySelector("main");
let rowHasShadow = false;
let columnHasShadow = true;
const options = {
root: tableContainer,
rootMargin: "0px",
threshold: 1
};
const rowObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-row' element is in view, remove shadow from header
rowHasShadow = false;
header.forEach(th => {
if (th.classList.contains('fixed-header') && !columnHasShadow) {
th.classList.add("noShadow")
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow")
}
});
}
else {
// '.observed-row' element is not in view, add shadow to header
rowHasShadow = true;
header.forEach(th => th.classList.remove("noShadow"));
}
}, options);
rowObserver.observe(document.querySelector(".observed-row"));
const columnObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-column' element is in view, remove shadow from last column
columnHasShadow = false;
lastColumn.forEach(th => {
if (th.classList.contains('fixed-header') && !rowHasShadow) {
th.classList.add("noShadow");
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow");
}
});
}
else {
// '.observed-column' element is not in view, add shadow to last column
columnHasShadow = true;
lastColumn.forEach(th => th.classList.remove("noShadow"));
}
}, options);
columnObserver.observe(document.querySelector(".observed-column"));
Run Code Online (Sandbox Code Playgroud)
.noShadow {
box-shadow: none !important;
}
Run Code Online (Sandbox Code Playgroud)
const lastColumn = document.querySelectorAll(".fixed-right");
const header = document.querySelectorAll(".fixed-top");
const tableContainer = document.querySelector("main");
let rowHasShadow = false;
let columnHasShadow = true;
const options = {
root: tableContainer,
rootMargin: "0px",
threshold: 1
};
const rowObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-row' element is in view, remove shadow from header
rowHasShadow = false;
header.forEach(th => {
if (th.classList.contains('fixed-header') && !columnHasShadow) {
th.classList.add("noShadow")
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow")
}
});
}
else {
// '.observed-row' element is not in view, add shadow to header
rowHasShadow = true;
header.forEach(th => th.classList.remove("noShadow"));
}
}, options);
rowObserver.observe(document.querySelector(".observed-row"));
const columnObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-column' element is in view, remove shadow from last column
columnHasShadow = false;
lastColumn.forEach(th => {
if (th.classList.contains('fixed-header') && !rowHasShadow) {
th.classList.add("noShadow");
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow");
}
});
}
else {
// '.observed-column' element is not in view, add shadow to last column
columnHasShadow = true;
lastColumn.forEach(th => th.classList.remove("noShadow"));
}
}, options);
columnObserver.observe(document.querySelector(".observed-column"));
Run Code Online (Sandbox Code Playgroud)
const lastColumn = document.querySelectorAll(".fixed-right");
const header = document.querySelectorAll(".fixed-top");
const tableContainer = document.querySelector("main");
let rowHasShadow = false;
let columnHasShadow = true;
const options = {
root: tableContainer,
rootMargin: "0px",
threshold: 1
};
const rowObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-row' element is in view, remove shadow from header
rowHasShadow = false;
header.forEach(th => {
if (th.classList.contains('fixed-header') && !columnHasShadow) {
th.classList.add("noShadow")
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow")
}
});
}
else {
// '.observed-row' element is not in view, add shadow to header
rowHasShadow = true;
header.forEach(th => th.classList.remove("noShadow"));
}
}, options);
rowObserver.observe(document.querySelector(".observed-row"));
const columnObserver = new IntersectionObserver((entries, observer) => {
if (entries[0].isIntersecting) {
// '.observed-column' element is in view, remove shadow from last column
columnHasShadow = false;
lastColumn.forEach(th => {
if (th.classList.contains('fixed-header') && !rowHasShadow) {
th.classList.add("noShadow");
} else if (!th.classList.contains('fixed-header')) {
th.classList.add("noShadow");
}
});
}
else {
// '.observed-column' element is not in view, add shadow to last column
columnHasShadow = true;
lastColumn.forEach(th => th.classList.remove("noShadow"));
}
}, options);
columnObserver.observe(document.querySelector(".observed-column"));Run Code Online (Sandbox Code Playgroud)
您还可以在codesandbox上查看此演示
在元素上添加滚动事件侦听器main。在事件处理程序中,您需要检查两件事:
如果scrollLeft等于scrollWidth - clientWidth,则为最后一列中的.noShadow所有元素添加类td
如果scrollTop等于零,.noShadow则为所有th元素添加类
以下是您需要的 javascript 代码以及noShadowcss 类
const lastColumn = document.querySelectorAll('.fixed-right');
const header = document.querySelectorAll('.fixed-top');
const tableContainer = document.querySelector('main');
tableContainer.addEventListener('scroll', (e) => {
removeShadowFromColumn();
removeShadowFromHeader();
});
function removeShadowFromHeader() {
if (tableContainer.scrollTop === 0) {
header.forEach(th => th.classList.add('noShadow'));
} else {
header.forEach(th => th.classList.remove('noShadow'));
}
}
function removeShadowFromColumn() {
const widthDiff = tableContainer.scrollWidth - tableContainer.clientWidth;
if (tableContainer.scrollLeft === widthDiff) {
lastColumn.forEach(th => th.classList.add('noShadow'));
} else {
lastColumn.forEach(td => td.classList.remove('noShadow'));
}
}
removeShadowFromHeader();
Run Code Online (Sandbox Code Playgroud)
main {
display: flex;
max-height: 20rem;
overflow: auto;
}
table {
border-spacing: 0;
}
th {
text-align: left;
}
th,
td {
border-bottom: 1px solid #c6c6c6;
height: 5rem;
white-space: nowrap;
padding-right: 2rem;
}
.fixed {
background-color: white;
position: sticky;
}
.fixed-top {
box-shadow: 4px 3px 5px 0px rgba(0, 0, 0, 0.2);
top: 0;
z-index: 2;
}
.fixed-right {
border-left: 1px solid #c6c6c6;
box-shadow: -5px 0px 5px 0px rgba(0, 0, 0, 0.2);
padding-left: 1rem;
right: 0;
z-index: 1;
}
.fixed-top.fixed-right {
box-shadow: 4px 3px 5px 0px rgba(0, 0, 0, 0.2),
-5px 0px 5px 0px rgba(0, 0, 0, 0.2);
z-index: 2;
}
.noShadow {
box-shadow: none !important;
}Run Code Online (Sandbox Code Playgroud)
<main>
<table>
<thead>
<tr>
<th class="fixed fixed-top">Animal</th>
<th class="fixed fixed-top">Age</th>
<th class="fixed fixed-top">Country</th>
<th class="fixed fixed-top">Sentence</th>
<th class="fixed fixed-top observed-column">Color</th>
<th class="fixed fixed-top fixed-right fixed-header">Programming Language</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sable</td>
<td>15 yo</td>
<td>Japan</td>
<td>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</td>
<td>Purple</td>
<td class="fixed fixed-right observed-row">Kotlin</td>
</tr>
<tr>
<td>Toco toucan</td>
<td>35 yo</td>
<td>Brazil</td>
<td>
Sed tortor erat, imperdiet a enim quis, placerat rhoncus nisl.
</td>
<td>Orange</td>
<td class="fixed fixed-right">Swift</td>
</tr>
<tr>
<td>Bull</td>
<td>42 yo</td>
<td>Spain</td>
<td>Donec vitae risus urna.</td>
<td>Red</td>
<td class="fixed fixed-right">JavaScript</td>
</tr>
<tr>
<td>Brown bear</td>
<td>17 yo</td>
<td>Russia</td>
<td>Proin gravida et velit ut congue.</td>
<td>Green</td>
<td class="fixed fixed-right">Python</td>
</tr>
</tbody>
</table>
</main>Run Code Online (Sandbox Code Playgroud)
const lastColumn = document.querySelectorAll('.fixed-right');
const header = document.querySelectorAll('.fixed-top');
const tableContainer = document.querySelector('main');
tableContainer.addEventListener('scroll', (e) => {
removeShadowFromColumn();
removeShadowFromHeader();
});
function removeShadowFromHeader() {
if (tableContainer.scrollTop === 0) {
header.forEach(th => th.classList.add('noShadow'));
} else {
header.forEach(th => th.classList.remove('noShadow'));
}
}
function removeShadowFromColumn() {
const widthDiff = tableContainer.scrollWidth - tableContainer.clientWidth;
if (tableContainer.scrollLeft === widthDiff) {
lastColumn.forEach(th => th.classList.add('noShadow'));
} else {
lastColumn.forEach(td => td.classList.remove('noShadow'));
}
}
removeShadowFromHeader();
Run Code Online (Sandbox Code Playgroud)
您还可以在codesandbox上查看演示
PS出于性能原因,我建议您通过使用Intersection Observer API 的第一种方法来执行此操作。