可扩展盒子不断增长

问题描述 投票:1回答:4

浏览器: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。再一次,我对“为什么”感兴趣。

css css3 flexbox
4个回答
2
投票

请注意,奇怪的行为似乎是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>

0
投票

你应该使用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>

0
投票

据我所知,你的意思是这个。我只是将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>

0
投票

可能的解决方案是使用

.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的高度。

© www.soinside.com 2019 - 2024. All rights reserved.