Dragging a child from an overflow container-y: scroll

I have a container with a list inside. List items can be dragged by moving with the mouse.

The container scrolls with:

overflow-y: scroll; 

By setting this property, Chrome automatically sets the overflow-x property to 'auto'. If I set overflow-x: visible , it is ignored by Chrome. If I set overflow-x: hidden , then obviously the item is cropped.

When I drag a list item out of the left or top edge of the container, it is cropped around the edges of the container. If I pulled it from the right or bottom edge, the container scrolls to fit it. I would like the element to be able to be dragged out of the container without cropping it and without it to start scrolling.

Given that the container must be set to overflow-y: scroll , and this in turn forces Chrome to install overflow-x: auto , is there any way to achieve this or is it impossible?

Codepen: http://codepen.io/Pedr/pen/azLWeY

Note: I know that I can crack it with an add-on to compensate for the container (so that the container’s limits actually end outside its visual borders), but this is not an option in my situation.

 $(function() { $('.Wrapper').mousemove(function(event){ $('.Item').offset({left: event.pageX, top: event.pageY}); }); }) 
 html, body { height: 100%; } .Wrapper { width: 100%; height: 100%; position: absolute; } .Container { background: grey; position: absolute; width: 50%; left: 25%; min-height: 100%; overflow-y: scroll; overflow-x: hidden; // Clips Item // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge. } .Item { padding: 20px; background: red; position: absolute; width: 600px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="Wrapper"> <div class="Container"> <div class="Item">ITEM</div> </div> </div> 
+7
html css overflow drag-and-drop clip
source share
8 answers

Here is my edit: http://codepen.io/anon/pen/MYrxGJ

What I did, set the Wrapper position to relative, delete the CSS Container position and set it to margin-left: 25%; margin-right: 25%; margin-left: 25%; margin-right: 25%; (same effect as margin: 0px auto; ). Thus, the absolute positioning of the div Item refers to the Wrapper div instead of the Container div.

+3
source share

Set ITEM to the fixed position .... to divert it from everything else

It works like this

 $(function() { $('.Wrapper').mousemove(function(event){ $('.Item').css('position', 'fixed'); $('.Item').offset({left: event.pageX, top: event.pageY}); }); }) 

Look at the snippet here:

 $(function() { $('.Wrapper').mousemove(function(event){ $('.Item').css('position', 'fixed'); $('.Item').offset({left: event.pageX, top: event.pageY}); }); }) 
 .Wrapper { width: 100%; height: 100%; position: absolute; } .Container { background: grey; position: absolute; width: 50%; left: 25%; min-height: 100%; overflow-y: scroll; overflow-x: hidden; // Clips Item // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge. } .Item { padding: 20px; background: red; position: absolute; width: 600px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="Wrapper"> <div class="Container"> <div class="Item">ITEM</div> </div> </div> 
+3
source share

I believe this will take care of your overflow problem. Basically, “turn off” the -y overflow on .mousemove () and first set the item's element outside the container. And you can remove the position: absolute from the container and have the following: http://codepen.io/anon/pen/jEaRaz

 $(function() { $('.Wrapper').mousemove(function(event){ $('.Item').offset({left: event.pageX, top: event.pageY}); $('.Container').css('overflow-y', 'hidden') }); }) 
+1
source share

Personally, I would use position:fixed - it would pull out a container being dragged from the rendering tree, since with respect to the container it would have nothing to do with overflow and would just draw directly onto windows without any scroll bars or clipping.

 $('.Wrapper').on("mousedown", ".Item", function(event){ $(event.target) .css('position', 'fixed') .on("mousemove", function(event){ // Take into account offset within element $(this).offset({left: event.pageX, top: event.pageY}); }) .one("mouseup", function(event){ // Finish dealing with element and clear position and event $(this) .off("mousemove") .css('position', ''); }) }); 
+1
source share

I believe your problem is with positioning. Could you try to make your .Container element at position:relative; , I think this will solve your problem, but you may have to work a bit on the actual positioning of the element.

EDIT: ignore above

Ok, it is fixed: change .Container to ..

.Container { background: none repeat scroll 0 0 grey; left: 25%; margin: 0 auto; min-height: 100%; overflow-x: hidden; overflow-y: scroll; position: static; width: 50%; }

firstly, this will allow your draggable element to be outside the container element, and then set margin: 0 auto; will ensure that the container is in the middle.

-one
source share

Try this method, I cloned the draggable element and add it to the body.

Js

 var cloneItem = $('.Item').clone().hide().appendTo("body"); 

http://codepen.io/nandhakumaru/pen/VYyMqr

-one
source share

You can duplicate an item outside the container when you select an item, and then delete it after it is deleted.

http://codepen.io/anon/pen/OPOMMp

Also, I would hide the overflow on the wrapper.

 .Wrapper { width: 100%; height: 100%; position: absolute; overflow: hidden; } 
-2
source share

I realized that this can be done simply by making the majority of your elements in the layout and making the elements dragged out of the layout, and it turned out that I was right. If you remove the position: absolute from your wrapper and from your container (which makes them render in the layout), and then give the margin-left field: 25%, you retain the same effect as before, but since the element itself is a position : absolute without any relative or absolutely positioned parent elements, it is positioned “outside the layout”, which means that it can exit this container. See this example: http://codepen.io/anon/pen/vEWGaa

(SO wants me to have code with a code page, so here is the new CSS):

 html, body { height: 100%; } .Wrapper { width: 100%; height: 100%; } .Container { background: grey; width: 50%; margin-left: 25%; min-height: 100%; overflow-y: scroll; overflow-x: hidden; // Clips Item // If left at auto it will clip the item on the top and left edge and scroll if the item overlaps the bottom or right edge. } .Item { padding: 20px; background: red; position: absolute; width: 600px; } 

EDIT: Also, if you place an overflow: hidden on the body, you do not get a scrollbar when your item is dragged out of the screen.

-2
source share

All Articles