Keep box-shadow direction consistent while rotating

本秂侑毒 提交于 2019-11-27 22:01:35

Keeping direction of an offset box-shadow consistent during rotation is simple with CSS transforms.
This approach relies on the fact that the transform origin is moved with the transforms. This means that when several transforms are set on the same element, the coordinate system of each transform changes according to the previous ones.

In the following example, the blue element is a pseudo element and the shadow is the div element:

div {
  width: 40px; height: 40px;
  margin: 40px;
  box-shadow: 0px 0px 10px 5px #000;
  animation: spinShadow 2s infinite;
  background-color: #000;
}
@keyframes spinShadow {
  to { transform: rotate(360deg); }
}
div:before {
  content: '';
  position: absolute;
  left:-5px; top:-5px;
  width: 50px; height: 50px;
  transform: rotate(0deg) translate(-10px, -10px) rotate(0deg);
  animation:inherit;
  animation-name: spinElt;
  background-color: #0bb;
}
@keyframes spinElt {
  to { transform: rotate(-360deg) translate(-10px, -10px) rotate(360deg); }
}
<div></div>

Explanation of the transition property on the pseudo element (See the following code snippet for an illustration of the steps):

transform: rotate(-360deg) translate(-10px, -10px) rotate(360deg)
  1. rotate(-360deg) counters the rotation of the parent to make the pseudo element static.
  2. translate(-10px, -10px) the pseudo element is translated to make the shadow offset
  3. rotate(360deg) the pseudo element is rotated in the same direction as parent

div {
  width: 40px; height: 40px;
  margin: 40px;
  box-shadow: 0px 0px 10px 5px #000;
  animation: spinShadow 2s infinite;
  background-color: #000;
}
@keyframes spinShadow {
  to { transform: rotate(360deg); }
}
div:before {
  content: '';
  position: absolute;
  left:-5px; top:-5px;
  width: 50px; height: 50px;
  animation:inherit;
  background-color: #0bb;
}
#first:before{
  transform: rotate(0deg);
  animation-name: first;
}  
@keyframes first {
  to { transform: rotate(-360deg); }
}
#second:before{
  transform: rotate(0deg) translate(-10px, -10px);
  animation-name: second;
}  
@keyframes second {
  to { transform: rotate(-360deg) translate(-10px, -10px); }
}
#complete:before{
  transform: rotate(0deg) translate(-10px, -10px) rotate(0deg);
  animation-name: complete;
}  
@keyframes complete {
  to { transform: rotate(-360deg) translate(-10px, -10px) rotate(360deg); }
}
<ol>
  <li>Counter rotate:<div id="first"></div></li>
  <li>Translate :<div id="second"></div></li>
  <li>Rotate:<div id="complete"></div></li>
<ol>

You could as well integrate box-shadow direction inside animation frames:

div {
  display: inline-block;
  margin: 1em ;
  height: 50px;
  width: 50px;
  box-shadow: 15px 15px 15px 5px gray;
  animation: rte 5s infinite linear;
}

.red {
  background: red
}

.green {
  background: green;
  animation-delay:2s;
}

.blue {
  background: blue;
  animation-delay:4s;
}

.bob {
  background: #b0b;
  animation-delay:6s;
}

.cyan {
  background: cyan;
  animation-delay:8s;
}

@keyframes rte {
  25% {
    box-shadow:  15px -15px 15px 5px gray;
  }
  50% {
      box-shadow:  -15px -15px 15px 5px gray;
  }
  75% {
    box-shadow:  -15px 15px 15px 5px gray;
  }
  100% {
    transform: rotate(360deg);
  }
}
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
<div class="bob"></div>
<div class="cyan"></div>

Inspired by the other answers I created my own answer as well: https://jsfiddle.net/zoxgbcrg/1/

.shadow {
  background-color: black !important;
  width: 40px;
  height: 40px;
  box-shadow: 0px 0px 10px 5px #000;
  margin-top: 35px;
  margin-left: 35px;
  position: absolute;
  z-index: -1;
}
<div class="box1 shadow"></div><div class="box1"></div>

The trick is also to create an additional <div> to handle the shadow. In my case it's not a :before but a real DOM element that is moved by margin.

Note: it seems that of today (31.01.2016) Firefox and Chrome have a subtile rendering difference. So for Firefox https://jsfiddle.net/zoxgbcrg/ is creating the desired result, for Chrome I suggest https://jsfiddle.net/zoxgbcrg/1/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!