flexbox中可拖动的分割窗格窗口不能越过子元素

Draggable split-pane windows in flexbox can't get past child elements

本文关键字:不能 窗口 元素 拖动 分割 flexbox      更新时间:2023-09-26

我用HTML/JS/CSS Flexbox实现了我自己的拆分窗格。

在以下情况下,我遇到了拆分器的问题-其中一个面板具有固定的大小(px),而另一个面板设置为增长(flex-grow: 1)。

如果另一个面板有子面板大小,它将不会滚动到最后。它被卡在子元素的大小上

这可以用CSS在拆分窗格面板上而不是在子面板上修复吗?

使用flex对我来说是非常重要的,因为我想保持我的应用程序的响应性,并希望尽可能避免固定大小。

这是一个JSFiddle示例我的问题。

代码片段如下所示。谢谢!

function startDrag() {
  glass.style = 'display: block;';
  glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
  glass.removeEventListener('mousemove', drag, false);
  glass.style = '';
}
function drag(event) {
  var splitter = getSplitter();
  var panel = document.getElementById('c2');
  var currentWidth = panel.offsetWidth;
  var currentLeft = panel.offsetLeft;
  panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
  return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
  display: flex;
  border: 1px solid;
  width: 500px;
  height: 300px;
  position: absolute;
}
.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
}
.c2 {
  background-color: green;
  width: 150px;
}
.splitter {
  width: 20px;
  cursor: col-resize;
}
.glass {
  height: 100%;
  width: 100%;
  cursor: col-resize;
  display: none;
  position: absolute;
}
.grandchild {
  background-color: red;
  width: 50px;
  height: 50px;
}
<div id="container" class="container">
  <div id="glass" class="glass"></div>
  <div class="c1">
    <div class="grandchild"></div>
  </div>
  <div id="c2" class="c2"></div>
</div>

如果另一个面板有子面板大小,它将不会滚动到最后。它被卡在子元素的大小上

这是因为伸缩容器在伸缩项上的初始设置是min-width: auto。这意味着,默认情况下,伸缩项的大小不能小于其内容的大小。

这可以用CSS在拆分窗格面板上而不是在子面板上修复吗?

是的。用min-width: 0visible以外的任何overflow覆盖默认值:

.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
  overflow: hidden; /* or min-width: 0 */
}

修订小提琴

function startDrag() {
  glass.style = 'display: block;';
  glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
  glass.removeEventListener('mousemove', drag, false);
  glass.style = '';
}
function drag(event) {
  var splitter = getSplitter();
  var panel = document.getElementById('c2');
  var currentWidth = panel.offsetWidth;
  var currentLeft = panel.offsetLeft;
  panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
  return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
  display: flex;
  border: 1px solid;
  width: 500px;
  height: 300px;
  position: absolute;
}
.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
  overflow: hidden;  
}
.c2 {
  background-color: green;
  width: 150px;
}
.splitter {
  width: 20px;
  cursor: col-resize;
}
.glass {
  height: 100%;
  width: 100%;
  cursor: col-resize;
  display: none;
  position: absolute;
}
.grandchild {
  background-color: red;
  width: 50px;
  height: 50px;
}
<div id="container" class="container">
  <div id="glass" class="glass"></div>
  <div class="c1">
    <div class="grandchild"></div>
  </div>
  <div id="c2" class="c2"></div>
</div>

它被固定在子元素的大小

当使用flexbox时,这是预期的行为。我猜如果你想要滚动到末尾那么你可以使用position: absolute来代替grandchild相对于c1:

.grandchild {
  background-color: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 0;
  left: 0;
}

Give overflow: hidden to c1 too:

.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
  position: relative;
  overflow: hidden;
}

干杯!

function startDrag() {
  glass.style = 'display: block;';
  glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
  glass.removeEventListener('mousemove', drag, false);
  glass.style = '';
}
function drag(event) {
  var splitter = getSplitter();
  var panel = document.getElementById('c2');
  var currentWidth = panel.offsetWidth;
  var currentLeft = panel.offsetLeft;
  panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
  return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
  display: flex;
  border: 1px solid;
  width: 500px;
  height: 300px;
  position: absolute;
}
.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
  position: relative;
  overflow: hidden;
}
.c2 {
  background-color: green;
  width: 150px;
}
.splitter {
  width: 20px;
  cursor: col-resize;
}
.glass {
  height: 100%;
  width: 100%;
  cursor: col-resize;
  display: none;
  position: absolute;
}
.grandchild {
  background-color: red;
  width: 50px;
  height: 50px;
  position: absolute;
  top: 0;
  left: 0;
}
<div id="container" class="container">
  <div id="glass" class="glass"></div>
  <div class="c1">
    <div class="grandchild"></div>
  </div>
  <div id="c2" class="c2"></div>
</div>

<

解决方案/strong>:

所以我猜你的策略应该是使用一个绝对的grandchild填充整个侧板,然后把content放在里面,像:

<div class="grandchild">
  <div class="content"></div>
</div>

并更改这些样式:

.grandchild {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.grandchild .content{
  background-color: red;
  width: 50px;
  height: 50px;
}
在下面的示例

:

function startDrag() {
  glass.style = 'display: block;';
  glass.addEventListener('mousemove', drag, false);
}
function endDrag() {
  glass.removeEventListener('mousemove', drag, false);
  glass.style = '';
}
function drag(event) {
  var splitter = getSplitter();
  var panel = document.getElementById('c2');
  var currentWidth = panel.offsetWidth;
  var currentLeft = panel.offsetLeft;
  panel.style.width = (currentWidth - (event.clientX - currentLeft)) + "px";
}
function getSplitter() {
  return document.getElementById('splitter');
}
var con = document.getElementById('container');
var splitter = document.createElement('div');
var glass = document.getElementById('glass');
splitter.className = 'splitter';
splitter.id = 'splitter';
con.insertBefore(splitter, con.lastElementChild);
splitter.addEventListener('mousedown', startDrag, false);
glass.addEventListener('mouseup', endDrag, false);
.container {
  display: flex;
  border: 1px solid;
  width: 500px;
  height: 300px;
  position: absolute;
}
.c1 {
  background-color: blue;
  flex: 1;
  height: 100%;
  position: relative;
  overflow: hidden;
}
.c2 {
  background-color: green;
  width: 150px;
}
.splitter {
  width: 20px;
  cursor: col-resize;
}
.glass {
  height: 100%;
  width: 100%;
  cursor: col-resize;
  display: none;
  position: absolute;
}
.grandchild {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.grandchild .content{
  background-color: red;
  width: 50px;
  height: 50px;
}
<div id="container" class="container">
  <div id="glass" class="glass"></div>
  <div class="c1">
    <div class="grandchild">
      <div class="content"></div>
    </div>
  </div>
  <div id="c2" class="c2"></div>
</div>