4

When I hover over the image, the transition works fine except for the fact that the front image (that of a rotating lock) only translates 20px in Z direction when the mouse is removed from that image. I want the rotating lock image to be 20px in front always.

Also, why does the rotating lock image becomes slightly smaller just after I hover the image?

body {
  margin:0;
  width: 100%;
  height: 100%;
}

.maincircle {
  width: 200px;
  height: 200px;
  position: relative;
  margin-left: 200px;
  margin-top: 10px;
  border-radius: 50%;
  border: 1px solid black;
  perspective: 600px;
  transform-style: preserve-3d; 
}
.door {
  background-color: gray;
  border-radius: 100%;
  height: 200px;
  margin: 0;
  position: relative;
  width: 200px;
  transition: .5s linear;
  transform-style: preserve-3d;
  transform-origin: 0 50%;
  transition: transform 2s 0.5s;
}

.door:before {
  background-color: gray;
  background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
  border-radius: 100%;
  content: '';
  height: 200px;
  left: 0;
  position: absolute;
  top: 0;
  width: 200px;
  transform: translateZ(-5px);
}

.door:after {
  background-color: gray;
  background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
  bottom: 0;
  content: '';
  left: 100px;
  position: absolute;
  top: 0;
  width: 5px;
  z-index: -10;
  transform: rotateY(-90deg);
  transform-origin: 100% 50%;
}

.maincircle:hover .door {
  transform: rotateY(-110deg);
}

.maincircle:hover .locker {
  transform: rotate(90deg);
}

.locker {
  background-image: url("https://irp-cdn.multiscreensite.com/806e9122/dms3rep/multi/tablet/CombinationLock-1000x1000.png"); 
  position: absolute;
  top: 25px;
  left: 25px;
  background-size: 100% 100%;
  border-radius: 100%;
  width: 150px;
  height: 150px;
  transform: translateZ(20px);
  transition: transform 0.5s;
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="maincircle">
      <div class="door">
        <div class="locker"></div>
      </div>
    </div>
  </body>
</html>
Harry
  • 87,580
  • 25
  • 202
  • 214
Dhruv Chadha
  • 1,161
  • 2
  • 11
  • 33

1 Answers1

4

Question 1: (I want the rotating lock image to be 20px in front always)

It is because transform settings are not additive in nature. When you specify the transform during the :hover as give below,

.maincircle:hover .locker {
  transform: rotate(90deg);
}

it overwrites the transform: translateZ(20px) that is specified within the default state (which is the setting under .locker selector) and so the translation in Z-axis is lost whenever the element is being hovered. It gets applied back only when the :hover is off (that is, the element returns to default state as specified in .locker selector).

In order to always have the translation in Z-axis, translateZ(20px) should be added to the transform stack within :hover selector also like below:

.maincircle:hover .locker {
  transform: rotate(90deg) translateZ(20px);
}

body {
  margin:0;
  width: 100%;
  height: 100%;
}

.maincircle {
  width: 200px;
  height: 200px;
  position: relative;
  margin-left: 200px;
  margin-top: 10px;
  border-radius: 50%;
  border: 1px solid black;
  perspective: 600px;
  transform-style: preserve-3d; 
}
.door {
  background-color: gray;
  border-radius: 100%;
  height: 200px;
  margin: 0;
  position: relative;
  width: 200px;
  transition: .5s linear;
  transform-style: preserve-3d;
  transform-origin: 0 50%;
  transition: transform 2s 0.5s;
}

.door:before {
  background-color: gray;
  background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
  border-radius: 100%;
  content: '';
  height: 200px;
  left: 0;
  position: absolute;
  top: 0;
  width: 200px;
  transform: translateZ(-5px);
}

.door:after {
  background-color: gray;
  background-image: linear-gradient(hsla(0,0%,100%,.25), hsla(0,0%,0%,.25));
  bottom: 0;
  content: '';
  left: 100px;
  position: absolute;
  top: 0;
  width: 5px;
  z-index: -10;
  transform: rotateY(-90deg);
  transform-origin: 100% 50%;
}

.maincircle:hover .door {
  transform: rotateY(-110deg);
}

.maincircle:hover .locker {
  transform: rotate(90deg) translateZ(20px);
}

.locker {
  background-image: url("https://irp-cdn.multiscreensite.com/806e9122/dms3rep/multi/tablet/CombinationLock-1000x1000.png"); 
  position: absolute;
  top: 25px;
  left: 25px;
  background-size: 100% 100%;
  border-radius: 100%;
  width: 150px;
  height: 150px;
  transform: translateZ(20px);
  transition: transform 0.5s;
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="maincircle">
      <div class="door">
        <div class="locker"></div>
      </div>
    </div>
  </body>
</html>

Question 2: (Why does the rotating lock image becomes slightly smaller just after I hover the image?)

I am putting this at the last (even below the code) because I know by now you'd have guessed why it became smaller. It becomes smaller because the element is losing the translateZ(20px) and so it is going farther away from your eye. Any object that goes farther away from the eye will look smaller.

Harry
  • 87,580
  • 25
  • 202
  • 214
  • 2 small questions- 1 ) Does an image automatically scale itself when I translateZ it? 2) Why do I need to add content : ' ' ; in .door:before and .door:after? – Dhruv Chadha May 29 '16 at 10:38
  • 1
    (1) I wouldn't call it `scale` as it may not be the correct word. It is more like perception or illusion. When the monitor is 1 feet in front of you it would *look* larger than say if it was 2 feet in front of you. (2) It is mandatory because pseudo-elements are actually generated only when `content` is specified. – Harry May 29 '16 at 10:41
  • @DhruvChadha: You'll find more details about why pseudo-elements require content in this thread - http://stackoverflow.com/questions/17067918/why-do-pseudo-elements-require-a-content-property – Harry May 29 '16 at 10:45
  • I added a .locker:before class to make a small green circle appear 10px behind the locker such that it is midway between the door and rotating locker, however the green circle is not going back. Why is this happening? - check this : https://jsfiddle.net/srbwn10f/ – Dhruv Chadha May 29 '16 at 10:52
  • @DhruvChadha: Add `transform-style: preserve-3d` for the `.locker` element also like [here](https://jsfiddle.net/srbwn10f/1/). – Harry May 29 '16 at 10:55
  • But doesnt transform-style: preserve-3d work for all children once it is defined in a parent element? – Dhruv Chadha May 29 '16 at 10:57
  • 1
    I expected it too @DhruvChadha. But I had seen in a few other cases as well that it is mandatory to specify again on the parent element when it has a pseudo with 3D transform. (*Edit:* I just checked [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style) and it specifies this property is not inherited and so should be set on all but the leaf elements.) – Harry May 29 '16 at 10:59