Zorak Zorak - 2 months ago 14
CSS Question

Proper translateZ cooperation with rotate

I am trying to create some fancy 3D interface, but I found, that the behavior of rotating 3d space is not what I expect.

The problem is:
the green-bordered square (in snippet) is container, which whole should rotate.
It has some perspective needed for the effect.

Blue and black squares are 2D layers in 3D space.
By rotating container around Y axis should rotate all its content, however, by given perspective, while black and blue have both different Z-axis, the viewer should see, like the position of them is changing.

For demonstration purposes, I have created very simple paper model showing the perspective. Note the black marks on the back paper and the angle of shadow which demonstrates the angle.

enter image description here

The problem is, that CSS does not handle the rotation over theese translated elements and all is flat, the objects does not move between each other, even if translated (tried both

translateY
and
translate3d
), tried
z-index
...

Now. I know, that I can define CSS classes matching layers, add them to my elements and by JS dynamically changing their translation of different axis to create this effect.

However I would like to find a solution of correct handling of 3D space rather than overriding it like this.

So - is there some CSS way, how to make it work like it should? Am I missing some CSS translate property or something?

See the CSS behavior and code on snippet bellow.

Thank you.



$( document ).on( "mousemove", function( event ) {
var dw = $(document).width();
var dh = $(document).height();

var transformz = -5+ (event.pageX*(10/dw));
var transformbgz = -1+ (event.pageX*(2/dw));
var transformdirz = -1+ (event.pageX*(2/dw));
var transformdiry = -1+ (event.pageY*(2/dh));

var transformpy = -7+ (event.pageY*(14/dh));
var transformbgpy = -1+ (event.pageY*(2/dh));

$( "#divbg" ).css("top",transformbgpy-4+"%");
$( "#divbg" ).css("left",transformbgz-10+"%");
// $( "#div2" ).css("transform","rotate3d("+transformdiry+","+transformdirz+",0,"+Math.abs(transformz)+"deg)");
$( "#div2" ).css("transform","rotateY("+transformz+"deg) rotateX("+transformpy+"deg)");
/* $( "#div3" ).css("transform","translateZ(-20px) rotateY("+transformz+"deg) rotateX("+transformpy+"deg)");*/



});

* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-moz-osx-font-smoothing: grayscale;
box-shadow: 0px 0px 2px 0px rgba(0,0,0,0.55);
}

body{margin:0; padding:0; overflow:hidden;}
#div1 {
position: absolute;
top:0;
left:0;
height: 100%;
width:100%;
border: 1px solid black;
-webkit-perspective: 300px; /* Chrome, Safari, Opera */
perspective: 300px;
overflow:hidden;
}
#divbg{position:absolute; top:0; left:-20%; width:120%; height:120%;
background: url(https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-550412.jpg) 0% 0;
background-repeat:no-repeat;

}


#div2 {
width:300px;
height:150px;
position: absolute;
top:10%;
left:30%;
border:1px solid #0F0;



}



#div3-black{
position:absolute; top:70px; left:130px;
width:100%;
height:40px;
background:black;
border:1px solid #888;
color:aqua;
font-size:40px;
text-shadow: 2px 2px 0px rgba(150, 150, 150, 1);
z-index:1;
transform:translate3d(0px, 0px, -30px);




}


#div3-blue{
position:absolute; top:30px; left:150px;
color:yellow;
background:aqua;
position:absolute;
top:60px;
left:140px;
width:60px;
height:40px;
font-size:40px;
text-shadow: 2px 2px 0px rgba(150, 150, 150, 1);
z-index:2;

transform:translate3d(0px,0px,50px);

}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1">
<div id="divbg"></div>
<div id="div2">
<div id="div3-black"></div>

<div id="div3-blue">

</div>


</div>
</div>




Answer Source

All that you are missing is

transform-style: preserve-3d;

I have also changed somewhat your snippet because I had problems with the image linked

$(document).on("mousemove", function(event) {
  var dw = $(document).width();
  var dh = $(document).height();

  var transformz = -5 + (event.pageX * (10 / dw));
  var transformbgz = -1 + (event.pageX * (2 / dw));
  var transformdirz = -1 + (event.pageX * (2 / dw));
  var transformdiry = -1 + (event.pageY * (2 / dh));

  var transformpy = -7 + (event.pageY * (14 / dh));
  var transformbgpy = -1 + (event.pageY * (2 / dh));

  $("#divbg").css("top", transformbgpy - 4 + "%");
  $("#divbg").css("left", transformbgz - 10 + "%");
  //  $( "#div2" ).css("transform","rotate3d("+transformdiry+","+transformdirz+",0,"+Math.abs(transformz)+"deg)");
  $("#div2").css("transform", "rotateY(" + transformz + "deg) rotateX(" + transformpy + "deg)");
  /*    $( "#div3" ).css("transform","translateZ(-20px) rotateY("+transformz+"deg) rotateX("+transformpy+"deg)");*/



});
* {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -moz-osx-font-smoothing: grayscale;
  box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.55);
  transform-style: preserve-3d;
}

body, html {
  margin: 0;
  padding: 0;
  overflow: hidden;
  height: 100%;
}

#div1 {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  border: 1px solid black;
  -webkit-perspective: 300px;
  /* Chrome, Safari, Opera  */
  perspective: 300px;
  overflow: hidden;
}

#divbg {
  position: absolute;
  top: 0;
  left: -20%;
  width: 120%;
  height: 120%;
  background-image: linear-gradient(45deg, green, blue);
  background-repeat: no-repeat;
}

#div2 {
  width: 300px;
  height: 150px;
  position: absolute;
  top: 10%;
  left: 30%;
  border: 1px solid #0F0;
}

#div3-black {
  position: absolute;
  top: 70px;
  left: 130px;
  width: 100%;
  height: 40px;
  background: black;
  border: 1px solid #888;
  color: aqua;
  font-size: 40px;
  text-shadow: 2px 2px 0px rgba(150, 150, 150, 1);
  z-index: 1;
  transform: translate3d(0px, 0px, -30px);
}

#div3-blue {
  position: absolute;
  top: 30px;
  left: 150px;
  color: yellow;
  background: aqua;
  position: absolute;
  top: 60px;
  left: 140px;
  width: 60px;
  height: 40px;
  font-size: 40px;
  text-shadow: 2px 2px 0px rgba(150, 150, 150, 1);
  z-index: 2;
  transform: translate3d(0px, 0px, 50px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1">
  <div id="divbg"></div>
  <div id="div2">
    <div id="div3-black"></div>

    <div id="div3-blue">

    </div>


  </div>
</div>