可扩展的盒子不断增长

时间:2017-12-15 20:56:52

标签: css css3 flexbox

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

4 个答案:

答案 0 :(得分:2)

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

无论为什么会发生这种情况,height: 100%上使用.wrapper时,你需要问问自己,100%是什么?

height: 100%元素从其父级中获取100%的元素,但为了使其工作,父级也需要一个card没有的高度,因此{ {1}}将解析为100%

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

解决方案是一直使用Flexbox。

Stack snippet

&#13;
&#13;
wrapper
&#13;
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');
}
&#13;
.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;
}
&#13;
&#13;
&#13;

答案 1 :(得分: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>

答案 2 :(得分: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>

答案 3 :(得分:0)

可能的解决方案是使用

.wrapper {
  flex: 1;
  display: flex;
}

而不是.wrapper {height: 100%}

&#13;
&#13;
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');
}
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

根据我的理解,height: 100%会混淆元素,因为它的父级高度是扩展的(转换后),所以它想要填充它。使用flex: 1;display: flex,元素将填充剩余高度,也将成为弹性框,这意味着其子级也不会更改.card高度。