搜索

CSS 教学

基本介绍

认识 CSS 开始使用 CSS CSS 语法规则 CSS 命名原则 CSS 常用样式属性

CSS 选择器

认识 CSS 选择器 优先级 ( 权重 ) 样式继承与联集 使用巢状结构语法 元素选择器 ID 和 Class 选择器 属性选择器 文件结构选择器 虚拟类别选择器 ( 结构 ) 虚拟类别选择器 ( 类型 ) 虚拟类别选择器 ( 输入 ) 虚拟类别选择器 ( 行为 ) 虚拟类别选择器 ( 超链接 ) 虚拟类别选择器 ( 逻辑 ) 虚拟类别选择器 ( 其他 ) 虚拟元素选择器 群组与组合选择器

数值与单位

全域关键字与文字数值 长度与角度单位 位置名称与时间单位 特殊样式属性 ( all、appearance)

规则与定义

变数 ( Variables ) 媒体查询 ( @media ) 容器查询 ( @container ) 自订属性值 ( @property ) 导入样式 ( @import ) 分层优先级 ( @layer ) 选择器作用域 ( @scope ) 定义字型 ( @font-face ) 计数规则 ( @counter-style ) 打印网页 ( @page )

函数类型

数学计算 文字与清单计数 形状与线段 路径 ( path )

颜色与滤镜

颜色单位 色彩模型 相对颜色 渐层色 图像滤镜 ( filter ) 背景滤镜 ( backdrop-filter ) 混合模式 ( mix-blend-mode )

文字与段落

设定字型 ( font-family ) 使用外部字型 文字尺寸 文字样式 ( 常用 ) 文字样式 ( 其他实用 ) 文字样式 ( 特殊用途 ) 文字换行 文字空白与 Tab 大小 文字行高与缩排 文字水平与垂直对齐 文字书写方向 文字自动分栏 使用 Color Font ( 彩色字型 ) 使用 Icon Font ( 图示文字 ) 制作自己的 Icon Font 显示生成内容与引号

元素容器

容器显示类型 ( display ) 元素 display 对照表 盒子模型 ( Box Model ) 宽高尺寸 ( width、height ) 显示与比例 ( box-sizing、aspect-ratio ) 内边距 ( padding ) 外边界 ( margin ) 边框 ( border ) 边框圆角 ( border-radius ) 图像边框 ( border-image ) 轮廓 ( outline ) 内容溢出与裁切 ( overflow ) 内容范围 ( contain ) 可见性与透明度 缩放与调整 ( zoom、resize )

背景与阴影

背景 ( 背景色、背景裁切 ) 背景图 ( 定位、尺寸 ) 背景图 ( 固定、重复 ) 背景图 ( 多重背景、混合 ) 背景缩写 ( background ) 容器阴影 ( box-shadow )

清单与表格

清单样式 清单计数器 表格基本样式 表格边框重叠与间距 表格内容宽度与对齐

基本排版与定位

元素排版方式 浮动 ( float ) 浮动形状 ( shape-* ) 定位 ( position ) 逻辑属性 ( logical properties ) 重置 CSS ( Reset CSS ) 水平置中技巧 垂直置中技巧

Flex 弹性排版

Flexbox 弹性盒子 Flex 对齐方式 Flex 弹性伸缩

Grid 网格排版

Grid 网格容器与格线 Grid 网格空间与命名 Grid 网格流向与间距 Grid 排列网格项目 Grid 项目对齐与顺序

转场与动画

转场 ( transition ) 转场触发事件 动画 ( animation ) 自订动画路径 ( offset ) 动画触发事件 多重动画的权重与顺序 动画进度控制 ( timeline )

变形、裁切与遮罩

裁切路径 ( clip-path ) 图像遮罩 ( mask ) 对象填满方式与定位 转换函数 ( transform ) 平移、旋转与缩放 3D 转换与透视

视窗与用户行为

卷轴样式 ( scrollbar ) 拉霸、滑杆样式 ( slider ) 鼠标光标图示 ( cursor ) 鼠标事件 ( pointer-events ) 用户选取 ( user-select ) 卷动行为 ( scroll、overscroll ) 打印换页 ( break-* )

CSS 预处理器

认识 CSS 预处理器 Less ( 安装、开始使用 ) Less ( 巢状结构、选择器 ) Less ( 变数、import ) Less ( Extend、Mixin ) Less ( 逻辑、循环、函数 )

范例效果

CSS 多重绕圈 3D 动画 CSS 圆饼图 CSS 跑马灯 Google 加载动画 电子时钟数字 渐层色的转场与动画 渐层色制作星空背景 渐层色边框 渐层色制作图案背景 不规则形状动画 弹跳的正方形动画 3D 正多面体 超链接底线动画效果 恶心黏黏球效果 CSS 视差滚动效果 卷轴控制放射形选单 卷轴改变文字背景色 CSS 页面卷动进度条 CSS 水波效果 圆点加载动画 ( 阴影动画 ) 字母翻牌效果 探照灯动画 立体双色跑马灯 楼梯文字动态效果 渐层色文字、双色文字 流动色彩文字 空心文字、文字水波背景 左右倾斜的背景效果 Icon 图示形状变换 故障文字效果 按钮的多种 hover 效果 点击展开或收折的选单 点击爱心图案放射效果 纯 CSS 数字加载进度条 纯 CSS 码表 ( 可计时 )

转换函数 ( transform )

透过 CSS 的 transform 样式属性,就能灵活运用和串接 translate()、translate3d()、rotate()、rotate3d()、scale3d()、skew()、matrix() 和 matrix3d() 等控制变形效果的 CSS 函数,在网页中实现各种变形效果,这篇教学会介绍这些转换函数的用法。

延伸阅读:transform 3D 转换与透视

快速导览:

CSS 教学 - transform 转换函数

CSS 的座标系统

使用 CSS 处理 transform 转换时,会混用“笛卡尔座标系统”以及“球面座标系统”两种座标系统,参考下图,如果要将元素平移,会参考由 XYZ 三轴所组成笛卡尔座标系统 ( 黑色线 ),如果使用球面座标系统 ( 红色线 ),则会让元素绕着三个轴进行旋转。

CSS 教学 - transform 转换函数 - CSS 的座标系统

下图使用四个 div 简单展示两种坐标系统。

CSS 教学 - transform 转换函数 - CSS 的座标系统

transform 转换

transform 是个可以“转换元素外形”的样式属性,默认值为 none,没有继承特性,这个样式会透过一些“CSS 转换函数”,让元素产生平移、旋转、倾斜、尺寸改变等变形效果,下方列出相关的 CSS 函数:

CSS 转换函数 说明
translate(x, y) 在 xy 两轴上的平移。
translateX(d)、translateY(d)、translateZ(d) 分别在 xyz 三轴上的平移。
translate3d(x, y, z) 在 xyz 立体空间的平移。
rotate(deg) 绕着 z 轴的旋转,顺时钟方向为正。
rotateX(deg)、rotateY(deg)、rotateZ(deg) 分别绕着 xyz 三轴旋转,顺时钟方向为正。
rotate3d(x, y, z, deg) 在 xyz 立体空间中绕着 xyz 三轴旋转,顺时钟方向为正。
scale(x, y) 在 xy 两轴上的尺寸变化。
scaleX(d)、scaleY(d)、scaleZ(d) 分别在 xyz 三轴上的尺寸变化。
scale3d(x, y, z) 在 xyz 立体空间的尺寸变化。
skew(x, y) 在 xy 两轴的倾斜角度。
skewX(deg)、skewY(deg) 分别在 xy 两轴的倾斜角度。
matrix(a, b, c, d, tx, ty) 在 xy 平面的矩阵转换。
matrix3d(16 個參數) 在 xyz 立体空间的矩阵转换。
perspective(d) 透视视角。

transform 的写法中,除了可以单独使用一个 CSS 转换函数,也可以使用“串连”的方式,使用“空白”分隔每个转换函数,让元素“变形之后再次变形”,下方呈现单一函数、串连三个函数、五个函数的写法:

div {
  transform: translate(x, y);
  transform: translate(x, y) scaleX(d) rotateY(deg);
  transform: translate(x, y) scaleX(d) rotateY(deg) skewX(ax) rotate(deg);
}

虽然同样都用了平移和旋转的函数,但因为“顺序不同”,最后呈现的结果也有所不同,例如下方范例的两组 div,“先移动再旋转”的 div 会移动到左侧之后再旋转,但“先旋转再移动”的 div 因为 x 轴已经转了 90 渡,因此移动之后就会跑到下方。

线上展示:https://codepen.io/oxxo/pen/GgKgjgv

<!-- HTML 程式碼-->
<div>原本位置</div><div class="a">oxxo</div><div class="b">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
  }
  .a, .b {  
    color: white;
    background: linear-gradient(to left, red, black);
  }
  .a {transform: translateX(150px) rotate(90deg);}  /* 先移動再旋轉 */
  .b {transform:  rotate(90deg) translateX(150px);} /* 先旋轉再移動 */
</style>

CSS 教学 - transform 变形转换 - transform 转换写法“顺序不同”呈现的结果也不同

translate() 平移

CSS 的平移函数有下列几个,内容都是填入具有“长度单位”的数值,建议使用绝对长度单位,如果使用百分比为单位,则会乘以原本尺寸的宽或高。

CSS 平移函数 说明
translate(x, y) 在 xy 两轴上的平移。
translateX(d)、translateY(d)、translateZ(d) 分别在 xyz 三轴上的平移。
translate3d(x, y, z) 在 xyz 立体空间的平移。

下方范例会使用 transform 搭配三种平移函数,移动三个 div 的位置。

线上展示:https://codepen.io/oxxo/pen/KwPwgwr

<!-- HTML 程式碼-->
<div>原本位置</div><div class="a">apple</div><div class="b">banana</div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
  }
  .a, .b, .c {color: white;}
  .a {
    transform: translate(150px, 0);
    background: #f55;
  }
  .b {
    transform: translateX(150px) translateY(150px);
    background: #0a0;
  }
  .c {
    transform: translate3d(0, 150px, 0);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - translate() 平移

操作过程中,因为操作 Z 轴的位移需要搭配“父元素的相机视角”才有反应,如果单纯使用 Z 轴平移,会完全看不出效果,下方范例的红色 div,因为缺少了父元素相机视角,不论有无设定 translateZ 数值都不会发生变化,但蓝色与绿色 div 就会发生变形,越靠近用户就越大,越远就越小 ( 文字和边框也会跟着缩放 )

参考:transform 3D 转换与透视

线上展示:https://codepen.io/oxxo/pen/azozmOz

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b camera"><div>oxxo</div></div>
<div class="co"></div><div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    top: 100px;
  }
  body>div {position: absolute;}
  .ao, .bo, .co {z-index: 2;}          /* 這三個是顯示原本位置與大小 */
  .ao, .a {left: 20px;}
  .bo, .b.camera{left: 200px;}
  .co, .c.camera{left: 380px;}
  .camera {
    transform-style: preserve-3d;      /* 設定內容元素為同一組 */
    perspective:300px;                 /* 相機視角往後移動 300px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a {
    transform: translateZ(150px) translateX;
    background: #f55;
  }
  .b div {
    transform: translateZ(-150px);
    background: #0a0;
  }
  .c div {
    transform: translateZ(150px);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - translate() 操作 Z 轴的位移需要搭配“父元素的相机视角”

rotate() 旋转

CSS 的旋转函数有下列几个,内容都是填入具有“角度单位”的数值。

CSS 旋转函数 说明
rotate(deg) 绕着 z 轴的旋转,顺时钟方向为正。
rotateX(deg)、rotateY(deg)、rotateZ(deg) 分别绕着 xyz 三轴旋转,顺时钟方向为正。
rotate3d(x, y, z, deg) 在 xyz 立体空间中绕着 xyz 三轴旋转,顺时钟方向为正。

下方范例会使用 transform 搭配三种旋转函数,将三个 div 移动到不同的位置,当中 rotate3d(x, y, z, deg) 所使用的 xyz 数值为“后方 deg 的比例”,如果 deg 为 30,设定 0.5 就是 15 度,-2 就是 -60 度。

线上展示:https://codepen.io/oxxo/pen/jENEMPe

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}  /* 標記原始位置 */
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: rotate(50deg);
    background: #f55;
  }
  .b {
    transform: rotateZ(50deg);
    background: #0a0;
  }
  .c {
    transform: rotate3d(0, 0, 1, 50deg);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - rotate() 旋转

操作过程中,如果要绕着 X 或 Y 轴的旋转需要搭配“父元素的相机视角”才有反应,如果单纯绕着 X 或 Y 轴旋转,只会有高度或宽度缩放的效果 ( 类似看着一个方块的“影子放大缩小” ),下方范例的红色 div,因为缺少了父元素相机视角,如果绕着 X 或 Y 轴旋转只会有缩放效果,但蓝色与绿色 div 就会发生变形,产生更为立体的旋转效果 ( 文字和边框也会跟着旋转 )。

参考:transform 3D 转换与透视

线上展示:https://codepen.io/oxxo/pen/JoPoRYG

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b camera"><div>oxxo</div></div>
<div class="co"></div><div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    top: 100px;
  }
  body>div {position: absolute;}         /* 這三個是顯示原本位置與大小 */
  .ao, .bo, .co {
    z-index: 2;
  }
  .ao, .a {  left: 20px;}
  .bo, .b.camera{  left: 180px;}
  .co, .c.camera{  left: 340px;}
  .camera {
    transform-style: preserve-3d;      /* 設定內容元素為同一組 */
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a {
    transform: rotateY(60deg);
    background: #f55;
  }
  .b div {
    transform: rotateY(60deg);
    background: #0a0;
  }
  .c div {
    transform: rotateX(60deg);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - rotate() 绕着 X 或 Y 轴的旋转需要搭配“父元素的相机视角”

scale() 尺寸缩放

CSS 的尺寸缩放函数有下列几个,内容都是填入“没有单位的倍率”数值。

CSS 旋转函数 说明
scale(s) 在 xy 两轴上的尺寸变化。
scaleX(s)、scaleY(s)、scaleZ(s) 分别在 xyz 三轴上的尺寸变化。
scale3d(x, y, z) 在 xyz 立体空间的尺寸变化。

下方范例会使用 transform 搭配三种尺寸缩放函数,将三个 div 缩放为相同的大小。

线上展示:https://codepen.io/oxxo/pen/PwYwGPE

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}  /* 標記原始位置尺寸 */
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: scale(1.5);
    background: #f55;
  }
  .b {
    transform: scaleX(1.5) scaleY(1.5);
    background: #0a0;
  }
  .c {
    transform: scale3d(1.5, 1.5, 1);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - scale() 尺寸缩放

由于网页元素本身没有“厚度”( Z 轴尺寸 ),只有将多个不同 Z 轴位置的元素组合后,才会产生 Z 轴方向的厚度,因此如果要针对 Z 轴缩放,就需要额外设定“父元素场景”以及“场景的父元素的相机视角”,下方范例的红色 div,因为缺少了场景与父元素相机视角,呈现效果仍然会是平面效果,但另外两个 div 是由场景和元素所构成,就可以看见设定 scaleZ() 之后,对于厚度产生了影响。

参考:transform 3D 转换与透视

线上展示:https://codepen.io/oxxo/pen/mybyrVM

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b camera">
  <div class="space">
    <div>oxxo</div><div>oxxo</div>
  </div>
</div>
<div class="co"></div>
<div class="c camera">
  <div class="space">
    <div>oxxo</div><div>oxxo</div>
  </div>
</div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    position: absolute;
  }
  body>div {top: 100px;}
  .ao, .bo, .co {
    z-index: 2;
  }
  .ao, .a {left: 20px;}
  .bo, .b.camera{left: 180px;}
  .co, .c.camera{left: 340px;}
  .camera {
    perspective: 100px;                  /* 相機視角 */
    perspective-origin:center center;
  }
  .a {
    transform:  rotateY(60deg) scaleZ(1.5);
    background: #f55;
  }
  .b .space {
    transform-style: preserve-3d;
    transform: rotateY(60deg) scaleZ(1.5);  /* 整個場景旋轉和縮放 */
    border: none;
  }
  .b .space div:nth-child(1) {
    transform: translateZ(20px);            /* 場景內容元素調整位置 */
    background: #0a0;
  }
  .b .space div:nth-child(2) {
    transform: translateZ(-20px);           /* 場景內容元素調整位置 */
    background: #0a0;
  }

  .c .space {
    transform-style: preserve-3d;
    transform: rotateY(60deg) scaleZ(0.5);  /* 整個場景旋轉和縮放 */
    border: none;
  }
  .c .space div:nth-child(1) {
    transform: translateZ(20px);            /* 場景內容元素調整位置 */
    background: #09f;
  }
  .c .space div:nth-child(2) {
    transform: translateZ(-20px);           /* 場景內容元素調整位置 */
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - scaleZ() 额外设定“父元素场景”以及“场景的父元素的相机视角”

skew() 倾斜

CSS 的尺寸缩放函数有下列几个,内容都是填入“倾斜的角度”数值。

CSS 旋转函数 说明
skew(x, y) 在 xy 两轴的倾斜角度。
skewX(deg)、skewY(deg) 分别在 xy 两轴的倾斜角度。

下方范例会使用 skew 搭配倾斜函数,将三个 div 倾斜为不同的角度。

线上展示:https://codepen.io/oxxo/pen/pvzvEgG

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 100px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: skew(30deg, 30deg);
    background: #f55;
  }
  .b {
    transform: skewX(30deg);
    background: #0a0;
  }
  .c {
    transform: skewY(30deg);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - skew() 倾斜

matrix() 2D 矩阵

matrix() 是透过“矩阵”让元素进行“2D 变换”的转换公式,matrix() 具有六个参数,这六个参数会组成 2x3 的矩阵,虽然 matrix() 在表面上是 2x3 矩阵,但本质其实是 3x3 的矩阵,因为 matrix() 是针对 xy 平面的函数,在 Z 轴的参数保持不变的状况下,可直接使用 2x3 矩阵进行运算。

CSS 教学 - transform 变形转换 - matrix() 矩阵本质是 3x3 的矩阵

matrix() 的六个参数都有各自的意义,分别对应平移、旋转、缩放和倾斜的函数,对照公式如下:

matrix 写法 对照其他转换函数
matrix(1, 0, 0, 1, x, y) translate(x, y)
matrix(cos(deg), sin(deg), -sin(deg), cos(deg), 0, 0) rotate(deg)
matrix(a, 0, 0, b, 0, 0) scale(a, b)
matrix(1, tan(y_deg), tan(x_deg), 1, 0, 0) skew(x_deg, y_deg) ( 注意 x 和 y 的位置 )

使用 matrix() 时不需要数值单位,会自动转换成“绝对长度”、“放大倍率”和“角度”,下方范例透过 matrix() 函数,产生平移、旋转、缩放和倾斜的效果。

线上展示:https://codepen.io/oxxo/pen/ogvgzxz

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b">oxxo</div>
<div class="co"></div>
<div class="c">oxxo</div>
<div class="do"></div>
<div class="d">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    left: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {top: 50px;}
  .bo, .b {top: 180px;}
  .co, .c {top: 310px;}
  .do, .d {top: 440px;}
  .a {
    transform: matrix(1, 0, 0, 1, 50, -20);
    /* 等同 transform: translate(50px, -20px); */
    background: #f55;
  }
  .b {
    transform: matrix(0.707, 0.707, -0.707, 0.707, 0, 0);
    /* 等同 transform: rotate(45deg); */
    /* sin(45deg)=0.707    cos(45deg)=0.707 */
    background: #f90;
  }
  .c {
    transform: matrix(1.5, 0, 0, 0.8, 0, 0);
    /* 等同 transform: scale(1.5, 0.8); */
    background: #0a0;
  }
  .d {
    transform: matrix(1, 0.577, 0.577, 1, 0, 0);
    /* 等同 transform: skew(30deg, 30deg); */
    /* tan(30deg)=0.577 */
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - matrix() 2D 矩阵

如果要“串连多个转换函数”,矩阵的处理就必须要扩展为 3x3 的矩阵运算,透过“矩阵的相乘”就能计算出最后的结果 ( 可使用“矩阵计算机”)。

CSS 教学 - transform 变形转换 - matrix() 矩阵的相乘

下方范例会根据上图的计算结果,让三个 div 分别使用“串联四种转换函数”、“四个 matrix()”以及“计算后成为单一个 matrix() 函数”的三种方式,产生出完全相同的效果。

线上展示:https://codepen.io/oxxo/pen/wBwBzGj

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b">oxxo</div>
<div class="co"></div>
<div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 80px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 50px;}
  .bo, .b {left: 180px;}
  .co, .c {left: 310px;}
  .a {
    transform: translate(20px, 50px)
               scale(1.2, 1.2)
               rotate(45deg)
               skew(30deg, 30deg);
    background: #f55;
  }
  .b {
    transform: matrix(1, 0, 0, 1, 20, 50) 
               matrix(1.2, 0, 0, 1.2, 0, 0) 
               matrix(0.707, 0.707, -0.707, 0.707, 0, 0)
               matrix(1, 0.577, 0.577, 1, 0, 0);
    background: #f90;
  }
  .c {
    transform: matrix(0.359, 1.338, -0.359, 1.338, 20, 50);
    background: #0a0;
  }
</style>

CSS 教学 - transform 变形转换 - 计算后成为单一个 matrix() 函数

matrix3d() 3D 矩阵

matrix3d() 是透过“矩阵”让元素进行“3D 变换”的转换公式*,matrix3d() 具有 16 个参数,这六个参数会组成 4x4 的矩阵。

CSS 教学 - transform 变形转换 - matrix3d() 3D 矩阵

matrix3d() 的 16 个参数都有各自的意义,平移对照公式如下:

div {
  transform: matrix3d( 1,   0,   0,   0,
                       0,   1,   0,   0,
                       0,   0,   1,   0,
                       x,   y,   z,   1);
  /* 等同 transform: transform: translate3d(x, y, z); */
}

尺寸缩放对照公式如下:

div {
  transform: matrix3d( x,   0,   0,   0,
                       0,   y,   0,   0,
                       0,   0,   z,   0,
                       0,   0,   0,   1);
  /* 等同 transform: transform: scale3d(x, y, z); */
}

旋转对照公式如下:

div {
  transform: matrix3d( 1,         0,          0,   0,
                       0,  cos(deg),   sin(deg),   0,
                       0, -sin(deg),   cos(deg),   0,
                       0,         0,          0,   1);
  /* 等同 transform: transform: rotateX(deg); 繞 x 旋轉 */

  transform: matrix3d( cos(deg),   0,  -sin(deg),   0,
                              0,   1,          0,   0,
                       sin(deg),   0,   cos(deg),   0,
                              0,   0,          0,   1);
  /* 等同 transform: transform: rotateY(deg); 繞 y 旋轉 */

  transform: matrix3d( cos(deg),   sin(deg),   0,   0,
                      -sin(deg),   cos(deg),   0,   0,
                              0,          0,   1,   0,
                              0,          0,   0,   1);
  /* 等同 transform: transform: rotateZ(deg); 繞 z 旋轉 */
}

倾斜对照公式如下:

div {
  transform: matrix3d( 1,          tan(y_deg),   0,   0,
                       tan(x_deg),          1,   0,   0,
                       0,                   0,   1,   0,
                       0,                   0,   0,   1);
  /* 等同 transform: transform: skew(x_deg, y_def); */
}

使用 matrix3d() 时不需要数值单位,会自动转换成“绝对长度”、“放大倍率”和“角度”,下方范例透过 matrix() 函数,产生平移、旋转、缩放和倾斜的效果。

线上展示:https://codepen.io/oxxo/pen/yyByaOw

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a camera"><div>oxxo</div></div>
<div class="bo"></div>
<div class="b camera"><div>oxxo</div></div>
<div class="co"></div>
<div class="c camera"><div>oxxo</div></div>
<div class="do"></div>
<div class="d camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    left: 100px;
  }
  body>div {position: absolute;}       /* 這四個是顯示原本位置與大小 */
  .ao, .bo, .co {z-index: 2;}
  .ao, .a.camera {top: 50px;}
  .bo, .b.camera {top: 180px;}
  .co, .c.camera {top: 310px;}
  .do, .d.camera {top: 440px;}
  .camera {
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a div {
    transform: matrix3d( 1,    0,    0,  0,
                         0,    1,    0,  0,
                         0,    0,    1,  0,
                        20,   20,  -20,  1);
    /* 等同 transform: translate3d(20px, 20px, -20px); */
    background: #f55;
  }
  .b div {
    transform: matrix3d( 2,      0,      0,  0,
                         0,    0.8,      0,  0,
                         0,      0,    0.5,  0,
                         0,      0,      0,  1);
    /* 等同 transform: scale3d(2, 0.8, 0.5); */
    background: #0a0;
  }
  .c div {
    transform: matrix3d( 1,       0,       0,  0,
                         0,   0.707,   0.707,  0,
                         0,  -0.707,   0.707,  0,
                         0,       0,       0,  1);
    /* 等同 transform: rotateX(45deg); */
    background: #09f;
  }
  .d div {
    transform: matrix3d(    1,   0.268,   0,  0,
                        0.268,       1,   0,  0,
                            0,       0,   1,  0,
                            0,       0,   0,  1);
    /* 等同 transform: skew(15deg, 15deg); */
    background: #f90;
  }
</style>

CSS 教学 - transform 变形转换 - matrix3d() 3D 矩阵

如果要“串连多个转换函数”,matrix3d() 可以像 matrix() 一样,透过“矩阵的相乘”计算出最后的结果,但需要特别注意 CSS 的 matrix3d() 矩阵在计算时会先进行“转置矩阵”,计算完成后再透过转置矩阵转回原本的格式 ( 使用“矩阵计算机”)。

CSS 教学 - transform 变形转换 - matrix3d() 矩阵相乘需要进行矩阵转置

下方范例会根据上图的计算结果,让三个 div 分别使用“串联三种转换函数”、“三个 matrix3d()”以及“计算后成为单一个 matrix3d() 函数”的三种方式,产生出完全相同的效果。

线上展示:https://codepen.io/oxxo/pen/VYZYKjp

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a camera"><div>oxxo</div></div>
<div class="bo"></div>
<div class="b camera"><div>oxxo</div></div>
<div class="co"></div>
<div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    left: 50px;
  }
  body>div {position: absolute;}         /* 這三個是顯示原本位置與大小 */
  .ao, .bo, .co {z-index: 2;}
  .ao, .a.camera {top: 50px;}
  .bo, .b.camera {top: 200px;}
  .co, .c.camera {top: 350px;}
  .camera {
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a div {
    transform: translate3d(20px, 20px, 10px) rotateZ(30deg) rotateY(30deg);
    background: #f55;
  }
  .b div {
      transform: matrix3d( 1,    0,   0,  0,
                           0,    1,   0,  0,
                           0,    0,   1,  0,
                          20,   20,  10,  1)
                matrix3d( 0.866,    0.5,   0,  0,
                           -0.5,  0.866,   0,  0,
                              0,      0,   1,  0,
                              0,      0,   0,  1)
                matrix3d( 0.866,   0,   -0.5,  0,
                              0,   1,      0,  0,
                            0.5,   0,  0.866,  0,
                              0,   0,      0,  1);
    background: #0a0;
  }
  .c div {
      transform: matrix3d( 0.75,   0.433,   -0.5,  0,
                          -0.5,   0.866,      0,  0,
                          0.433,    0.25,  0.707,  0,
                            20,      20,     10,  1);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - 计算后成为单一个 matrix3d() 函数

perspective() 透视距离

perspective() 可以设定“元素和用户之间的距离”,距离使用“大于 1px”并具有“长度单位”的数值,当距离越大时,元素的“透视变形程度”就越小,当距离越小时,元素的“透视变形程度”就越大,如果设定为 none 表示距离无限远,不会发生透视变形的状况,下图为 W3C 所定义的规范,d 为透视距离,Z 为元素本身在 Z 轴的位移,若 d 小于 1px 会直接使用 1px 作为数值。

CSS 教学 - transform 变形转换 - W3C perspective() 透视距离

下方范例会呈现 100px、50px 和 none 的透视变形差异,虽然都绕着 X 轴旋转,但因为透视变形的关系,看到的效果就会不同,类似使用“望远镜头”和“广角镜头”所拍摄的照片差异。

线上展示:https://codepen.io/oxxo/pen/XJrmrwg

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b">oxxo</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 100px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: perspective(100px) rotateX(30deg);
    background: #f55;
  }
  .b {
    transform: perspective(60px) rotateX(30deg);
    background: #0a0;
  }
  .c {
    transform: perspective(none) rotateX(30deg);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - perspective() 透视距离

因为 perspective() 属于 CSS 的函数,在 transform 使用时需要注意“串连函数”的“顺序”,如果将 perspective() 摆在其他转换函数的后方,会因为串连的缘故,前方的转换都不会套用透视效果,加上每个元素如果都有自己的透视距离,在视觉上会显得不协调,建议参考“transform 3D 转换与透视”,使用整体的透视效果会更好。

下方范例将 perspective() 摆在其他转换函数的后方,呈现时就会没有效果 ( 后方又有函数时,就会套用透视进行转换 )

线上展示:https://codepen.io/oxxo/pen/JoPYjjL

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b">oxxo</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    left: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {top: 50px;}
  .bo, .b {top: 180px;}
  .co, .c {top: 310px;}
  .a {
    transform: rotateX(30deg) rotateX(30deg) perspective(100px);
    background: #f55;
  }
  .b {
    transform: rotateX(30deg) perspective(100px) rotateX(30deg) ;
    background: #0a0;
  }
  .c {
    transform: perspective(100px) rotateX(30deg) rotateX(30deg);
    background: #09f;
  }
</style>

CSS 教学 - transform 变形转换 - perspective() 只会对后方转换函数有作用

小结

目前几乎所有的浏览器都支援 transform 样式属性以及相关的 CSS 转换函数,只要轻松转写几行 CSS,就能实现许多有趣又吸睛的视觉效果。

继续阅读:transform 3D 转换与透视

意见反馈

微信二维码 微信扫码关注 抖音二维码 抖音扫码关注