主题
移动 Web 基础与变换(一)
本页对应 移动 Web 基础与变换,共 8 段视频,约 1 小时 12 分。
学习目标
- 能够说明字体图标的适用场景,独立引入 iconfont 的 CSS 文件并通过类名在页面中显示图标,且能调整图标大小与颜色。
- 能够处理字体图标样式不生效的权重问题,并通过提高选择器权重或使用
!important验证修复效果。 - 能够在图标库缺少所需图标时,向 UI 获取 SVG 文件,完成 iconfont 上传、去除颜色提交审核、加入购物车并下载使用的流程。
- 能够写出
transform: translate()的完整语法,区分单值、translateX()、translateY()、正负值及百分比含义,并实现元素悬浮位移效果。 - 能够使用绝对定位配合
transform: translate(-50%, -50%)实现子盒子相对父盒子的水平垂直居中。 - 能够完成“开门”案例布局,使用
hover配合左右位移实现开门动画,并用transform: rotate()与deg实现顺/逆时针旋转及过渡效果。
知识点
平面转换是什么
作用:为元素添加动态效果,一般与过渡配合使用。概念:改变盒子在平面内的形态(位移、旋转、缩放、倾斜)。

平面转换也叫 2D 转换,属性是 transform。为什么需要:页面里常见的鼠标悬停位移、图片放大、按钮旋转,都靠它完成。怎么想:先记住它改变的是元素在平面 X/Y 轴上的“形态”,X 正方向向右,Y 正方向向下。怎么做:写 transform: 具体转换函数(...)。易错点:转换函数写错、角度和像素单位混用;多个转换写在一起时顺序会影响结果。
平移
css
transform: translate(X轴移动距离, Y轴移动距离);为什么需要:让盒子在平面上移动,做开门、悬浮位移等效果。怎么想:两个值分别控制 X、Y;正负均可,百分比参照盒子自身尺寸计算。怎么做:translate(100px,100px) 向右下移动;只写一个值表示沿 X 轴移动;单独设置用 translateX() 或 translateY()。易错点:百分比不是参照父级,而是自身宽高;translateX/Y 的 X、Y 要大写;想看到缓慢移动要配 transition。转写稿里调试过:100% 相当于“自己多宽就走多远”。
定位居中


为什么需要:子盒子相对父盒子上下左右居中很常见。怎么想:旧方案是绝对定位 top:50%; left:50% 先到父级中心点,但此时子盒子左上角在中心,还要拉回自身一半。怎么做:旧方案用 margin-left/margin-top 负的自身一半,需要计算;新方案用 transform: translate(-50%,-50%),不用管盒子具体宽高。易错点:margin 的百分比参照父级宽度,不等于自身一半;转写稿中试过负 margin 百分比不理想,最后用 translate(-50%,-50%) 解决。
案例-双开门

为什么需要:综合练习位移、背景定位、过渡和 hover。怎么想:父级放整张背景图并 overflow:hidden;左右两个子盒子各占 50%,右盒子用 background-position:right 0 取精灵图右侧;鼠标悬停父级时,左门向左移 -100%,右门向右移 100%。
html
<div class="father">
<div class="left"></div>
<div class="right"></div>
</div>css
* {
margin: 0;
padding: 0;
}
/* 1. 布局:父子结构,父级是大图,子级是左右小图 */
.father {
display: flex;
margin: 0 auto;
width: 1366px;
height: 600px;
background-image: url(./images/bg.jpg);
overflow: hidden;
}
.father .left,
.father .right {
width: 50%;
height: 600px;
background-image: url(./images/fm.jpg);
transition: all .5s;
}
.father .right {
/* right 表示的取到精灵图右面的图片 */
background-position: right 0;
}
/* 2. 鼠标悬停的效果:左右移动 */
.father:hover .left {
transform: translate(-100%);
}
.father:hover .right {
transform: translateX(100%);
}易错点:过渡加在左右门上,不是加在 hover 里;overflow:hidden 用来裁掉移出去的部分;左右移动方向别写反。
旋转
css
transform: rotate(旋转角度);为什么需要:做时钟指针、按钮转动等效果。怎么想:角度单位是 deg;正值顺时针,负值逆时针。怎么做:rotate(90deg)。易错点:转 360deg 看起来像没转,因为一圈回到原位;转写稿中加 transition 并观察角或文字才明显。
转换原点
默认情况下,转换原点是盒子中心点
css
transform-origin: 水平原点位置 垂直原点位置;为什么需要:时钟指针要绕底部转,而不是绕中心转。怎么想:先确定绕哪个点旋转。怎么做:取值可用方位名词、像素、百分比,如 center bottom。易错点:原点设置和旋转要配合;时钟指针常用 transform-origin:center bottom。

css
.hour {
width: 6px;
height: 50px;
background-color: #333;
margin-left: -3px;
transform: rotate(15deg);
transform-origin: center bottom;
}
.minute {
width: 5px;
height: 65px;
background-color: #333;
margin-left: -3px;
transform: rotate(90deg);
transform-origin: center bottom;
}
.second {
width: 4px;
height: 80px;
background-color: red;
margin-left: -2px;
transform: rotate(240deg);
transform-origin: center bottom;
}多重转换
多重转换技巧:先平移再旋转。
css
transform: translate() rotate();为什么需要:既要移动又要旋转时,顺序会改变坐标轴。怎么想:旋转会改变元素坐标轴向;先写旋转,后面的转换会按旋转后的轴向计算。怎么做:一般先 translate() 再 rotate()。易错点:顺序写反,位移方向会“歪”。
缩放
css
transform: scale(缩放倍数);
transform: scale(X轴缩放倍数, Y轴缩放倍数);为什么需要:做图片悬停放大、播放按钮弹出。怎么想:一个值表示 X/Y 等比例缩放;大于 1 放大,小于 1 缩小。怎么做:scale(1.2)。易错点:scale() 不写单位;播放特效里常和 opacity、transition 配合。

css
/* 1. 摆放播放按钮:图片区域的中间 */
.box li {
overflow: hidden;
}
.pic {
position: relative;
}
.pic::after {
position: absolute;
left: 50%;
top: 50%;
/* margin-left: -29px;
margin-top: -29px; */
/* transform: translate(-50%, -50%); */
content: '';
width: 58px;
height: 58px;
background-image: url(./images/play.png);
transform: translate(-50%, -50%) scale(5);
opacity: 0;
transition: all .5s;
}
/* 2. hover效果:大按钮,看不见:透明是0 → 小按钮,看得见:透明度1 */
.box li:hover .pic::after {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}易错点:伪元素定位居中仍用 translate(-50%,-50%);初始 scale(5) 配合 opacity:0,悬停回到 scale(1)。
倾斜
css
transform: skew();为什么需要:做倾斜卡片等变形效果。怎么想:取值是角度度数 deg。怎么做:如 skew(10deg)。易错点:单位写 deg,不要写 px。
渐变在移动 Web 基础中的位置
本节属于移动 Web 布局前的基础知识。转写稿里把这一阶段概括为四大块:字体图标、平面转换、渐变、3D 空间转换,并说明重点是平面转换。这里要纠正几个同音字:不是“字体浮标”,而是“字体图标”;不是“平面转化”,而是“平面转换”;不是“3D 空间转化”,而是“3D 空间转换”。渐变虽然单词较长,但明确说不推荐死记,使用时能查出来、跟着会写即可,它本质上仍是 CSS 样式。
为什么需要:页面里经常要给盒子加背景层次,纯色背景有时太生硬,渐变可以让多个颜色平滑过渡。
怎么想:先判断是线性渐变还是径向渐变,再确定方向、颜色和颜色终点位置。
怎么做:用 background-image 设置渐变,而不是把它当成普通背景色。
易错点:不要把 linear-gradient() 直接写给 background-color;颜色之间用英文逗号分隔;透明色可用 transparent 或 rgba()。
渐变是多个颜色逐渐变化的效果,一般用于设置盒子背景。分类如下:
- 线性渐变

- 径向渐变

线性渐变
为什么需要:线性渐变适合做从一个方向过渡到另一个方向的背景,例如遮罩、 banner 底部压暗、卡片背景等。
怎么想:先想“往哪个方向渐变”,再想“有哪些颜色,每个颜色停在哪里”。方向和终点位置都是可选项,不写时浏览器会按默认规则处理。
怎么做:使用如下语法:
css
background-image: linear-gradient(
渐变方向,
颜色1 终点位置,
颜色2 终点位置,
......
);取值:
- 渐变方向:可选
- to 方位名词
- 角度度数
- 终点位置:可选
- 百分比
易错点:方向写在第一个参数位置;颜色和终点位置之间用空格;多个颜色之间用逗号;如果只写颜色不写终点位置,颜色会按浏览器默认分布。
案例-产品展示
为什么需要:产品图上方直接放白色文字可能看不清,需要在图片底部加一层由透明到黑色的渐变遮罩,鼠标悬停时再显示。
怎么想:先搭结构:图片、标题、遮罩三层;遮罩绝对定位覆盖整个盒子;默认 opacity: 0 隐藏,hover 时变为 1;过渡写在 .mask 上。
怎么做:笔记中的结构和样式如下。

- HTML 结构
html
<div class="box">
<img src="./images/product.jpeg" alt="" />
<div class="title">OceanStor Pacific 海量存储斩获2021 Interop金奖</div>
<div class="mask"></div>
</div>- CSS 样式
css
.mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
transparent,
rgba(0,0,0,0.5)
);
opacity: 0;
transition: all .5s;
}
.box:hover .mask {
opacity: 1;
}易错点:.mask 用了绝对定位,实际使用时要注意父级定位上下文;transparent 表示透明,rgba(0,0,0,0.5) 表示半透明黑色;过渡加在 .mask 上,而不是只写在 :hover 里;悬停选择器要写清楚父子关系。
径向渐变
为什么需要:径向渐变从一个圆心向外扩散,适合做光晕、圆形高光、中心发散的背景效果。
怎么想:先确定圆心和半径,再确定颜色顺序。半径可以写一条,也可以写两条;写两条时为椭圆。圆心位置可用像素、百分比或方位名词。
怎么做:使用如下语法:
css
background-image: radial-gradient(
半径 at 圆心位置,
颜色1 终点位置,
颜色2 终点位置,
......
);取值:
- 半径可以是2条,则为椭圆
- 圆心位置取值:像素单位数值 / 百分比 / 方位名词
易错点:at 用来连接半径和圆心位置;半径写两条时注意顺序;圆心位置不要和颜色终点位置混淆;仍然要写在 background-image 中。
小结与练习建议
本节转写稿没有展开渐变的逐步调试,主要提醒是:渐变单词长,不要求死记,忘了就查语法,能跟着写出来即可。练习时先写线性渐变,再做产品展示遮罩,最后试径向渐变。检查重点是:渐变是否写在 background-image、颜色逗号是否为英文、遮罩定位和 opacity 过渡是否生效。
课件图示








代码示例
示例一:平移语法 + 定位居中
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>平移与定位居中</title>
<style>
* { margin: 0; padding: 0; }
/* ---------- 1. 平移基本语法 ---------- */
.box {
width: 200px;
height: 200px;
background-color: pink;
margin: 100px auto;
transition: all .5s; /* 过渡写在基础盒子上 */
}
.box:hover {
/* transform: translate(100px, 100px); X 正右、Y 正下 */
/* transform: translate(-100px, 100px); 负值往左 */
/* transform: translate(100%); 百分比参照盒子自身宽度 */
/* transform: translateX(100px); 只沿 X 轴,X 必须大写 */
transform: translateY(100px); /* 只沿 Y 轴 */
}
/* ---------- 2. 定位居中 ---------- */
.father {
position: relative;
width: 600px;
height: 400px;
border: 1px solid #999;
margin: 0 auto;
}
.son {
position: absolute;
left: 50%;
top: 50%;
width: 188px; /* 故意用不整的数字 */
height: 166px;
background-color: #ccc;
/* 旧方案要自己算一半:margin-left: -94px; margin-top: -83px; */
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div class="box"></div>
<div class="father">
<div class="son"></div>
</div>
</body>
</html>关键行与易错点
transform: translate(X, Y)的两个值分别对应 X 轴、Y 轴;X 正方向向右、Y 正方向向下,正负值都可写。- 只写一个值
translate(100px)时,只表示沿 X 轴 移动,Y 轴不动;要单独控制 Y 轴用translateY(),注意 X / Y 必须大写,小写不生效。 - 百分比参照 盒子自身尺寸:
translate(100%)就是“自己多宽就走多远”,和父级宽度无关。 - 居中方案:
left: 50%; top: 50%只是把子盒子的左上角移到父级中心点,所以还要translate(-50%, -50%)把自身一半拉回来;这样不用管宽高是多少,彻底免去旧方案margin-left: -94px那种手算。 transition必须写在基础状态.box上,写在:hover里只能“进去有过渡、出来没过渡”。
示例二:双开门(精灵图 + 平移)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>双开门</title>
<style>
* { margin: 0; padding: 0; } /* 消除 body 默认 8px 外边距 */
/* 1. 布局:父级是大图,子级是左右小图 */
.father {
display: flex;
margin: 0 auto;
width: 1366px;
height: 600px;
background-image: url(./images/bg.jpg); /* 换成你自己的图片路径 */
overflow: hidden; /* 门移出去的部分藏起来 */
}
.father .left,
.father .right {
width: 50%;
height: 600px;
background-image: url(./images/fm.jpg); /* 门:一整张图 */
transition: all .5s;
}
.father .right {
/* right 表示取到精灵图右面的图片 */
background-position: right 0;
}
/* 2. 鼠标悬停的效果:左右移动 */
.father:hover .left {
transform: translate(-100%);
}
.father:hover .right {
transform: translateX(100%);
}
</style>
</head>
<body>
<div class="father">
<div class="left"></div>
<div class="right"></div>
</div>
</body>
</html>关键行与易错点
- 两扇门共用一张图
fm.jpg,右门用background-position: right 0把图“右半边”显示出来,这就是笔记里说的精灵图思路。 translate(-100%)的参照是门自身宽度(父级的一半),所以正好把门推出父盒子宽度的一半,左右对称。overflow: hidden不能漏:门被推出去会撑出横向滚动条。* { margin: 0; padding: 0; }同样不能漏,body 默认 8px 外边距会让 1366px 的盒子超出屏幕。transition写在.left / .right上而不是:hover里,这样鼠标移出时门也会缓缓关上。
示例三:缩放播放特效 + 渐变遮罩
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>播放特效与渐变遮罩</title>
<style>
* { margin: 0; padding: 0; }
body { padding: 50px; }
ul { list-style: none; }
.box { display: flex; gap: 20px; }
.box li { overflow: hidden; }
.pic { position: relative; width: 300px; height: 200px; }
.pic img { width: 100%; height: 100%; display: block; object-fit: cover; }
/* 1. 摆放播放按钮:图片区域的中间 */
.pic::after {
position: absolute;
left: 50%;
top: 50%;
/* margin-left: -29px; margin-top: -29px; 旧方案要算一半 */
/* transform: translate(-50%, -50%); 只居中不缩放 */
content: '';
width: 58px;
height: 58px;
background-image: url(./images/play.png); /* 换成你自己的图标 */
background-size: cover;
transform: translate(-50%, -50%) scale(5); /* 先平移,再放大 */
opacity: 0;
transition: all .5s;
}
/* 2. hover 效果:大按钮看不见 → 小按钮看得见 */
.box li:hover .pic::after {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
/* 3. 产品展示的渐变遮罩 */
.mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
transparent,
rgba(0, 0, 0, 0.5)
);
opacity: 0;
transition: all .5s;
}
.box li:hover .mask { opacity: 1; }
</style>
</head>
<body>
<ul class="box">
<li>
<div class="pic">
<img src="./images/product.jpeg" alt="" />
<div class="mask"></div>
</div>
</li>
</ul>
</body>
</html>关键行与易错点
- 多重转换的顺序极其关键:
translate(-50%, -50%) scale(5)是先平移再缩放,位移距离按原始尺寸计算;如果写成scale(5) translate(-50%, -50%),坐标轴已被放大 5 倍,位移也跟着放大,按钮会跑偏。笔记的结论就是“先平移再旋转/缩放”。 scale()只写一个值表示 X、Y 等比缩放;大于 1 放大,小于 1 缩小,不需要写单位。- 显隐用
opacity而不是display: none,因为 opacity 可以参与过渡,也不会改变布局。 - 渐变必须写在
background-image: linear-gradient(...)上,写成background-color是无效的。 linear-gradient默认方向从上到下,第一个色transparent让图片上方透明、下方变暗;颜色终点位置可选用百分比控制。- 定位居中同样用
left/top: 50% + translate(-50%, -50%),比margin-left: -29px这种硬算一半更省事。
常见错误
- 现象:绝对定位
top:50%; left:50%后再写translate(50%,50%),盒子偏到右下。原因:translate百分比参照元素自身尺寸,方向写反。修法:改为translate(-50%,-50%)。 - 现象:双开门只有鼠标移到单扇门上才动,左右不同步。原因:
hover写在了子元素上。修法:用父级控制子元素,如.father:hover .left、.father:hover .right。 - 现象:鼠标移入有过渡,移出生硬跳回。原因:
transition写在:hover状态里。修法:把transition放在元素基础状态。 - 现象:
transform: rotate(...) translate(...)后位移方向歪掉。原因:旋转改变坐标轴,多重转换顺序影响结果。修法:按需求先写translate()再写rotate()。 - 现象:时钟指针绕自身中心转,不绕底部。原因:未设置转换原点。修法:给指针设置
transform-origin: center bottom。 - 现象:遮罩写
background-color: linear-gradient(...)不显示渐变。原因:linear-gradient()是背景图值,不是颜色值。修法:改用background-image或background。
练习
- 用绝对定位实现子盒子在父盒子中上下左右居中,要求不计算子盒子宽高,并说明为什么用
-50%。 - 完成双开门案例:鼠标悬停父盒子时,左门向左移出、右门向右移出,移入移出都要有过渡。
- 完成时钟指针布局:时、分、秒针分别设置旋转角度,并保证都绕指针底部旋转。
- 写一个“小车先平移再旋转”的
transform组合,并交换顺序观察差异,记录哪一版符合预期。 - 给产品图添加底部渐变遮罩:默认透明,悬停显示从透明到半透明黑的线性渐变。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 今日重点 | 02:15 |
| 2 | 字体图标 | 15:09 |
| 3 | 案例-字体图标 | 03:14 |
| 4 | 上传图标 | 08:05 |
| 5 | 位移-1-基本语法 | 15:43 |
| 6 | 位移-2-居中 | 07:28 |
| 7 | 位移-3-开门案例 | 13:57 |
| 8 | 旋转-1-基本 | 06:36 |
小结
- 居中场景优先考虑
translate(-50%,-50%),避免依赖固定宽高计算。 hover动画的控制选择器要写清作用域,父级触发、子级变化更稳定。transition应放在基础状态,保证进入和离开都有过渡。- 多重转换顺序不是随意排列,先平移再旋转通常更符合预期。
- 旋转类案例先确认转换原点,再调角度和过渡时间。
- 渐变用于背景图属性,不要误写成背景颜色属性。
- 调试时先看选择器是否命中,再看属性值是否生效,最后看状态切换是否成对。