使用 jQuery 设置元素高度给出不正确的高度



我有一个元素列表(我称之为卡片(,每个元素的宽度为33%,以填充页面。 它们内部是一个标题和一个详细信息,我想通过单击复选框来显示所有这些的详细信息。 详细信息的长度在所有卡片之间是可变的,因此当用户单击以显示详细信息时,我尝试获取每张卡片详细信息的高度,将它们设置为相同,然后显示所有卡片的详细信息。

我正确设置了高度,但是一旦调用slideDown()它们,它们就会被赋予比我设置的高度更大的高度。 我终于能够弄清楚它与data-set-label有关,data-set-datainline-block并且宽度为 50%。 如果我删除它,slideDown()显示适当的高度。 就好像slideDown()没有考虑到内联块元素在同一行上,但这似乎不对......

出了什么问题?

$(document).ready(function() {
$("#ShowDetailsCheckBox").change(function() {
if ($(this).is(":checked")) {
setContentDataHeights();
$(".cards-card-detail").slideDown();
} else {
$(".cards-card-detail").slideUp();
}
});
});
function setContentDataHeights() {
var maxContentDataHeight = 0;
$(".cards-card-detail").each(function() {
if ($(this).height() > maxContentDataHeight)
maxContentDataHeight = $(this).height();
});
if (maxContentDataHeight > 0) {
$(".cards-card-detail").each(function() {
//$(this).css("height", maxContentDataHeight.toString() + "px");
$(this).height(maxContentDataHeight);
});
}
}
* {
box-sizing: border-box;
}
.cards {
font-size: 0;
}
.cards-card {
font-size: 12pt;
display: inline-block;
width: 33%;
vertical-align: top;
border: 1px solid red;
}
.cards-card:nth-child(2n) {
width: 34%;
border: 1px solid green;
}
.cards-card-header {
height: 100px;
}
.cards-card-detail {
padding: 10px;
border-top: 1px solid red;
display: none;
}
.data-set-wrapper {
width: 100%;
font-size: 0;
}
.data-set-label {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
.data-set-data {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type="checkbox" id="ShowDetailsCheckBox" />Show details
<div class="cards">
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
</div>

在 JSFiddle 上查看

这很时髦。

一个理论:

.cards-card-detail元素有display:none时,它们的宽度是未定义的。.data-set-label元素width:50%但是,由于它们的父元素的宽度未定义,它们的宽度以一种奇怪的方式计算,导致内部文本换行和高度被抛弃。

一些测试:

在下面的测试中,.data-set-label的宽度计算为"50 像素",即使它被定义为"50%"。但是当.cards-card-detaildisplay:block时,会返回更准确的宽度。

$(function() {
console.log("display:none - " + $('.data-set-label').width());
$('.cards-card-detail').show()
console.log("display:block - " + $('.data-set-label').width());
});
* {
box-sizing: border-box;
}
.cards {
font-size: 0;
}
.cards-card {
font-size: 12pt;
display: inline-block;
width: 33%;
vertical-align: top;
border: 1px solid red;
}
.cards-card:nth-child(2n) {
width: 34%;
border: 1px solid green;
}
.cards-card-header {
height: 100px;
}
.cards-card-detail {
padding: 10px;
border-top: 1px solid red;
display: none;
}
.data-set-wrapper {
font-size: 0;
}
.data-set-label {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
.data-set-data {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="cards">
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
</div>

.data-set-label的宽度明确设置为"50px"会使文本换行并增加.cards-card-detail的高度,似乎与您的示例中的"错误"高度相同(巧合?

* {
box-sizing: border-box;
}
.cards {
font-size: 0;
}
.cards-card {
font-size: 12pt;
display: inline-block;
width: 33%;
vertical-align: top;
border: 1px solid red;
}
.cards-card:nth-child(2n) {
width: 34%;
border: 1px solid green;
}
.cards-card-header {
height: 100px;
}
.cards-card-detail {
padding: 10px;
border-top: 1px solid red;
}
.data-set-wrapper {
font-size: 0;
}
.data-set-label {
font-size: 12px;
border: 1px solid red;
width: 50px;
display: inline-block;
}
.data-set-data {
font-size: 12px;
border: 1px solid red;
width: 50px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="cards">
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
</div>

一个解决方案:

我通过将.cards-card-detail的宽度定义为"100%"取得了一些成功,希望孩子们的"50%"宽度能够正确设置。

$(function() {
$("#ShowDetailsCheckBox").change(function() {
if ($(this).is(":checked")) {
setContentDataHeights();
$(".cards-card-detail").slideDown();
} else {
$(".cards-card-detail").slideUp();
}
});
});
function setContentDataHeights() {
var maxContentDataHeight = 0;
$(".cards-card-detail").each(function() {
if ($(this).height() > maxContentDataHeight)
maxContentDataHeight = $(this).height();
});
if (maxContentDataHeight > 0) {
$(".cards-card-detail").height(maxContentDataHeight);
}
}
* {
box-sizing: border-box;
}
.cards {
font-size: 0;
}
.cards-card {
font-size: 12pt;
display: inline-block;
width: 33%;
vertical-align: top;
border: 1px solid red;
}
.cards-card:nth-child(2n) {
width: 34%;
border: 1px solid green;
}
.cards-card-header {
height: 100px;
}
.cards-card-detail {
padding: 10px;
border-top: 1px solid red;
display: none;
width: 100%;
}
.data-set-wrapper {
font-size: 0;
}
.data-set-label {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
.data-set-data {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type="checkbox" id="ShowDetailsCheckBox" />Show details
<div class="cards">
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
</div>

我对其他解释很好奇。


编辑:

我明白你的意思:上面的解决方案不能始终如一地工作。
这是一种替代技术:

.cards设置为opacity:0,直到设置.card-card-detail的高度。然后揭开卡片。

$(document).ready(function() {
setContentDataHeights();
$('.cards-card-detail').hide();
$('.cards').addClass('show');
$("#ShowDetailsCheckBox").change(function() {
if ($(this).is(":checked")) {
$(".cards-card-detail").slideDown();
} else {
$(".cards-card-detail").slideUp();
}
});
});
function setContentDataHeights() {
var maxContentDataHeight = 0;
$(".cards-card-detail").each(function() {
if ($(this).height() > maxContentDataHeight)
maxContentDataHeight = $(this).height();
});
if (maxContentDataHeight > 0) {
$(".cards-card-detail").height(maxContentDataHeight);
}
}
* {
box-sizing: border-box;
}
.cards {
font-size: 0;
opacity: 0;
transition: opacity .25s;
}
.cards.show {
opacity: 1;
}
.cards-card {
font-size: 12pt;
display: inline-block;
width: 33%;
vertical-align: top;
border: 1px solid red;
}
.cards-card:nth-child(2n) {
width: 34%;
border: 1px solid green;
}
.cards-card-header {
height: 100px;
}
.cards-card-detail {
padding: 10px;
border-top: 1px solid red;
}
.data-set-wrapper {
font-size: 0;
}
.data-set-label {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
vertical-align: top;
}
.data-set-data {
font-size: 12px;
border: 1px solid red;
width: 50%;
display: inline-block;
vertical-align: top;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="ShowDetailsCheckBox" />Show details
<div class="cards">
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">label label label label label label </label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">label label label label label label label label label label </label>
<div class="data-set-data">
some data
</div>
</div>
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
<div class="cards-card">
<div class="cards-card-header">
Here is some header information
</div>
<div class="cards-card-detail">
<div class="data-set-wrapper">
<label class="data-set-label">Label</label>
<div class="data-set-data">
some data
</div>
</div>
</div>
</div>
</div>

最新更新