如何在一个元素上应用多个变换声明?

51

我有一个带有两个类的元素,其中一个称为“rotate”,将使元素旋转360度,另一个称为“doublesize”,将使元素的大小扩大2倍:

.rotate {
    transform: rotate(0deg);
}

.rotate:hover {
    transform: rotate(360deg);
}

.doublesize {
    transform: scale(1);
}

.doublesize:hover {
    transform: scale(2);
}

http://jsfiddle.net/Sbw8W/

我猜这个不起作用是因为类之间互相覆盖了transform属性吗?

我知道我可以很容易地在一个CSS规则中完成这个操作,例如:

.doublerotatesize {
    transform: scale(1) rotate(0deg);
}

.doublerotatesize:hover {
    transform: scale(2) rotate(360deg);
}

但是如果可能的话,我希望能够单独地应用每个类,而不影响其他类。

5个回答

56

我猜这不起作用是因为这些类互相覆盖了transform属性?

正确。这是级联工作方式的副作用所导致的不幸限制。

你将需要在一个单独的transform声明中指定这两个函数。你可以简单地将两个类选择器链接在一起,而不是创建一个新的组合变换类:

.doublesize.rotate {
    -webkit-transform: scale(1) rotate(0deg);
}

.doublesize.rotate:hover {
    -webkit-transform: scale(2) rotate(360deg);
}

...但正如你所看到的,问题在于transform属性而不是选择器本身。


这个问题预计在Transforms level 2中得以解决。在这个版本中,每个变换都已提升为独立的属性,这将允许你像声明任何其他CSS属性组合一样分别声明它们来简单地组合变换。这意味着你只需要这样做:

/* Note that rotate: 0deg and scale: 1 are omitted
   as they're the initial values */

.rotate:hover {
    rotate: 360deg;
}

.doublesize:hover {
    scale: 2;
}

利用层叠样式表的优势,而不是被其所限制。无需使用特定的类名或组合 CSS 规则。


2
我应该可以同时指定translateY和translateX而不会相互覆盖。 - Muhammad Umer
即使使用转换级别2,仍然无法通过2个不同的类应用相同的2个变换,这在某些情况下仍然是必要的。例如,您可能希望在一个类中水平变换,在另一个类中垂直变换。如果他们再分解一级(transformXtransformY等),那可能就足够了。 - trysis
@trysis:你说得对。似乎SVG变换和CSS级联根本不搭配 :( - BoltClock

20
使用CSS变量可以实现这种分离。思路是在元素内使用CSS变量链式多次变换,然后稍后单独更新每个变量:

div {
  width: 100px;
  height: 100px;
  display: inline-block;
  background-color: red;
  transform:
    /* I prepared 3 placeholder so we can chain 3 transformation later */
    var(--t1,) /* we need "nothing" as fallbak*/
    var(--t2,) 
    var(--t3,);
}

.transitionease {
  transition: all 1s ease;
}

.transitionease:hover {
  transition: all 3s ease;
}

.rotate {
  --t1: rotate(0deg);
}

.rotate:hover {
  --t1: rotate(360deg);
}

.doublesize {
  --t2: scale(1);
}

.doublesize:hover {
  --t2: scale(2);
}
<div class="transitionease"></div>
<div class="transitionease doublesize rotate "></div>
<div class="transitionease doublesize"></div>


3

您可以将多个动画组合在一起,但不能通过组合CSS类来实现。请参见此处的第一个答案:将多个CSS动画组合成一个总体动画

第一部分告诉您如何使用某些参数(延迟、持续时间)将动画与CSS组合:

.outside.animate {
   -webkit-animation-delay: 0s, .5s, .5s;
   -webkit-animation-duration: 500ms, 1000ms, 1000ms;
   -webkit-animation-name: button-bounce, rotate, skyblue;
}

肯定的是,首先需要定义您的动画。

3
但那些是动画,而不是过渡效果。 - BoltClock
这个主题是关于组合变换属性的,转换并不是真正的问题。 - enguerranws
2
不,它们三者完全是不同的概念。变换(Transforms)是可动画化的,这意味着动画和过渡都可以与变换一起使用,但动画和过渡不能相互包含。 - BoltClock
我知道,但是这个话题是关于组合多个变换属性的。动画可以做到这一点。 - enguerranws
我首先尝试了动画,遇到了与转换相同的问题,即类彼此覆盖。http://jsfiddle.net/9Eq5k/同时,尝试使用动画来实现过渡效果会导致默认动画在页面加载时触发,因此需要使用jquery/javascript在第一次鼠标移出后添加类。本来希望有一个无需脚本的解决方案,但最终可能需要使用javascript来编辑css以实现我想要的效果。 - Ash
显示剩余2条评论

3

仅通过CSS是无法实现这个功能的,但如果你不介意使用一些jQuery,你可以使用下面的效果:

var $elem = $('.cssDropPinImage');

$({deg: 0}).animate({deg: 360}, {
  duration: 600,
  step: function(now) {
    var scale = (2 * now / 360);
    $elem.css({
      transform: 'rotate(' + now + 'deg) scale(' + scale + ')'
    });
  }
});
body {
  padding: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<img src="https://via.placeholder.com/40" class="cssDropPinImage">


是的!我一直在尝试寻找使用jQuery进行多个转换的方法,现在终于成功了。作为另一种选择,您还可以使用单行符号表示法创建一个类,然后使用on()事件委托将其绑定到该类的事件上。 - Callat

0
问题暗示了悬停时的缩放和旋转动画。另一种实用的解决方法是通过重新排列HTML中的元素,并将单独的变换应用于父元素和子元素,仅在父元素上响应悬停事件。
具体做法如下:
<div class="doublesize">
   <div class="rotate"></div>
</div>

.doublesize {
   transition: transform 1s ease;
}

.rotate {
   width: 100px; 
   height: 100px;
   background-color: red;   
   transition: transform 1s ease;
}

.doublesize:hover {
   transform: scale(2);    
}

.doublesize:hover .rotate {
   transform: rotate(360deg);
}

http://jsfiddle.net/n38csxy1/4/

我知道这跟原来的设置相比有些大的改变,但我希望这个观点能够帮助到某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接