1

I have this code of an animating, rotating cube made with CSS. The Code works on Chrome and Firefox, also on iOS Safari it's working but not on Safari OSX. On Safari only two sides are rendered...

Is there any known issue with Safari rendering 3D Rotations? I also added -webkit fragments to code but it did not help either...

Is this enough details?

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    } 

    body {
    min-height: 100vh;
    background: #222;
    overflow: hidden;
    }

    .cube {
    position: absolute;
    top: 35%;
    left: 50%;
    transform-origin: 50% 100%;
    -ms-transform-origin: 50% 100%;
    -webkit-transform-origin: 50% 100%;
    -moz-transform-origin: 50% 100%;
    -o-transform-origin: 50% 100%;
    transform-style: preserve-3d;
    -ms-transform-style: preserve-3d;
    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    -o-transform-style: preserve-3d;
    perspective: 5000px;
    animation: rotate 10s linear infinite;
    }

    @keyframes rotate {
    0% {
    transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -ms-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -webkit-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -moz-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -o-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    }
    50% {
    transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -ms-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -webkit-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -moz-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -o-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    }
    100% {
    transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -ms-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -webkit-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -moz-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -o-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    }
    }

    .cube .side {
    width: 200px;
    height: 200px;
    background: red;
    position: absolute;
    }

    .cube .side.back {
    transform: translateZ(-200px);
      -ms-transform: translateZ(-200px);
      -webkit-transform: translateZ(-200px);
          -moz-transform: translateZ(-200px);
      -o-transform: translateZ(-200px);
      }

    .cube .side.right {
      transform-origin: 100% 50%;
      -ms-transform-origin: 100% 50%;
      -webkit-transform-origin: 100% 50%;
      -moz-transform-origin: 100% 50%;
      -o-transform-origin: 100% 50%;
      transform: rotateY(-90deg);
      -ms-transform: rotateY(-90deg);
      -webkit-transform: rotateY(-90deg);
      -moz-transform: rotateY(-90deg);
      -o-transform: rotateY(-90deg);
    }

    .cube .side.left {
      -ms-transform-origin: 0% 50%;
      -webkit-transform-origin: 0% 50%;
      -moz-transform-origin: 0% 50%;
      -o-transform-origin: 0% 50%;
      transform-origin: 0% 50%;
      transform: rotateY(90deg);
      -ms-transform: rotateY(90deg);
      -webkit-transform: rotateY(90deg);
      -moz-transform: rotateY(90deg);
      -o-transform: rotateY(90deg);
    }

    .cube .side.top {
      -ms-transform-origin: 50% 0%;
      -webkit-transform-origin: 50% 0%;
      -moz-transform-origin: 50% 0%;
      -o-transform-origin: 50% 0%;
      transform-origin: 50% 0%;
      -ms-transform: rotateX(-90deg);
      -webkit-transform: rotateX(-90deg);
      -moz-transform: rotateX(-90deg);
      -o-transform: rotateX(-90deg);
      transform: rotateX(-90deg);
    }

    .cube .side.bottom {
      -ms-transform-origin: 50% 100%;
      -webkit-transform-origin: 50% 100%;
      -moz-transform-origin: 50% 100%;
      -o-transform-origin: 50% 100%;
      transform-origin: 50% 100%;
      -ms-transform: rotateX(90deg);
      -webkit-transform: rotateX(90deg);
      -moz-transform: rotateX(90deg);
      -o-transform: rotateX(90deg);
      transform: rotateX(90deg);
    }* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    } 

    body {
    min-height: 100vh;
    background: #222;
    overflow: hidden;
    }

    .cube {
    position: absolute;
    top: 35%;
    left: 50%;
    transform-origin: 50% 100%;
    -ms-transform-origin: 50% 100%;
    -webkit-transform-origin: 50% 100%;
    -moz-transform-origin: 50% 100%;
    -o-transform-origin: 50% 100%;
    transform-style: preserve-3d;
    -ms-transform-style: preserve-3d;
    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    -o-transform-style: preserve-3d;
    perspective: 5000px;
    animation: rotate 10s linear infinite;
    }

    @keyframes rotate {
    0% {
    transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -ms-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -webkit-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -moz-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    -o-transform: translate(-50%, -50%) rotateX(0) rotateY(0);
    }
    50% {
    transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -ms-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -webkit-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -moz-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    -o-transform: translate(-50%, -50%) rotateX(180deg) rotateY(180deg);
    }
    100% {
    transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -ms-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -webkit-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -moz-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    -o-transform: translate(-50%, -50%) rotateX(360deg) rotateY(360deg);
    }
    }

    .cube .side {
    width: 200px;
    height: 200px;
    background: repeating-linear-gradient( to right, transparent 1% 9%, #0f0 9% 10% ), repeating-linear-gradient(to top, transparent 1% 9%, #0f0 9% 10%);
    background: red;
    position: absolute;
    }

    .cube .side.back {
    transform: translateZ(-200px);
      -ms-transform: translateZ(-200px);
      -webkit-transform: translateZ(-200px);
          -moz-transform: translateZ(-200px);
      -o-transform: translateZ(-200px);
      }

    .cube .side.right {
      transform-origin: 100% 50%;
      -ms-transform-origin: 100% 50%;
      -webkit-transform-origin: 100% 50%;
      -moz-transform-origin: 100% 50%;
      -o-transform-origin: 100% 50%;
      transform: rotateY(-90deg);
      -ms-transform: rotateY(-90deg);
      -webkit-transform: rotateY(-90deg);
      -moz-transform: rotateY(-90deg);
      -o-transform: rotateY(-90deg);
    }

    .cube .side.left {
      -ms-transform-origin: 0% 50%;
      -webkit-transform-origin: 0% 50%;
      -moz-transform-origin: 0% 50%;
      -o-transform-origin: 0% 50%;
      transform-origin: 0% 50%;
      transform: rotateY(90deg);
      -ms-transform: rotateY(90deg);
      -webkit-transform: rotateY(90deg);
      -moz-transform: rotateY(90deg);
      -o-transform: rotateY(90deg);
    }

    .cube .side.top {
      -ms-transform-origin: 50% 0%;
      -webkit-transform-origin: 50% 0%;
      -moz-transform-origin: 50% 0%;
      -o-transform-origin: 50% 0%;
      transform-origin: 50% 0%;
      -ms-transform: rotateX(-90deg);
      -webkit-transform: rotateX(-90deg);
      -moz-transform: rotateX(-90deg);
      -o-transform: rotateX(-90deg);
      transform: rotateX(-90deg);
    }

    .cube .side.bottom {
      -ms-transform-origin: 50% 100%;
      -webkit-transform-origin: 50% 100%;
      -moz-transform-origin: 50% 100%;
      -o-transform-origin: 50% 100%;
      transform-origin: 50% 100%;
      -ms-transform: rotateX(90deg);
      -webkit-transform: rotateX(90deg);
      -moz-transform: rotateX(90deg);
      -o-transform: rotateX(90deg);
      transform: rotateX(90deg);
    }
<div class="cube">
        <div class="side front"></div>
        <div class="side back"></div>
        <div class="side right"></div>
        <div class="side left"></div>
        <div class="side top"></div>
        <div class="side bottom"></div>
 </div>

2
  • 1
    Works just fine in Safari (18.4) on my Mac (15.4). Here is a video showing Safari rendering on the left, Chrome on the right. Commented Apr 7 at 1:27
  • wow.. I have OSX 13.7.5 (last working for my mb pro) and safari 18.4 look how it's there: ibb.co/ym1Q1jKQ Commented Apr 7 at 8:07

1 Answer 1

0

First off, that code is horrendous.

Ditch the prefixes, they haven't been needed for over a decade at least. And IE/ pre-Chromium Edge never ever needed the -ms- prefix for CSS 3D transforms. IE9 didn't support 3D transforms at all and IE10 supported them unprefixed (though it didn't support preserve-3d at all and we had to resort to weird hacks for animating cubes in 3D in IE10). Even if you use prefixes, always put the unprefixed version last, after all the prefixed ones.

Prefixes aside, the rest of the code is not just outdated, but terribly inefficient.

Your cube should live inside a .scene. For simplicity, I'm using the body here, but it can be any other element. This scene gets a perspective (or not, if you want an isometric result). You don't set perspective on the cube itself, you set it on the parent .scene.

Any cube has 6 faces, so 6 .face elements. These get grouped in 3 pairs of two faces. Each pair is perpendicular onto one of the three axes of the cube's system of coordinates. We get them along the axes we want by rotating each pair around an axis.

/* 3D rotation vector; this is rotation around 2nd (y axis) */
.face { --v: 0, 1, 0 }
/* first two faces rotate around 3rd (z axis) */
.face:nth-child(-n + 2) { --v: 0, 0, 1 }
/* last two faces rotate around 1st (x axis) */
.face:nth-child(n + 5) { --v: 1, 0, 0 }

The two faces of each pair look in opposite directions (different sign depending on parity).

.face { --s: -1 }
.face:nth-child(2n) { --s: 1 } /* even faces (2nd, 4th, 6th) */

Then you use these two variables to set a transform on the .face elements to put them all into place on the cube:

transform: 
    rotate3d(var(--v), 90deg) 
    scale3d(1, 1, var(--s)) 
    translatez(4em)

Here's the simple wireframe cube in 3D - this is all the CSS that's needed for it:

html, body { display: grid }

html { min-height: 100% }

.scene { perspective: 25em }

.cube {
  display: grid; /* to allow for stacking faces */
  place-self: center;
  transform-style: preserve-3d; /* allow 3D transforms on children */
  transform: rotate3d(.5, .4, .3, 30deg)
}

.face {
  --v: 0, 1, 0; /* rotation vector */
  --s: -1; /* facing negative direction of axis */
  --r: 4em; /* cube inradius = half edge length */
  grid-area: 1/ 1; /* stack face elements all on top of each other */
  padding: var(--r); /* size it in 1 declaration */
  transform: 
    rotate3d(var(--v), 90deg) /* position faces perpendicular to axes */
    scale3d(1, 1, var(--s)) /* flip half the faces so they look to - */
    translatez(var(--r)); /* move forward on the cube */
  --stops: #0f0 0 2px, #0000 0 10%;
  background: 
    repeating-linear-gradient(90deg, var(--stops)) -1px, 
    repeating-linear-gradient(var(--stops)) 0 -1px;
  
  &:nth-child(-n + 2) { --v: 0, 0, 1 }
  &:nth-child(n + 5) { --v: 1, 0, 0 }
  
  &:nth-child(2n) { --s: 1 }
}
<body class='scene'>
  <div class='cube'>
    <div class='face'></div>
    <div class='face'></div>
    <div class='face'></div>
    <div class='face'></div>
    <div class='face'></div>
    <div class='face'></div>
  </div>
</body>

Your cube rotation keyframes are then reduced to:

@keyframes rotate {
    to { transform: rotateX(1turn) rotateY(1turn) }
}

Don't forget to remove the placeholder rotate3d() transform on the cube when adding the animation and to add the transform-origin.

Sign up to request clarification or add additional context in comments.

3 Comments

thank you for your reply. I appreciate. I did the prefixes and all that weird stuff because I thought safari will then render it. your cube has the same problem then mine: only the two sides of it are shown. I am on safari 18.4 on MacOS 13.7.5. I figured out, that this OS has a particular problem, to render 3d transform things, with its webkit version. no solution will kill the problem. its the webkit... sadly to say this.
@SilverStar069 Might be worth filing a bug then bugs.webkit.org/enter_bug.cgi CSS 3D transforms have been supported in Safari for 15 years already, so this must be a bug. I don't have any Apple device to test, I can only test Safari 18.4 via Epiphany Technology Preview on Linux and all looks fine there.
its not a bug in webkit particularly it's a bug in OSX´s build of webkit in its old OS. The bug is fixed with the newer version of OSX but the old OS will not have an update by apple.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.