JSFiddle - React, Tailwind, and code Playground

HTML

<div class="scene" style="perspective: 1000px; width: 100%; height: 100%">

  <!-- Apply opacity to the whole car: -->
  <div class="car" style="width: 300px; height: 200px; transform: translate3d(100px, 100px, 0px) rotateY(140deg) rotateZ(-20deg)">
    <h2>Car!</h2>

    <div class="render-to-texture" style="perspective: 1000px; opacity: 0.4; transform: rotateZ(20deg) rotateY(0deg) rotateZ(-20deg)">
      <div class="wrap" style="transform: rotateZ(20deg) rotateY(0deg) rotateZ(-20deg)">
        <div class="frame" style="border: none">
          <div class="frontLeftFender camo" style="width: 80px; height: 40px; transform: translate3d(0px, 0px, 50px)"></div>
          <div class="frontRightFender camo" style="width: 80px; height: 40px; transform: translate3d(0px, 0px, -50px)"></div>
          <div class="hood camo" style="width: 80px; height: 100px; transform: rotateX(90deg) translate3d(0px, 0px, 50px)"></div>
          <div class="bumper" style="width: 100px; height: 40px; transform: rotateY(90deg) translate3d(0px, 0px, -50px)"></div>
          <div class="leftDoor camo" style="width: 130px; height: 80px; transform: translate3d(80px, -40px, 50px)"></div>
          <div class="rightDoor camo" style="width: 130px; height: 80px; transform: translate3d(80px, -40px, -50px)"></div>
          <div class="roof camo" style="width: 130px; height: 100px; transform: rotateX(90deg) translate3d(80px, 0px, 90px)"></div>
          <div class="windshield" style="width: 100px; height: 40px; transform: rotateY(90deg) translate3d(0px, -40px, 30px)"></div>
          <div class="hatch camo" style="width: 80px; height: 100px; transform: rotateX(90deg) rotateY(90deg) translate3d(-50px, 0px, 170px)"></div>
          <div class="underside" style="width: 210px; height: 100px; transform: rotateX(90deg) translate3d(0px, 0px, 10px)"></div>
        </div>

        <div class="wheel" style="border: none; transform: translate3d(20px, 24px, -50px)">
          <div class="wheelRotation"...

CSS

.car {
  border: 5px solid red;
}

      html, body, .scene {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }

      * {
        box-sizing: border-box;
      }
      
      .scene {
        position: relative;
      }

      .scene div {
        position: absolute;
        transform-style: preserve-3d;
        transform-origin: center center;

        /*default size*/
        width: 10px;
        height: 10px;
      }

      .wheelSide {
        background-image: url("http://www.freeiconspng.com/uploads/car-tire-png-see-tire-details-add-to-my-car-8.png");
        background-size: 28px;
      }

      .wheelOuter {
        background-color: black;
      }

      .camo {
        background-image: url("http://blog.spoongraphics.co.uk/wp-content/uploads/2010/camo-patterns/Urban-Camo.jpg");
        background-size: 200px;
        background-repeat: repeat;
      }

      .bumper {
        background-image: url("http://www.wranglerforum.com/attachment.php?attachmentid=18928&d=1273472303");
        background-size: 168px;
        background-position: center center;
      }

      .underside {
        background-image: url("http://media.caranddriver.com/images/11q2/398067/2012-honda-civic-hybrid-technical-illustration-for-aero-under-body-panels-photo-398255-s-1280x782.jpg");
        background-size: 288px;
        background-position: center center;
      }

JavaScript

// rotate wheels
      let wheels = document.querySelectorAll('.wheelRotation')
      requestAnimationFrame(function loop() {
        wheels.forEach(wheel => {
          let zRot = getRotation(wheel, 'z')
          setRotation(wheel, 'z', zRot-6)
        })

        requestAnimationFrame(loop)
      })

      // rotate car
      let rtt = document.querySelector('.render-to-texture')
      let rttWrap = document.querySelector('.render-to-texture > .wrap')
      let car = document.querySelector('.car')
      requestAnimationFrame(function loop() {
        let yRot = getRotation(car, 'y')
        setRotation(car, 'y', yRot+1)
        setRotation(rtt, 'y', -(yRot+1))
        setRotation(rttWrap, 'y', (yRot+1))

        requestAnimationFrame(loop)
      })

      function getRotation(el, axis) {
        axis = (axis).toUpperCase()
        let transformProp = el.style.transform
        let yRot = parseInt(transformProp.substr(transformProp.indexOf('rotate'+axis)).split('(')[1])
        return (yRot).toString() == "NaN" ? 0 : yRot
      }

      // there's probably a better way.
      function setRotation(el, axis, value) {
        axis = axis.toUpperCase()
        let transformProp = el.style.transform

        let halves = transformProp.split('rotate'+axis)
        let firstHalf = halves[0]
        let secondHalf = halves[1]

        if (halves.length == 1) {
          el.style.transform += `rotate${axis}(${value}deg)`
          return
        }

        let secondHalfParts = secondHalf.split(')')
        secondHalfParts[0] = `(${value}deg`
        secondHalf = secondHalfParts.join(')')

        el.style.transform = `${firstHalf}rotate${axis}${secondHalf}`
      }