浏览器:Chrome
我试图设置一排盒子,里面有一个可以展开的物品。我希望同一行上的项目具有相同的高度。当可扩展项目折叠时,我希望容器相应地缩小。不知何故,我创造了一些东西,当盒子扩大时,它不断增加它的大小。
此示例是从应用程序中提取的。所以div的多层可能对你没有多大意义。我只是提取了重现问题所需的最小部分。
const expandButtons = document.querySelectorAll('.expand');
for (let i = 0; i < expandButtons.length; i++) {
const button = expandButtons[i];
button.addEventListener("click", () => toggleExpand(button));
}
function toggleExpand(el) {
const content = el.parentElement.querySelector('.content');
content.classList.toggle('is-expanded');
}
.row {
display: flex;
}
.col {
display: flex;
}
.card {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.wrapper {
height: 100%;
}
.card-block {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
max-height: 0;
overflow: auto;
transition: max-height 500ms;
}
.content.is-expanded {
max-height: 6em;
}
.spacer {
display: flex;
flex-grow: 1;
}
<div class="row">
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<p>ASDF</p>
<div class="content">
<p>First</p>
<p>Second</p>
<p>Third</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<div class="content">
<p>First</p>
<p>Second</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
</div>
题
展开第二个框会增加高度,折叠时不会向后缩回。扩展/折叠第一个修复它。为什么会这样? (我对解释而不是解决方案感兴趣)
编辑
我添加了示例中证明height: 100%
合理的部分以避免混淆。这样我就可以将按钮保持在底部。这包括将display: flex; flex-direction: column;
添加到.card-block
并添加.spacer
类和相应的元素。这些不会导致问题,但是height: 100%
的原因。
顺便说一句,解决它的简单方法是从flex-direction: column
中删除.card
。再一次,我对“为什么”感兴趣。
请注意,奇怪的行为似乎是Chrome中的一个错误,因为在其他浏览器中不会发生这种情况。
无论为什么会这样,
当在height: 100%
上使用.wrapper
时,你需要问自己,100%的是什么?
有height: 100%
的元素从其父级中获取100%,但为了工作,父级需要一个高度,这是你的card
没有,因此100%
将解析为auto
。
由于wrapper
将被解析auto
,所以.card-block
也将如此,因为它的父母(wrapper
)也没有明确的高度。 (它似乎在Chrome中有点表现,认为这不适用于跨浏览器。)
解决方案是一直使用Flexbox。
堆栈代码段
const expandButtons = document.querySelectorAll('.expand');
for (let i = 0; i < expandButtons.length; i++) {
const button = expandButtons[i];
button.addEventListener("click", () => toggleExpand(button));
}
function toggleExpand(el) {
const content = el.parentElement.querySelector('.content');
content.classList.toggle('is-expanded');
}
.row {
display: flex;
}
.col {
display: flex;
}
.card {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.wrapper {
/*height: 100%; removed */
flex: 1; /* added, fill parent height */
display: flex; /* added */
/*align-items: stretch this is the default and make its item,
the "card-block", fill its parent height */
}
.card-block {
/*height: 100%; removed */
display: flex;
flex-direction: column;
}
.content {
max-height: 0;
overflow: auto;
transition: max-height 500ms;
}
.content.is-expanded {
max-height: 6em;
}
.spacer {
display: flex;
flex-grow: 1;
}
<div class="row">
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<p>ASDF</p>
<div class="content">
<p>First</p>
<p>Second</p>
<p>Third</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<div class="content">
<p>First</p>
<p>Second</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
</div>
你应该使用height:auto,而不是height:100%;
const expandButtons = document.querySelectorAll('.expand');
expandButtons.forEach(x => {
x.addEventListener("click", () => toggleExpand(x));
});
function toggleExpand(el) {
const content = el.parentElement.querySelector('.content');
content.classList.toggle('is-expanded');
}
.row {
display: flex;
}
.col {
display: flex;
}
.card {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.wrapper {
height: auto;
}
.card-block {
height: auto;
}
.content {
max-height: 0;
overflow: auto;
transition: max-height 500ms;
}
.content.is-expanded {
max-height: 6em;
}
<div class="row">
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<p>ASDF</p>
<div class="content">
<p>First</p>
<p>Second</p>
<p>Third</p>
</div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<div class="content">
<p>First</p>
<p>Second</p>
</div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
</div>
据我所知,你的意思是这个。我只是将align-items:baseline;
添加到.card
类。我也从margin-top
班中删除了.card-block > p
。
const expandButtons = document.querySelectorAll('.expand');
for (let i = 0; i < expandButtons.length; i++) {
const button = expandButtons[i];
button.addEventListener("click", () => toggleExpand(button));
}
function toggleExpand(el) {
const content = el.parentElement.querySelector('.content');
content.classList.toggle('is-expanded');
}
.row {
display: flex;
}
.col {
display: flex;
}
.card {
display: flex;
flex-direction: column;
border: 1px solid black;
align-items: baseline;
}
.wrapper {
height: 100%;
}
.card-block {
height: 100%;
}
.card-block > p {
margin-top: 0;
}
.content {
max-height: 0;
overflow: auto;
transition: max-height 500ms;
}
.content.is-expanded {
max-height: 6em;
}
<div class="row">
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<p>ASDF</p>
<div class="content">
<p>First</p>
<p>Second</p>
<p>Third</p>
</div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<div class="content">
<p>First</p>
<p>Second</p>
</div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
</div>
可能的解决方案是使用
.wrapper {
flex: 1;
display: flex;
}
而不是.wrapper {height: 100%}
。
const expandButtons = document.querySelectorAll('.expand');
for (let i = 0; i < expandButtons.length; i++) {
const button = expandButtons[i];
button.addEventListener("click", () => toggleExpand(button));
}
function toggleExpand(el) {
const content = el.parentElement.querySelector('.content');
content.classList.toggle('is-expanded');
}
.row {
display: flex;
}
.col {
display: flex;
}
.card {
display: flex;
flex-direction: column;
border: 1px solid black;
}
.wrapper {
flex: 1;
display: flex;
}
.card-block {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
max-height: 0;
overflow: auto;
transition: max-height 500ms;
}
.content.is-expanded {
max-height: 6em;
}
.spacer {
display: flex;
flex-grow: 1;
}
<div class="row">
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<p>ASDF</p>
<div class="content">
<p>First</p>
<p>Second</p>
<p>Third</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="wrapper">
<div class="card-block">
<div class="content">
<p>First</p>
<p>Second</p>
</div>
<div class="spacer"></div>
<button type="button" class="expand">Expand</button>
</div>
</div>
</div>
</div>
</div>
根据我的理解,height: 100%
混淆了元素,因为它的父元素的高度是扩展的元素(在转换之后),所以它想要填充它。使用flex: 1;
和display: flex
,元素将填充剩余的高度,也将是一个flexbox,意味着它的孩子也不会改变.card
的高度。