【发布时间】:2021-07-25 12:35:22
【问题描述】:
我正在编写一个网页,其中有一个表格,其中的行可以滑动打开和关闭。最初,有些行是关闭的 (display: none),我希望它们滑动打开。设置高度和使用overflow: hidden 不适用于表格行,所以我要更改表格内 div 的高度。
这行得通。唯一的问题是我需要在滑动打开之前知道 div 的高度,这似乎是不可能的。我能想到的一种解决方案是加载显示行的页面,然后遍历它们,存储它们的高度并隐藏它们。我不喜欢这个解决方案,因为加载时页面会跳来跳去。
这是我的问题的一个简单、可运行的示例。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
table, td {border: 1px solid black;}
#lower_row {display: none;}
#lower_div {overflow: hidden;}
</style>
<script type="text/javascript">
function toggleLower() {
lowerRow = document.getElementById("lower_row");
lowerDiv = document.getElementById("lower_div");
if (getStyle(lowerRow, "display") == "none") {
lowerRow.style.display = "table-row";
}
else {
lowerRow.style.display = "none";
}
showHeight();
}
function showHeight() {
lowerDiv = document.getElementById("lower_div");
document.getElementById("info").innerHTML = getStyle(lowerDiv, "height");
}
// Return a style atribute of an element.
// J/S Pro Techniques p136
function getStyle(elem, name) {
if (elem.style[name]) {
return elem.style[name];
}
else if (elem.currentStyle) {
return elem.currentStyle[name];
}
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/([A-Z])/g, "-$1");
name = name.toLowerCase();
s = document.defaultView.getComputedStyle(elem, "");
return s && s.getPropertyValue(name);
}
else {
return null;
}
}
</script>
</head>
<body onload="showHeight()">
<p>The height the lower row is currently <span id="info"></span></p>
<table>
<tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
<tr id="lower_row"><td><div id="lower_div"><p>Peekaboo!</p></div></td></tr>
</table>
</body>
</html>
编辑 1:
一种建议的解决方案是将 div 移出页面。我无法让它工作,而且我认为它的高度会错误,因为它的高度取决于桌子的宽度。
我正在研究使用visibility:hidden 的解决方案,但它有问题。它仍然占用少量空间,并且报告的高度是错误的。这是该解决方案的一个示例:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
table {width: 250px;}
table, td {border: 1px solid black;}
#lower_row {position: absolute; visibility: hidden}
#lower_div {overflow: hidden;}
</style>
<script type="text/javascript">
function toggleLower() {
lowerRow = document.getElementById("lower_row");
lowerDiv = document.getElementById("lower_div");
if (getStyle(lowerRow, "visibility") == "hidden") {
lowerRow.style.visibility = "visible";
lowerRow.style.position = "static";
}
else {
lowerRow.style.visibility = "hidden";
lowerRow.style.position = "absolute";
}
showHeight();
}
function showHeight() {
lowerDiv = document.getElementById("lower_div");
document.getElementById("info").innerHTML = getStyle(lowerDiv, "height");
}
// Return a style atribute of an element.
// J/S Pro Techniques p136
function getStyle(elem, name) {
if (elem.style[name]) {
return elem.style[name];
}
else if (elem.currentStyle) {
return elem.currentStyle[name];
}
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/([A-Z])/g, "-$1");
name = name.toLowerCase();
s = document.defaultView.getComputedStyle(elem, "");
return s && s.getPropertyValue(name);
}
else {
return null;
}
}
</script>
</head>
<body onload="showHeight()">
<p>The height the lower row is currently <span id="info"></span></p>
<table>
<tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
<tr id="lower_row"><td><div id="lower_div"><p>This is some long text. This is some long text. This is some long text. This is some long text.</p></div></td></tr>
</table>
</body>
</html>
编辑 2:解决方案
Paul 的回答是我的问题的解决方案:如何找到未显示的元素的高度。但是,它不适用于我的问题。在我的网站上,div 的高度取决于它的宽度,它取决于 td 的宽度,它取决于其他行的状态和表格的宽度,它取决于页面的宽度。这意味着,即使我预先计算了高度,只要有人扩展另一行或更改窗口大小,该值也会出错。此外,复制表格并保留所有这些约束几乎是不可能的。
但是,我找到了解决方案。当用户点击展开一行时,我的网站会按顺序执行以下步骤:
- 将 div.style.height 设置为 1px。
- 将 row.style.display 设置为 table-row。
- 存储 div.scrollHeight 的值。
- 运行滚动动画,在 div.scrollHeight 处停止。
- 动画结束后,将 div.style.height 设置为 auto。
div.scrollHeight 给出了 div 内容的高度,包括它的溢出。不显示 div 时它不起作用,但这对我的应用程序来说不是问题。这是实际代码的示例。 (同样,我没有包含滚动动画的代码,因为它太长了。)
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
table, td {border: 1px solid black;}
#lower_row {display: none;}
#lower_div {overflow: hidden;}
</style>
<script type="text/javascript">
function toggleLower() {
var lowerRow = document.getElementById("lower_row");
var lowerDiv = document.getElementById("lower_div");
if (getStyle(lowerRow, "display") == "none") {
lowerDiv.style.height = "0px";
lowerRow.style.display = "table-row";
showHeight();
lowerDiv.style.height = "auto";
}
else {
lowerDiv.style.height = "0px";
showHeight();
lowerRow.style.display = "none";
}
}
function showHeight() {
var lowerDiv = document.getElementById("lower_div");
document.getElementById("info").innerHTML = lowerDiv.scrollHeight;
}
// Return a style atribute of an element.
// J/S Pro Techniques p136
function getStyle(elem, name) {
if (elem.style[name]) {
return elem.style[name];
}
else if (elem.currentStyle) {
return elem.currentStyle[name];
}
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/([A-Z])/g, "-$1");
name = name.toLowerCase();
s = document.defaultView.getComputedStyle(elem, "");
return s && s.getPropertyValue(name);
}
else {
return null;
}
}
</script>
</head>
<body>
<p>The height the lower row is currently <span id="info">...</span></p>
<table>
<tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
<tr id="lower_row"><td><div id="lower_div"><p>
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
This is some long text. This is some long text. This is some long text. This is some long text.
</p></div></td></tr>
</table>
</body>
</html>
【问题讨论】:
-
似乎是什么问题?您的 html 工作正常。当我单击该行时,下面的行会展开。
-
@vishal 为了简单起见,我的示例没有滑动动画。为了有一个滑动动画,我需要知道它展开之前的高度。正如我的示例所示,它展开之前的高度是“自动”。
-
@dln385 请在我的帖子中查看我的更新
标签: javascript html css