Drag-and-drop windows in flexbox cannot get past child elements

I implemented my own split panel using HTML / JS / CSS Flexbox.

I have problems with the separator in the following case: one of the panels has a fixed size (in pixels), and the other is set to grow ( flex-grow: 1 ).

If there are children with a size on the other panel, it will not scroll to the end. He is stuck in the size of children.

Is it possible to fix this using CSS on panels with a split panel, but not on children?

It is very important for me to use flex, because I want to maintain the responsiveness of my application and want to avoid fixed sizes, wherever I am.

This is a JSFiddle sample of my question.

The following is a snippet of code. Thanks!

 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> 
+5
source share
2 answers

He gets stuck in the amount of children

This is the expected behavior when using flexbox . I think if you want to scroll to the end, you can use position: absolute for grandchild relative to c1 :

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

Give overflow: hidden in c1 too:

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

Hooray!

 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> 

Decision

Therefore, I assume that your strategy should be to use an absolute grandchild that fills the entire sidebar and then puts the content inside, like:

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

and change these styles:

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

Example below:

 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> 
+2
source

If another panel has children with a size, it will not scroll to the end. It gets stuck in the amount of children.

This is because the initial setup of the flexible container is min-width: auto for flexible elements. This means that the default flexible item cannot be smaller than the size of its contents.

Can this be fixed with CSS on split-panel panes, but not on child panels?

Yes. Override the default value with min-width: 0 or any overflow except visible :

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

revised violin

 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> 

+2
source

Source: https://habr.com/ru/post/1257431/


All Articles