Search code examples
htmlcss3dcss-transforms

Why is a CSS 3D rotation not happening around the center point?


I'm building out an aggregation of 3d cubes and trying to rotate the aggregated piece. For some reason it's not rotating along the center point.

When I just have an individual cube, it works as expected. When I join 3 cubes into a column, it works as expected. It's just when I join 3 columns into a "section" that the "section" doesn't rotate along the center point.

When the column and cube had this issue it was because I didn't set a proper height and width on them. Am I setting the wrong height and width for the '.section' element? If so, what should it be? An explanation on why my dimensions are wrong would be appreciated as well.

(Sorry for the astronomical code, but SO won't allow just a codepen and the problem doesn't happen with simplified code.)

    <div class="scene">
      <div class="section col-section">
        <div class="col col-back">
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
        </div>      
        <div class="col col-middle">
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
        </div>      
        <div class="col col-front">
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
          <div class="cube">
            <div class="cube__face cube__face--front">
              <div>front</div>
            </div>  
            <div class="cube__face cube__face--back">
              <div>back</div>
            </div>
            <div class="cube__face cube__face--right">
              <div>right</div>
            </div>
            <div class="cube__face cube__face--left">
              <div>left</div>
            </div>
            <div class="cube__face cube__face--top">
              <div>top</div>
            </div>
            <div class="cube__face cube__face--bottom">
              <div>bottom</div>
            </div>
          </div>
        </div>
      </div>
    </div>
      .scene {
        perspective: 600px;
      }

      .cube {
        width: 100px;
        height: 100px;
        position: relative;
      }

      .cube__face {
        position: absolute;
        width: 100px;
        height: 100px;
        color: white;
        font-size: 1.5rem;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .cube__face--front  {
        transform: rotateY(0deg) translateZ(50px);
        background-color: pink;
      }

      .cube__face--right {
        transform: rotateY(90deg) translateZ(50px);
        background-color: yellow;
      }

      .cube__face--back {
        transform: rotateY(180deg) translateZ(50px);
        background-color: green;
      }

      .cube__face--left {
        transform: rotateY(-90deg) translateZ(50px);
        background-color: blue;
      }

      .cube__face--top {
        transform: rotateX(90deg) translateZ(50px);
        background-color: orange;
      }

      .cube__face--bottom {
        transform: rotateX(-90deg) translateZ(50px);
        background-color: magenta;
      }

      .col {
        position: absolute;
        transform-style: preserve-3d;
        width: 100px;
        height: 300px;
      }

      .col .cube {
        position: absolute;
        top: 100px;
      }

      .col .cube:first-child {
        top: 0;
      }

      .col .cube:last-child {
        top: 200px;
      }

      .col-back {
        transform: translateZ(-200px);
      }

      .col-middle {
        transform: translateZ(-100px);
      }

      .section {
        transform-style: preserve-3d;
        backface-visibility: hidden;
        transform: rotateX(0deg);
        transition: all 1s linear;
      }

      .col-section {
        width: 100px;
        height: 100px;
      }

Solution

  • Ok, I was swimming in a sea of ignorance as to the fact that transform-origin accepts a 3rd value that corresponds to the z-axis. Basically, the default transform origin was correct for the x and y access, but I needed a custom one for the z-index to push it back a bit.

    transform-origin: 50px 150px -100px;