1

I'm trying to make certain elements on my page draggable. These elements have transform: translate3d() applied to them, but when running

$(".draggable").draggable();

it makes the elements ignore the transform: translate3d() CSS style. Here's a JS fiddle showing the problem:

https://jsfiddle.net/snbe92ff/

The yellow bar on top of the orange box is not supposed to be visible, yet, when draggable() is used, it is. I'm not sure why this happens. According to chrome, no styles are overridden, but these classes are added to the elements:

ui-draggable
ui-draggable-handle

Looking at the jQuery source code, no transform is happening there either. So why is transform: translate3d() being ignored when draggable() is executed, and how do I fix it?

RedShift
  • 287
  • 1
  • 6
  • 17
  • 1
    Please do not use inline styles... it makes it a lot harder to work with your code. – T J Feb 18 '16 at 06:52

2 Answers2

1

At the moment, your absolutely positioned elements are positioned relative to the transformed element since it establishes a new local coordinate system (see https://www.w3.org/TR/css3-transforms/#transform-rendering) and none of the other near by parents do.

So unlike what you think, the yellow bar on top of orange bar is not hidden by blue bar overlapping it. It's not visible on top of orange bar because all the yellow bars are actually at the top of the blue bar, since they are positioned relative to the transformed parent.

The moment you apply draggable(), the immediate parent <div> of these bars gets position:relative (establishing a new coordinate system) hence the bars positions relative to them, which is why orange box's top bar appears on top of it (till now it was on top of the transformed parent).


From what I understood you want the box on top to hide the bar of the box below it, which can be achieved by giving the bars a lower z-index and setting a high z-index via the zIndex property of draggable. This property sets an z-index only while the item is being dragged. Hence the lower z-index we applied to bars won't affect during dragging. As soon as we finish dragging and draggable loses this higher z-index, the lower z-index of the bar takes effect.

You can test this by overlapping the orange box with the blue box in demo.

$(document).ready(function() {
  $('.draggable').draggable({
    zIndex: 1
  })
});
#container {
  transform-style: preserve-3d;
  transform: translateY(20px);
}
.draggable {
  width: 90px;
  height: 90px;
}
img {
  width: 90px;
  height: 90px;
  transform: translate3d(0, 0, 50px)
}
.bar {
  position: absolute;
  top: -10px;
  width: 90px;
  height: 10px;
  z-index: -1;
  background-color: yellow;
  transform: translate3d(0, 0, 25px)
}
#blue img {
  background-color: blue;
}
#orange img {
  background-color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
<div id="container">
  <div id="blue" class="draggable">
    <div class="bar"></div>
    <img>
  </div>
  <div id="orange" class="draggable">
    <div class="bar"></div>
    <img>
  </div>
</div>
T J
  • 42,762
  • 13
  • 83
  • 138
  • That looks really good! I will try to integrate this and get back to you. – RedShift Feb 18 '16 at 09:47
  • It works but now I tried adding in rotation and I broke it :-(. You can see it here: https://jsfiddle.net/rjfeeu8b/1/ From what I've been reading, the rotation creates a new stacking context. But .container already has transform-style: preserve-3d, which is supposed to make the childs work on the stacking context of the .container (as far as I can tell). (PS still rewarded as this wasn't part of my original question) – RedShift Feb 18 '16 at 22:20
  • @RedShift Hmmm... Unfortunately if we have 2 different stacking contexts, we can only entirely position them using `z-index`, we can't have just one element jump out of its context and go below another element in a different context... So what I did is, instead of applying rotation to entire `.draggable`, I applied it separately to `.bar` and `` : https://jsfiddle.net/rjfeeu8b/2/ so that they all have their on contexts... we have to tweak the positioning of `.bar` so that it looks sticking to the `` but maybe this works for you – T J Feb 19 '16 at 04:37
  • @RedShift oh, I forgot to mention that you should stop using inline `style=""` it's not a good practice... see this http://stackoverflow.com/a/2612494/2333214 – T J Feb 19 '16 at 04:43
0

Maybe you are looking for something like this: https://jsfiddle.net/rrx3zpdp/ As far I understanded you would like the background to stay back and not move with the elements which are draggable. P.S. if you like you can change the background width

I delete the both background colors from here:

<div style="transform-style: preserve-3d">

  <div style="width: 90px; height: 90px;" id="blue" class="draggable">
    <div style="width: 90px; height: 10px; ***background-color: yellow;*** position: absolute; top: -10px; transform: translate3d(0, 0, 25px)"></div>
    <img style="background-color: blue; width: 90px; height: 90px; transform: translate3d(0, 0, 50px)">
  </div>
  <div style="width: 90px; height: 90px;" id="orange" class="draggable">
    <div style="width: 90px; height: 10px; ***background-color: yellow;*** position: absolute; top: -10px; transform: translate3d(0, 0, 25px)"></div>
    <img style="background-color: orange; width: 90px; height: 90px; transform: translate3d(0, 0, 50px)">
  </div>

</div>

And added one here:

<div style="transform-style: preserve-3d; ***background-color: yellow;***">

Your mistake is because you are setting background to the same div that is draggable, just set it to other div like I did. Hope this helps you.

whitesova93
  • 100
  • 1
  • 9
  • Actually no, I want the boxes to be draggable on their own, as each box will have a different background with different edges around them. Those yellow edges need to be dragged along with the orange and blue boxes. – RedShift Feb 15 '16 at 11:50
  • You see the orange and blue boxes right? They each have a top edge, drawn in yellow. When those boxes are being dragged over each other, and it overlaps the yellow edges, the yellow edge being overlapped should disappear. If I could use z-index, what I would do is that the yellow edges have a z-index of 1, and the blue/orange boxes a z-index of 2. So whenever the blue/orange overlaps the yellow, the yellow disappears. – RedShift Feb 15 '16 at 12:00