如何防止Flex容器溢出/下溢?

时间:2016-07-24 12:34:15

标签: javascript css flexbox

我有一个可以通过拖动调整大小的flexbox容器。如何防止容器溢出(变得太小并开始隐藏某些项目)或下溢(变得过大并显示空白)?

在下面的示例中,当所有项目都达到18px高度(最后一个除外)时,容器应停止收缩,并在所有项目达到最大高度时停止展开(不应出现空格)。



const resizable = document.querySelector('.flex');
let startHeight = NaN;
let startY = NaN;

resizable.addEventListener('mousedown', e => {
  startHeight = resizable.getBoundingClientRect().height;
  startY = e.pageY;
});

window.addEventListener('mousemove', e => {
  if (isNaN(startY) || isNaN(startHeight)) {
    return;
  }
  
  resizable.style.height = (startHeight + e.pageY - startY) + 'px';
});

window.addEventListener('mouseup', () => {
  startHeight = startY = NaN;
});

.flex {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid black;
  cursor: ns-resize;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.item-1 {
  background: red;
  height: 40px;
  max-height: 60px;
  flex: 1;
}

.item-2 {
  background: blue;
  flex: none;
}

.item-3 {
  background: green;
  height: 50px;
  max-height: 50px;
  flex: 1;
}

.item-4 {
  background: yellow;
  height: 30px;
  flex: none;
}

<div class="flex">
  <div class="item-1">
    Item 1
  </div>
  <div class="item-2">
    Item 2
  </div>
  <div class="item-3">
    Item 3
  </div>
  <div class="item-4">
    Item 4
  </div>
</div>
&#13;
&#13;
&#13;

首选纯CSS解决方案。解决方案应该允许缩小容器,使所有物品都处于最小尺寸,并扩展它以使它们全部占据它们的最大尺寸。 在容器的CSS中硬编码最小和最大高度是不可接受的。我正在寻找通用的解决方案。

1 个答案:

答案 0 :(得分:1)

我不认为这里可以使用纯CSS解决方案,因为你绝对使用JavaScript来设置高度。

您可以在下面的代码段中添加一个像我所做的那样的警卫。当可调整大小为零时,你也可以计算底部高度,当它是巨大的时候,并根据它来引入边界(可能性能更好,但dom更改不好)

const resizable = document.querySelector('.flex');
const lastChild = resizable.querySelector(':last-child');
const resizableBorderBottom = 1;  // hardcoded - could be computed too
let startHeight = NaN;
let startY = NaN;

resizable.addEventListener('mousedown', e => {
  /* 
   * here we assume that the bottom of the last child
   * is the same as the bottom of the resizable for simplicity
   */
  startHeight = resizable.getBoundingClientRect().height;
  startY = e.pageY;
});

window.addEventListener('mousemove', e => {
  if (isNaN(startY) || isNaN(startHeight)) {
    return;
  }
  const lastHeight = resizable.style.height;
  resizable.style.height = ((startHeight + e.pageY - startY) | 0) + 'px';
  const lastChildBottom = lastChild.getBoundingClientRect().bottom | 0;
  const resizableBottom = (resizable.getBoundingClientRect().bottom | 0) - resizableBorderBottom;
  // check if we need to revert the change
  if (lastChildBottom !== resizableBottom) {
    resizable.style.height = lastHeight;
  }
});

window.addEventListener('mouseup', () => {
  startHeight = startY = NaN;
});
.flex {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid black;
  cursor: ns-resize;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.item-1 {
  background: red;
  height: 40px;
  max-height: 60px;
  flex: 1;
}

.item-2 {
  background: blue;
  flex: none;
}

.item-3 {
  background: green;
  height: 50px;
  max-height: 50px;
  flex: 1;
}

.item-4 {
  background: yellow;
  height: 30px;
  flex: none;
}
<div class="flex">
  <div class="item-1">
    Item 1
  </div>
  <div class="item-2">
    Item 2
  </div>
  <div class="item-3">
    Item 3
  </div>
  <div class="item-4">
    Item 4
  </div>
</div>