【问题标题】:Expandable box keeps growing可扩展盒子不断增长
【发布时间】:2017-12-16 06:09:01
【问题描述】:

浏览器: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% 的原因。

顺便说一句,修复它的简单方法是从 .card 中删除 flex-direction: column。同样,我对“为什么”感兴趣。

【问题讨论】:

  • 出于某种原因,.wrapper.card-blockheight: 100% 是否必要?
  • @ItayGanor 是的,在应用程序中,我将按钮向下推到所有按钮的底部,并在间隔板上使用 flex-grow: 1。我把那一点去掉,因为它不是问题的一部分,但height: 100% 是产生问题所必需的。
  • 不管为什么会发生这种情况,当在.wrapper 上使用height: 100% 时,您需要问自己,100% 是什么? ...由于其父级没有定义的高度,那些 100% 将解析为 auto.card-block 也会这样做。它似乎在 Chrome 中有些表现,认为这不适用于跨浏览器。
  • @LGSon 高度将解析为自动是什么意思?如果我将它们设置为自动它没有相同的行为。我想要的 100% 是行中最高元素的计算高度。
  • 我发布了一个答案。我并不是说auto 会起作用,我的意思是具有height: 100% 的元素会从其父级中获取100% 的值,但是要使其起作用,父级还需要一个高度,而您没有,因此100% 将解析为 auto

标签: css flexbox


【解决方案1】:

请注意,奇怪的行为似乎是 Chrome 中的一个错误,因为这在其他浏览器中不会发生。

不管为什么会这样,.wrapper上使用height: 100%时,你需要问自己,100%是什么?

具有height: 100% 的元素会从其父级获取 100%,但要使其正常工作,父级还需要一个高度,而您的 card 没有,因此 100% 将解析为 @ 987654326@.

由于wrapper 将被解析为auto.card-block 也将被解析,因为它的父级(wrapper)也没有定义的高度。 (它在 Chrome 中似乎有些表现,认为这不适用于跨浏览器。)

解决办法是一路使用Flexbox。

堆栈sn-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;
}

.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>

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我需要身高:100%。该应用程序还有更多内容。这只是最小的可重现示例。如果你去掉任何一个部分,问题就会消失。但我需要那些零件。
    【解决方案3】:

    据我了解,您是这个意思。我只是将align-items:baseline; 添加到.card 类。我还从.card-block &gt; p 类中删除了margin-top

    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>

    【讨论】:

    • 您能解释一下您所做的更改吗?它仍然会扩展盒子,并且在折叠时不会收缩。它现在没有继续增长。
    • 当然我添加了 align-items:baseline;到 .card 类。我还从 p 标签中删除了 margin-top。
    【解决方案4】:

    一个可能的解决方案是使用

    .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,元素将填充剩余的高度,并且也是一个弹性框,这意味着它的子元素也不会改变.card 的高度。

    【讨论】:

    • “混淆元素”是什么意思。为什么height: 100% 不混淆第一个元素?
    • @bygrace 哪个元素是第一个?
    • 左边的方框。
    • 当第二张卡片的.content 中有更多项目时,似乎根本不会出现这个问题。此外,将overflow-y: scroll 添加到.content 也可以解决此问题。这意味着,这个问题是一个 Chrome 错误,它与 使用滚动条 缩放 div 有关。这就是为什么第二张卡而不是第一张卡会发生这种情况的原因。
    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    相关资源
    最近更新 更多