CSS3系列 13 变形动画

本文深入探讨CSS3变形动画,包括坐标系统、变形操作、变形叠加等基础知识,以及移动、缩放、旋转、倾斜等具体操作。通过大量实例演示,帮助读者掌握创建炫酷页面效果的技巧,如3D转换、菜单缩放、相册放大等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在开始介绍CSS变形动画之前,可以先了解一下学习了它之后能做什么,有什么用,这样你看这篇文章可能会有一些动力。

学习了CSS变形动画后,你可以为你的页面做出很多炫酷的效果,如一个3D的魔方,一个很酷的旋转菜单等等。

在本章节中将会采用大量的实例进行演示,相信你如果看完这篇文章后写出的页面会更加的吸引眼球。

动态菜单

基础知识

坐标系统

首先我们要学习的变形动画,想达到在上图中出现的3D效果单纯的X与Y两个轴是实现不了的,还需要加入一条纵深轴,即Y轴的参与才有一个3D的视觉感受。

那么如何来理解X,Y,Z这三条轴的关系呢?可以看一下下面这张图。

  • X轴代表水平轴
  • Y轴代表垂直轴
  • Z轴代表纵深轴

image-20200719220200287

X和Y轴都非常好理解,怎么理解这个Z轴呢?

CSS的中文名称叫做层叠样式表,那么它肯定是一层一层的。之前学习过z-index就是用来设置层的优先级,优先级越高越在上面,也可以理解为离我们肉眼越近,它把优先级低的层给盖住了,所以Z轴可以理解为我们观察的视角与被观察物体之间的一条轴。

Z轴数值越大,说明观测距离越远。

Z轴的数值可以无限大,所以设置的时候一定要小心。

变形操作

可以使用transform规则控制元素的变形操作,包括元素移动、旋转、倾斜、3D转换等等。

下表中是CSS提供的变形动作,在接下来的学习中将会对一个变形动作进行详解。

选项 说明
none 定义不进行转换。
translate(x,y) 定义 2D 转换。
translate3d(x,y,z) 定义 3D 转换。
translateX(x) 定义转换,只是用 X 轴的值。
translateY(y) 定义转换,只是用 Y 轴的值。
translateZ(z) 定义 3D 转换,只是用 Z 轴的值。
scale(x,y) 定义 2D 缩放转换。
scale3d(x,y,z) 定义 3D 缩放转换。
scaleX(x) 通过设置 X 轴的值来定义缩放转换。
scaleY(y) 通过设置 Y 轴的值来定义缩放转换。
scaleZ(z) 通过设置 Z 轴的值来定义 3D 缩放转换。
rotate(angle) 定义 2D 旋转,在参数中规定角度。
rotate3d(x,y,z,angle) 定义 3D 旋转。
rotateX(angle) 定义沿着 X 轴的 3D 旋转。
rotateY(angle) 定义沿着 Y 轴的 3D 旋转。
rotateZ(angle) 定义沿着 Z 轴的 3D 旋转。
skew(x-angle,y-angle) 定义沿着 X 和 Y 轴的 2D 倾斜转换。
skewX(angle) 定义沿着 X 轴的 2D 倾斜转换。
skewY(angle) 定义沿着 Y 轴的 2D 倾斜转换。
perspective(n) 为 3D 转换元素定义透视视图。

变形叠加

这其实是一个坑点,在使用变形中一定要注意,重复对元素设置变形操作时只在元素的原形态上操作。

我们可以先看一下下面的案例,不懂代码没关系,懂这个意思就行了。

默认处理

下面设置了两次移动,并不会移动550px 而是只移动50px。

我们在元素中先设置了右移500px,鼠标放上去时再往右移动50px,可是下面却出现了向左移动的场景,这是因为对div进行了位置居中处理,它必须要按照之前居中的位置进行50px的移动。而不是按照居中后设置的500px的地方再进行向右移动50px。

上面这句话有点绕,总之。上面设置了,位置改变了,下面再设置,不会按照已改变的位置进行变化,而是按照原位置。

变形叠加

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            list-style: none;
        }

        body {
            height: 100vh;
            width: 100vw;
            background-color: aliceblue;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        div {
            width: 200px;
            height: 200px;
            background-color: blueviolet;
            /* 意思就是说按x轴移动500px */
            transform: translateX(500px);
            /* 过渡时间2s */
            transition: 2s;

        }

        div:hover {
            /* 意思就是说按x轴移动50px */
            transform: translateX(50px);
        }
    </style>
</head>

<body>

    <div></div>

</body>

</html>

伪类叠加

还是设置两次移动,如果移动的方向都一样,且伪类设置的移动比原本的移动多一点,就在原本的基础上直接进行变形,而不用再找开始位置了。

我们还是拿上面的案例,只不过伪类移动的数值将50px改为600px,比第一次设置大100px,那么此时他就不会再往左走,而是直接在原有基础上进行叠加,向右移动100px。

伪类叠加

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            list-style: none;
        }

        body {
            height: 100vh;
            width: 100vw;
            background-color: aliceblue;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        div {
            width: 200px;
            height: 200px;
            background-color: blueviolet;
            /* 意思就是说按x轴移动500px */
            transform: translateX(500px);
            /* 过渡时间2s */
            transition: 2s;

        }

        div:hover {
            /* 意思就是说按x轴移动600px */
            transform: translateX(600px);
        }
    </style>
</head>

<body>

    <div></div>

</body>

</html>

内联元素

内联元素即行级元素,inline元素是不能参与变形的,将其转为 inline-block 或 block 以及弹性元素时才可以产生变化效果。

:hover伪类

鼠标移动到某一元素上发生的用户行为。

当该行为出现时,我们可以为它指定一些参数的改变。

如下,改变颜色。

hover

:target伪类

意思就是说你点击一个<a>,该<a>标签中的href指向的锚点标签会发生变化。

点击第一个<a>元素,与之相对的锚点元素发生变化。

点击第二个<a>元素,与第一个<a>元素相对的锚点变化停止,与第二个<a>元素相对的锚点发生变化。

target

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            flex-flow: column;
            justify-content: center;
            align-items: center;
        }

        div {
            width: 200px;
            height: 200px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #fff;
            font-size: 2em;
        }

        div:nth-child(1) {
            background: red;

        }

        div:nth-child(2) {
            background: blue;

        }

        #div-1:target {
            background-color: green;
        }

        #div-2:target {
            background-color: black;
        }
    </style>
</head>

<body>
    <div id="div-1">原本颜色:红</div>
    <div id="div-2">原本颜色:蓝</div>
    <a href="#div-1">让div-1变绿</a>
    <a href="#div-2">让div-2变黑</a>
</body>

</html>

最后注意一点

事件元素上放过渡时间,:hover上放具体的事件,如移动,旋转,倾斜等操作。

如果你设置了移动却将过渡时间放在了:hover里面,那么就会出现下面这种情况。

可以看见,直勾勾的就回来了,这种效果显然不是我们想要的。

过渡时间

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        main {
            width: 400px;
            height: 200px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;

            /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */
            position: relative;
        }

        div:first-child {
            height: 8px;
            width: 8px;
            background-color: black;

            z-index: 1;
            border-radius: 50%;

            /* 脱离文档流并居中 */
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4px;
            margin-top: -4px;

        }

        div:last-child {
            height: 100px;
            width: 100px;
            background-color: blueviolet;
            /* 过渡时间1s,应该放这里,而不是:hover上面 */
            /* transition: 1s; */

        }

        div:last-child:hover {
            transform: translateX(100px);
        }
    </style>
</head>

<body>
    <main>
        <div></div>
        <div></div>
    </main>
</body>

</html>

移动元素

  • 沿X轴移动时正值向右移动、负值向左移动
  • 沿Y轴移动时正值向下移动、负值向上移动
  • 如果使用百分数将控制元素的原尺寸计算百分比然后移动
  • 可同时设置多个值,解析器会从左向右依次执行
  • 变形是在原基础上更改,即第二次设置值时不是在第一次值上变化

translateX

控制元素在X轴上的移动,正值向右、负值向左。

如,我们下面设置translateX(100px),过渡时间为1s。

x平移

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        main {
            width: 400px;
            height: 200px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;

            /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */
            position: relative;
        }

        div:first-child {
            height: 8px;
            width: 8px;
            background-color: black;

            z-index: 1;
            border-radius: 50%;

            /* 脱离文档流并居中 */
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4px;
            margin-top: -4px;

        }

        div:last-child {
            height: 100px;
            width: 100px;
            background-color: blueviolet;
            /* 过渡时间1s,应该放这里,而不是:hover上面 */
            transition: 1s;

        }

        div:last-child:hover {
            transform: translateX(100px);
        }
    </style>
</head>

<body>
    <main>
        <div></div>
        <div></div>
    </main>
</body>

</html>

translateY

控制元素在X轴上的移动,正值向下、负值向上。

如,我们下面设置translateY(100px),过渡时间为1s。

y平移

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        main {
            width: 200px;
            height: 400px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;

            /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */
            position: relative;
        }

        div:first-child {
            height: 8px;
            width: 8px;
            background-color: black;

            z-index: 1;
            border-radius: 50%;

            /* 脱离文档流并居中 */
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4px;
            margin-top: -4px;

        }

        div:last-child {
            height: 100px;
            width: 100px;
            background-color: blueviolet;
            /* 过渡时间1s,应该放这里,而不是:hover上面 */
            transition: 1s;

        }

        div:last-child:hover {
            transform: translateY(100px);
        }
    </style>
</head>

<body>
    <main>
        <div></div>
        <div></div>
    </main>
</body>

</html>

translate

translate是translateX以及translateY的简写模式,第一个值控制X移动,第二个值控制Y移动。

一句话,设置X与Y轴的移动,注意,这个方法中不包含Z轴,因为一旦有Z轴参与就会变为3D效果。

XY平移

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        main {
            width: 400px;
            height: 400px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;

            /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */
            position: relative;
        }

        div:first-child {
            height: 8px;
            width: 8px;
            background-color: black;

            z-index: 1;
            border-radius: 50%;

            /* 脱离文档流并居中 */
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4px;
            margin-top: -4px;

        }

        div:last-child {
            height: 100px;
            width: 100px;
            background-color: blueviolet;
            /* 过渡时间1s,应该放这里,而不是:hover上面 */
            transition: 1s;

        }

        div:last-child:hover {
            /* 先设置X轴,再设置Y轴 */
            transform: translate(100px, 100px);
        }
    </style>
</head>

<body>
    <main>
        <div></div>
        <div></div>
    </main>
</body>

</html>

百分比移动

当要移动的元素宽高为100px时,如果使用50%进行移动,则代表移动50px。

百分比平移

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        main {
            width: 400px;
            height: 400px;
            border: 1px solid #ccc;
            display: flex;
            justify-content: center;
            align-items: center;

            /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */
            position: relative;
        }

        div:first-child {
            height: 8px;
            width: 8px;
            background-color: black;

            z-index: 1;
            border-radius: 50%;

            /* 脱离文档流并居中 */
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4px;
            margin-top: -4px;

        }

        div:last-child {
            height: 100px;
            width: 100px;
            background-color: blueviolet;
            /* 过渡时间1s,应该放这里,而不是:hover上面 */
            transition: 1s;

        }

        div:last-child:hover {
            /* 先设置X轴,再设置Y轴 */
            transform: translate(50%, 50%);
        }
    </style>
</head>

<body>
    <main>
        <div></div>
        <div></div>
    </main>
</body>

</html>

元素居中

我们之前介绍过很多元素居中的方法,如定位操作,弹性盒模型,其实使用移动也可以达到元素居中的效果。

给你丢一套模板。

/* 让子元素脱离文档流并参照副父级元素偏移。这是定位+margin的居中方法 */
position: absolute;
left: 50%;
top: 50%;
/* left和top设置子元素宽高的负的50%就行 */
margin-left: -3px;
margin-top: -3px;


/* 这是弹性盒模型控制元素居中的方法 */
display: flex;
justify-content: center;
align-items: center;


/* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */
position: absolute;
left: 50%;
top: 50%;
/* X和Y设置子元素宽高的负的50%就行 */
transform: translate(-50%, -50%);

image-20200719234621478

translateZ

控制Z轴移动,正数向外(距离我们近)、负数向里移动(距离我们远)。因为Z轴是透视轴没有像X/Y一样的固定尺寸,所以不能使用百分数。

Z轴平移

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        * {
            padding: 0;
            margin: 0;
            list-style: none;
            box-sizing: border-box;
        }

        body {
           
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值