So I’ve got a really simple initial version of a 3d box which I needed to refactor to accommodate various ways it will need to work moving forward. This involved some general DOM changes and I am having a heck of a time with getting my perspective & transform origin etc tweaked back for the behavior I want.
I know the culprit is between the transform/perspective but I can’t see where apparently.
A quick visualization of my issue (A=NO, B=YES PLEASE):
Regardless of what I do I can’t seem to get the perspective and the transform origin on A
to match the original behavior of B
and would really appreciate a pair of eyes for my out of practice self but I’ve added code examples of both instances to both below.
Notice B
keeps its antenna more or less vertical while pivoting on a nice transform origin?
I would like to get back this with A
code instead, for your review first: A
// See how it looks like transform origin is like back center and the perspective makes the back end look fatter than on the other?
@charset "UTF-8";
:root {
--info: #00739D;
--accent: rgba(0,0,0,.05);
--accent2: rgba(0,0,0,.01);
--background: #fff;
--foreground: #000;
--foreground-inactive: #777;
--border: rgba(0,0,0,.123);
--port-bg: rgba(0,0,0,.3);
}
*, *:before, *:after {
background: none;
position: relative;
padding: 0;
border: 0;
margin: 0;
outline: 0;
box-shadow: none;
}
body {
overflow: hidden;
background-color: var(--background);
font-family: Arial;
font-weight: 400;
perspective: 1200px;
}
@keyframes smoothEntry {
to {
opacity: 1;
transform: scale(1);
}
}
.container {
height: 90vh;
display: flex;
align-items: center;
justify-content: center;
transform: scale(0.7);
opacity: 0;
transition: transform 0.5s linear, opacity 0.5s linear;
animation: smoothEntry 1s linear forwards;
}
#the-stage {
position: absolute;
width: 25rem;
height: 6.25rem;
}
#the-device {
position: absolute;
width: 100%;
height: 100%;
transform: translateZ(-100px);
transition: transform 0.5s linear;
transform-style: preserve-3d;
transform-origin: bottom center;
}
.idleZDisplay {
animation: idleZDisplay 5s linear alternate infinite;
}
.idleZDisplay:hover {
/* animation-play-state: paused; */
}
#the-device > div {
position: absolute;
}
.top, .right, .bottom, .left, .front {
border: var(--accent) 1px solid;
/* backface-visibility: hidden; */
}
.front {
position: relative;
background-color: var(--accent);
transform: rotateY(0deg) translateZ(125px);
}
.front:after {
position: absolute;
left: 5rem;
content: '';
display: block;
height: 10rem;
width: 1rem;
background-color: red;
transform: translateY(-100%);
}
.back {
background-color: var(--accent2);
transform: rotateX(180deg) translateZ(125px);
}
.front,
.back {
width: 25rem;
/**********************/
height: 6.25rem;
}
.left {
transform: rotateY(-90deg) translateZ(275px);
}
.right {
transform: rotateY(90deg) translateZ(125px);
}
.left,
.right {
width: 15.625rem;
height: 6.25rem;
left: 9.375rem;
background-color: var(--accent);
}
.top {
background-color: var(--accent);
transform: rotateX(90deg) translateZ(125px);
}
.bottom {
background-color: var(--accent);
transform: rotateX(-90deg) translateZ(-25px);
}
.top,
.bottom {
width: 400px;
height: 250px;
top: 0;
}
@keyframes idleZDisplay {
from {
transform: rotateY(-30deg) rotateX(-7deg);
}
to {
transform: rotateY(30deg) rotateX(-7deg);
}
}
h1 {
position: fixed;
top: 1rem;
left: 1rem;
font-size: 1.1rem;
}
<h1>
A: What to fix
</h1>
<div class="container">
<div id="the-stage">
<div id="the-device" class="idleZDisplay">
<div class="front"></div>
<div class="back"></div>
<div class="left"></div>
<div class="right"></div>
<div class="top"></div>
<div class="bottom"></div>
</div>
</div>
</div>
************* You’ll notice pretty quickly doesn’t have the more pleasing perspective behavior as: B
// look at the nice pretty much consistently perpendicular antenna that stays nice and vertical with the perspective bottom center and the behavior appears smoother?
.box {
width: 520px;
height: 100px;
position: relative;
animation: spin 8s linear infinite alternate;
}
.back {
width: 520px;
height: 100px;
position: absolute;
transform: rotateY(180deg) translateZ(180px);
}
.front {
width: 520px;
height: 100px;
position: absolute;
transform: rotateY(180deg) translateZ(-180px) rotateY(180deg);
padding-left: 72px;
}
.front:before {
position: absolute;
content: '';
display: block;
height: 10rem;
width: 1rem;
background-color: green;
transform: translateY(-100%);
}
.right {
width: 360px;
height: 100px;
left: 40px;
transform: rotateY(90deg) translateZ(300px);
}
.left {
width: 360px;
height: 100px;
left: 120px;
transform: rotateY(-90deg) translateZ(300px);
}
.top {
width: 520px;
height: 360px;
top: 0px;
transform: rotateX(-90deg) translateZ(-180px);
}
.floor {
width: 520px;
height: 360px;
top: 0px;
transform: rotateX(-90deg) translateZ(-80px);
}
.surface {
border: 1px solid #777;
border-radius: 2px;
position: absolute;
background-color: rgba(230, 230, 230, .05);
}
.scene {
margin: auto;
width: 520px;
height: 100px;
transform: rotateX(-4deg);
}
@keyframes spin {
from {
transform: rotateY(30deg);
animation-timing-function: ease-in-out;
}
to {
transform: rotateY(-30deg);
}
}
body {
background-color: #323232;
padding-top: 260px;
transform: scale(.7);
perspective: 1200px;
font-family: sans-serif;
color: white;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
transform-style: preserve-3d;
}
h1 {
position: fixed;
top: 1rem;
left: 1rem;
}
<h1>
B (what I want)
</h1>
<div class="scene">
<div class="box">
<div class="surface back"></div>
<div class="surface front"></div>
<div class="surface right"></div>
<div class="surface left"></div>
<div class="surface top"></div>
<div class="surface floor"></div>
</div>
</div>