第2章:CSS3变换(Transform)基础——让元素动起来的第一步

说实话,CSS3的Transform是我最早接触的动画属性之一。记得刚入行那会儿,要实现一个元素旋转或者位移,还得用JavaScript去操作DOM的style.left、style.top,那叫一个痛苦。后来CSS3的Transform一出来,我整个人都舒服了——原来让元素动起来,可以这么简单。

这一章,咱们就聊聊Transform的四个核心函数:translate()rotate()scale()skew(),以及一个容易被忽略但极其重要的属性——transform-origin。最后,我会带大家实现一个经典的卡片翻转效果。

2.1 认识Transform:它到底改变了什么?

先问一个问题:Transform改变的是元素的什么?

很多人会脱口而出:「位置、大小、角度啊。」

对,但不全对。Transform改变的是元素的视觉呈现,而不是它在文档流中的实际占位。什么意思呢?你想想看,一个元素用了translateX(100px),它看起来往右移了100px,但它在文档流里的原始位置依然占据着空间,其他元素不会自动让位。这一点,我在项目中踩过坑——有一次做弹窗动画,用了translate做位移,结果发现弹窗虽然移走了,但底下的遮罩层点击区域还是原来的位置,排查了半天才反应过来。

核心要点:Transform不会影响文档流,它只改变元素的渲染结果。这意味着你可以随意变换元素,而不用担心打乱布局。

2.2 四个核心函数详解

2.2.1 translate() —— 移动元素

translate() 说白了就是让元素「挪个窝」。它接受两个参数:X轴偏移量和Y轴偏移量。

/* 语法 */
transform: translate(tx, ty);
transform: translateX(tx);
transform: translateY(ty);

/* 示例 */
.box {
  transform: translate(50px, 100px);  /* 向右移50px,向下移100px */
}

我个人习惯用百分比来做相对位移,比如 translate(50%, 50%),这个百分比是相对于元素自身尺寸的。这在做居中布局时特别好用——配合绝对定位,一个 top: 50%; left: 50%; transform: translate(-50%, -50%) 就能完美居中,不用管父容器多大。

小技巧:translate可以使用负值,比如 translate(-50%, -50%) 就是向左上角移动自身一半的宽高。这在做垂直水平居中时是经典写法。

2.2.2 rotate() —— 旋转元素

rotate() 让元素绕着一个中心点旋转。参数是角度,单位是 deg(degree的缩写)。

/* 语法 */
transform: rotate(angle);

/* 示例 */
.box {
  transform: rotate(45deg);   /* 顺时针旋转45度 */
  transform: rotate(-30deg);  /* 逆时针旋转30度 */
}

正值为顺时针,负值为逆时针。这个很好记,你想想看钟表指针怎么走的就明白了。

我曾经在做一个加载动画时,用rotate让一个圆环无限旋转,效果非常丝滑。但要注意,rotate默认的旋转中心是元素的几何中心,也就是50% 50%的位置。如果你想改变旋转中心,那就得用到后面要讲的 transform-origin 了。

2.2.3 scale() —— 缩放元素

scale() 用来放大或缩小元素。参数是缩放倍数,1为原始大小,大于1放大,小于1缩小。

/* 语法 */
transform: scale(sx, sy);
transform: scaleX(sx);
transform: scaleY(sy);

/* 示例 */
.box {
  transform: scale(1.5);       /* 整体放大1.5倍 */
  transform: scale(0.5, 2);   /* 宽度缩小一半,高度放大一倍 */
}

这里有个坑,我刚开始用的时候踩过——scale() 只接受一个参数时,它会同时缩放X和Y轴。如果你只想缩放一个方向,用 scaleX()scaleY() 更清晰。

注意:scale缩放的是元素的视觉尺寸,但元素在文档流中的占位空间不变。如果你缩放了一个按钮,它的点击区域还是原来的大小,除非你用 pointer-events 或者重新计算点击区域。

2.2.4 skew() —— 倾斜元素

skew() 可能是四个函数里最不常用的,但某些场景下它非常出彩。它让元素沿着X轴或Y轴发生倾斜变形,参数同样是角度。

/* 语法 */
transform: skew(ax, ay);
transform: skewX(ax);
transform: skewY(ay);

/* 示例 */
.box {
  transform: skew(10deg, 5deg);   /* X轴倾斜10度,Y轴倾斜5度 */
  transform: skewX(20deg);        /* 只沿X轴倾斜20度 */
}

你可以把skew想象成把一张纸的一边固定,另一边用力推——纸就变成了平行四边形。这个效果在做一些立体感或者动态背景时很有用。

2.3 transform-origin:控制变换的「支点」

前面提到,rotate、scale、skew默认都是以元素的中心为基准进行变换的。但如果你想让元素绕着左上角旋转,或者从底部开始缩放呢?这时候就需要 transform-origin 出场了。

/* 语法 */
transform-origin: x-position y-position z-position;

/* 常用值 */
transform-origin: center center;   /* 默认值,中心点 */
transform-origin: top left;        /* 左上角 */
transform-origin: 50% 50%;         /* 等同于 center center */
transform-origin: 0 100%;          /* 左下角 */
transform-origin: 100px 200px;     /* 指定像素位置 */

这个属性接受两个或三个值(3D变换时用第三个值),可以是关键词(top、bottom、left、right、center),也可以是百分比或具体像素值。

我记得有一次做卡片翻转效果,想让卡片从底部「翻」起来,而不是从中间翻。当时默认的transform-origin是center,效果很平淡。改成 transform-origin: bottom center 之后,整个动画的立体感和动感瞬间就出来了。

一句话总结:transform-origin决定了变换的「锚点」。改变它,同样的变换函数会产生完全不同的视觉效果。

2.4 实战:卡片翻转效果

好了,理论知识讲完了。咱们来做一个经典的卡片翻转效果。这个效果在很多网站上都见过——鼠标悬停时,卡片像扑克牌一样翻过来,展示背面的内容。

实现思路其实很简单:

  1. 准备一个容器,里面放两个面(正面和背面)
  2. 默认显示正面,背面隐藏
  3. 鼠标悬停时,让整个容器沿Y轴旋转180度
  4. 背面在旋转过程中「翻」到前面来

关键代码来了:

<div class="card">
  <div class="card-inner">
    <div class="card-front">
      <h3>正面内容</h3>
      <p>悬停我看看背面</p>
    </div>
    <div class="card-back">
      <h3>背面内容</h3>
      <p>这是背面的信息</p>
    </div>
  </div>
</div>

<style>
.card {
  width: 300px;
  height: 200px;
  perspective: 1000px;  /* 给父容器添加透视,产生3D效果 */
}

.card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform 0.6s ease;
  transform-style: preserve-3d;  /* 保留子元素的3D空间 */
}

.card:hover .card-inner {
  transform: rotateY(180deg);  /* 悬停时翻转180度 */
}

.card-front, .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;  /* 隐藏背面,防止翻转时看到反面 */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
}

.card-front {
  background: #4A90D9;
  color: white;
}

.card-back {
  background: #F5A623;
  color: white;
  transform: rotateY(180deg);  /* 背面默认旋转180度,这样翻转后它才正面朝前 */
}
</style>

这里有几个关键点,我重点说一下:

  • perspective:给父容器设置透视,让翻转有立体感。没有它,翻转就是扁平的,像一张纸在平面上旋转,没有「纵深」的感觉。
  • transform-style: preserve-3d:告诉浏览器,子元素要在3D空间里进行变换。如果不加这个,子元素的rotateY会被「拍平」到父元素的平面上。
  • backface-visibility: hidden:这个属性很关键。它让元素的背面不可见。默认情况下,一个元素旋转180度后,你会看到它的「背面」(也就是镜像内容)。加上 hidden 后,背面就透明了,这样翻转时才能看到另一面的内容。

避坑指南:我曾经在项目中忘记加 transform-style: preserve-3d,结果卡片翻转时两个面「打架」,正面和背面同时出现,画面非常诡异。排查了半天才发现是少了这一行。所以,做3D变换时,这三个属性(perspective、preserve-3d、backface-visibility)最好一起上,缺一不可。

2.5 本章小结

这一章我们聊了CSS3 Transform的四个基础函数:

  • translate():移动元素,不影响文档流
  • rotate():旋转元素,默认绕中心
  • scale():缩放元素,视觉尺寸变化
  • skew():倾斜元素,做出平行四边形效果

以及 transform-origin 这个控制变换「支点」的属性,还有 perspectivetransform-stylebackface-visibility 这三个3D变换的「黄金搭档」。

说实话,Transform是CSS动画的基石。你想想看,后面要学的过渡(Transition)和动画(Animation),本质上都是在不同时间点改变Transform的值。所以这一章的内容,值得你多花点时间消化。

下一章,我们会聊CSS3过渡(Transition),看看如何让这些变换「动起来」,而不是瞬间跳变。到时候,咱们再结合今天学的Transform,做一些更酷的效果。

课后练习:试着把上面卡片翻转的transform-origin改成不同的位置(比如top left、bottom right),看看翻转效果有什么变化。你会发现,同样的代码,不同的支点,视觉感受完全不同。


公众号:蓝海资料掘金营,微信deep3321