「响应式网页设计」 CSS应用基础设计

CSS visual design

Posted by Mingyu on April 27, 2022

基本属性

使用 text-align 属性创建视觉平衡

这部分的主题是应用视觉设计。 开始的挑战基于美化一个卡片组件的外观,借此展示了若干核心原则。

web 内容大部分都是文本。 CSS 里面的 text-align 属性可以控制文本的对齐方式。

text-align: justify; 将文本隔开,使每行的宽度相等,也即两端对齐。

text-align: center; 可以让文本居中对齐。

text-align: right; 可以让文本右对齐。

text-align: left; 是默认值,它可以让文本左对齐。

使用 width 属性调整元素的宽度

你可以使用 CSS 里的 width 属性来指定元素的宽度。 属性值可以是相对单位(比如 em),绝对单位(比如 px),或者包含块(父元素)宽度的百分比。 下面这段代码可以把图片的宽度设置为 220px:

1
2
3
img {
  width: 220px;
}

使用 height 属性调整元素的宽度

width 属性类似,你可以使用 CSS 里面的 height 属性来指定元素的高度。 下面这段代码可以把图片的高度设置为 20px:

1
2
3
img {
  height: 20px;
}

使用 strong 标签加粗文本

你可以使用 strong 标签来加粗文字。 粗体文字一般用来吸引读者注意或用来表示强调。 添加了 strong 标签后,浏览器会自动给元素添加这段样式:font-weight:bold;

使用 u 标签给文本添加下划线

你可以使用 u 标签来给文字添加下划线。 下划线通常用来表示重要内容或需要记忆的内容。 添加了 u 标签后,浏览器会自动给元素添加这段样式:text-decoration: underline;

使用 em 标签强调文本

你可以使用 em 标签来强调文本。 由于浏览器会自动给元素应用 font-style: italic;,所以文本会显示为斜体。

使用 s 标签给文本添加删除线

你可以用 s 标签来给文字添加删除线。 删除线是位于文字水平中央的一条线,它代表着一段文字不再有效。 添加了 s 标签后,浏览器会自动给元素添加这段样式:text-decoration: line-through;

使用 hr 标签创建水平线

你可以用 hr 标签来创建一条宽度撑满父元素的水平线。 这种水平分割线一般用来表示内容主题的改变,或在视觉上将文档分隔成几个部分。

注意: HTML 中的 hr 是自闭合标签,所以我们不需要为它添加结束标签。

调整文本的背景色

为了让页面更美观,除了设置整个页面的背景色以及文字颜色外,你还可以单独设置文字的背景色,即在文字的父元素上添加 background-color 属性。 在本挑战里我们将使用 rgba() 颜色,而不是之前学到的 hex 编码或者 rgb() 颜色。

rgba 代表: r = red 红色 g = green 绿色 b = blue 蓝色 a = alpha 透明度

RGB 值可以取在 0 到 255 之间。 alpha 值可取在 0 到 1 之间,其中 0 代表完全透明,1 代表完全不透明。 rgba() 在需要设置颜色透明度时十分有用, 这意味着你可以做出一些很漂亮的半透明效果。

在本挑战里你将会用到这个代码 background-color: rgba(45, 45, 45, 0.1)。 它表示背景是黑灰色,因为设置了透明度为 0.1,所以几乎是透明的。

调整标题元素与段落元素的大小

标题元素(h1h6)的字体大小通常应大于段落标签的字体大小。 这使用户更容易直观地了解页面上所有内容的布局和重要性级别。 你可以使用 font-size 属性来调整元素中文本的大小。

给卡片元素添加 box-shadow

box-shadow 属性用来给元素添加阴影,该属性值是由逗号分隔的一个或多个阴影列表。

box-shadow 属性按顺序采用以下值:

  • offset-x (阴影的水平偏移量),
  • offset-y (阴影的垂直偏移量),
  • blur-radius(高斯模糊,数字越大越模糊,默认值是0,表示一点也不进行模糊)
  • spread-radius(在应用模糊之前,框应该膨胀的量,比如说,本来容器是100x100的,加上spreadRadius半径50, 阴影色块的初始大小就变成了(100 + 2 * 50) x (100 + 2 * 50) 了。然后再进行高斯模糊)
  • color

其中 blur-radiusspread-radius 是可选的。

可以通过逗号分隔每个 box-shadow 元素的属性来添加多个 box-shadow。

如下为添加了模糊效果的例子,它使用了透明度较高的黑色作为阴影:

1
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);

这里再总结一下blurRadius和spreadRadius的区别:

  1. blurRadius是高斯模糊的程度,spreadRadius是阴影的大小。
  2. 在一定范围内,增大blurRadius能使阴影扩散范围变大,但是过了阈值,继续增大blurRadius阴影大小不会变大。但spreadRadius能持续变大。

降低元素的透明度

CSS 里的 opacity 属性用来设置元素的透明度。

属性值为 1 代表完全不透明。 属性值为 0.5 代表半透明。 属性值为 0 代表完全透明。

透明度会应用到元素内的所有内容,不论是图片,还是文本,或是背景色。

使用 text-transform 属性给文本添加大写效果

CSS 里的 text-transform 属性可以改变英文字母的大小写。 使用这个属性时,我们无需改变 HTML 元素中的文本也可以统一页面里英文的显示。

下面的表格展示了 text-transform 的不同值对文字 “Transform me” 的影响:

结果
lowercase “transform me”
uppercase “TRANSFORM ME”
capitalize “Transform Me”
initial 使用默认值
inherit 使用父元素的 text-transform 值。
none Default:不改变文字。

设置 font-size

font-size 属性用来指定元素内文字的大小。 我们可以为多个元素添加这个规则,让页面内不同元素的文字大小得以统一。 在本挑战里,你需要设置从 h1h6 的文字大小。

设置 font-weight

在上一个挑战里我们已经为每个标题设置了 font-size,接下来我们将要设置 font-weight

font-weight 属性用于设置文本中字体的粗细。

设置段落文本的 font-size

CSS 里面的 font-size 属性不只限于标题,还可以应用于任何包含文字的元素内。

理解绝对单位与相对单位

像素是一个长度单位,它告诉浏览器应该如何调整元素的大小和位置。 其实除了 px,CSS 也有其他单位供我们使用。

单位长度的类型可以分成 2 种:相对和绝对。 绝对单位与长度的物理单位相关。 例如,inmm 分别代表着英寸和毫米。 绝对长度单位会接近屏幕上的实际测量值,不过不同屏幕的分辨率会存在差异,这就可能会造成误差。

相对单位长度,比如 emrem,它们的实际值会依赖其他长度的值而决定。 比如 em 的大小基于元素字体的字体大小。 如果使用它来设置 font-size 值,它的值会跟随父元素的 font-size 值来改变。

Note: 有些单位长度选项是相对视窗大小来改变值的, 这种设定符合响应式网页设计的原则。

设置段落的 line-height

CSS 提供 line-height 属性来设置行间的距离。 行高,顾名思义,可以用来设置每行文字所占据的垂直空间。

调整锚点的悬停状态

本挑战将要涉及到伪类。 伪类是可以添加到选择器上的关键字,用来选择特定状态的元素。

比如,可以使用 :hover 伪类选择器来选取超链接的悬停状态。 下面的代码可以在鼠标悬停在超链接上时将其 color 变成红色:

1
2
3
a:hover {
  color: red;
}

创建一个自定义的 CSS 变量

为创建一个 CSS 变量,你只需要在变量名前添加两个连字符号,并为其赋值即可,例子如下:

1
--penguin-skin: gray;

这样就会创建一个 --penguin-skin 变量,它的值为 gray。 现在你可以在你的 CSS 中的其他地方使用这个变量来改变其他属性的值为灰色。

使用变量来作为 CSS 属性值的时候,可以设置一个备用值来防止由于某些原因导致变量不生效的情况。

注意: 备用值不是用于增强浏览器的兼容性,它也不适用于 IE 浏览器。 相反,它是用来让浏览器在找不到你的变量时可以显示一种颜色。

下面是操作方式:

1
background: var(--penguin-skin, black);

如果你的变量没有设置,这将会把背景设置为 black。 提示:这对调试代码也会很有帮助。

当创建一个变量时,变量会在创建变量的选择器里可用。 同时,在这个选择器的后代选择器里也是可用的。 这是因为 CSS 变量是可继承的,和普通的属性一样。

CSS 变量经常会定义在 :root 元素内,这样就可被所有选择器继承。

:root 是一个伪类选择器,它是一个能够匹配文档根元素的选择器,通常指的是 html 元素。 我们在 :root 里创建变量在全局都可用,即在任何选择器里都生效。

1
2
3
4
5
6
7
:root {
    --penguin-belly: pink;
}

body {
    background: var(--penguin-belly, #c6faf1);
}

位置

更改元素的相对位置

在 CSS 里一切 HTML 元素皆为盒子,也就是通常所说的盒模型。 块级元素自动从新的一行开始(比如标题、段落以及 div),行内元素排列在上一个元素后(比如图片以及 span)。 元素默认按照这种方式布局称为文档的普通流,同时 CSS 提供了 position 属性来覆盖它。

当元素的定位设置为 relative 时,它允许你通过 CSS 指定该元素在当前文档流页面下的相对偏移量。 CSS 里控制各个方向偏移量的属性是 leftrighttopbottom。 它们代表从原来位置向远离该方向偏移指定的像素、百分比或者 em。 下面的例子展示了段落向上偏移 10px:

1
2
3
4
p {
  position: relative;
  bottom: 10px;
}

把元素的位置设置成相对,并不会改变该元素在布局中所占的位置,也不会对其它元素的位置产生影响。

注意: 定位可以使页面布局更灵活、高效。 不管元素的定位是怎样的,HTML 标记在从上到下阅读起来时应该是整洁的、有意义的。 这样可以让视障人士(重度依赖辅助设备比如屏幕阅读软件的人们)也能够无障碍地浏览你的网页。

使用 CSS 偏移移动相对定位的元素

CSS 里面的 topbottomleftright 定义了元素在相应方位的偏移距离。 元素将从当前位置向属性相反的方向偏移。 就像你在上一个挑战看到的,top 属性使 h2 向下移动。 同样,使用 left 将项目移动到右边。

绝对定位的参照物是元素的父元素

接下来要介绍 CSS position 属性的取值选项 absolute,它的含义是相对于其包含块定位。 和 relative 定位不一样,绝对定位会将元素从当前的文档流里面移除,周围的元素会忽略它。 这样我们就可以用 CSS 的 top、bottom、left、right 属性来调整元素的位置。

绝对定位比较特殊的一点是元素的定位参照于最近的 positioned 祖先元素。 如果它的父元素没有添加定位规则,浏览器会继续寻找直到默认的 body 标签。absolute定位的基准是相对于最近一级的不是默认值static的父元素(可以是absolute/relative/fixed等)来进行定位的,而不仅仅是相对于为position为relative的父级元素。父级元素还可以是absolute、fixed定位

固定定位的参照物是浏览器的窗口

接下来要介绍的是 fixed 定位,它是一种特殊的绝对(absolute)定位,将元素相对于浏览器窗口定位。 类似于绝对位置,它与 CSS 偏移属性一起使用,并且也会将元素从当前的文档流里面移除。 其它元素会忽略它的存在,这样也许需要调整其他位置的布局。

fixedabsolute 的最明显的区别在于,前者定位的元素不会随着屏幕滚动而移动。

使用 float 属性将元素左浮动或右浮动

接下来要介绍的定位机制并不是 position 属性的选项,而是通过元素的 float 属性来设置。 浮动元素不在文档流中,它向 leftright 浮动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。 通常需要用 width 属性来指定浮动元素占据的水平空间。

1
2
3
4
5
6
7
8
#left {
    float:left;
    width: 50%;
}
#right {
    float:right;
    width: 40%;
}

使用 z-index 属性更改重叠元素的位置

当一些元素在位置上重叠时(例如,使用 position: absolute | relative | fixed | sticky 时),在 HTML 里后出现的元素会默认显示在更早出现的元素的上面。 你可以使用 z-index 属性指定元素的堆叠次序。 z-index 的取值是整数,数值大的元素会叠放到数值小的元素上面。

使用 margin 属性将元素水平居中

在应用设计中经常需要把一个块级元素水平居中显示。 一种常见的实现方式是把块级元素的 margin 值设置为 auto。

同样的,这个方法也对图片奏效。 图片默认是内联元素,但是可以通过设置其 display 属性为 block来把它变成块级元素。

颜色

了解互补色

色彩理论以及设计色彩学很复杂,这里将只涉及基础部分。 在网站设计里,颜色能让内容更醒目,能调动情绪,从而创造舒适的视觉体验。 不同的颜色组合对网站的视觉效果影响很大,精妙的设计都需要适宜的颜色来美化页面内容。

色环是我们认识颜色关系的好工具。它是一个近色相邻、异色相离的圆环。 当两个颜色恰好在色环的两端时,这两个颜色就互为补色。 两个互为补色的颜色会在混合后变成灰色。 然而,补色搭配能形成强烈的视觉对比效果。

下面是一些以 hex 形式表示的补色例子:

红色(#FF0000)和蓝绿色 (#00FFFF) 绿色(#00FF00)和品红色(#FF00FF) 蓝色(#0000FF)和黄色(#FFFF00)

这与我们许多人在学校学的过时的 RYB 色彩模式不同,RYB 有不同的原色和补色。 现代色彩理论使用 RGB 模型(如在计算机屏幕上)和 CMY(K)模型(如在印刷中)。

现在,很多在线选色工具也为我们提供了寻找补色的功能。

注意: 对于颜色相关的挑战:颜色搭配是提起用户兴趣或吸引用户注意的重要方式之一。 但我们不应让颜色作为传达重要信息的唯一方式,因为视觉障碍用户可能无法像其他人一样看出其中的含义。 我们将会在应用无障碍章节进行详细介绍。

了解三次色

电脑显示器和各类屏幕都是基于颜色叠加的模型:将红(R)、绿(G)、蓝(B)三原色的色光以不同的比例相加,就可以产生各种色彩光。 这在现代色彩理论中叫作三原色光模式(RGB Color Model)。 红色(R)、绿色(G)和蓝色(B)叫作三原色。 如果把两种原色相加,就可以产生二次色:蓝绿(G+B)、品红(R+B)和黄色(R+G), 我们在上一个挑战里已经见过这些颜色了。 这些二次色恰好是在合成它们时未使用的原色的补色,即在色环中位于两端。 例如,品红色是红色和蓝色相加产生,它是绿色的补色。

三次色是由原色和二次色相加产生的颜色, 例如,在 RGB 颜色模型中,红色(原色)和黄色(二次色)相加产生橙色(三次色)。 将这六种颜色中相邻的颜色相加,便产生了十二色色环。

设计里面有很多种颜色搭配方法。 涉及到三次色的一种配色方法是分裂补色搭配法。 选定主色之后,在色环上选择与它的补色相邻的两种颜色与之搭配。 此种搭配既有对比,又不失和谐。

下面是使用分裂补色搭配法创建的三个颜色:

颜色 HEX 颜色码
橙色 #FF7F00
蓝绿色 #00FFFF
树莓红 #FF007F

将各种元素的颜色调整为互补色

通过前面关卡的学习,我们知道了补色搭配能形成强列的对比效果,让内容更富生机。 但是如果使用不当效果会适得其反:比如将文字背景色和文字颜色设置为互补色,这样文字会很难看清。 通常的做法是,一种颜色做为主要颜色,然后使用其补色用来装点那些需要用户特别注意的部分。

使用深青色(#09A7A1)做为页面主色,用其补色橙色(#FF790E)来装饰登录按钮。 把 headerfooterbackground-color 从黑色改成深青色。 然后把 h2 的文字 color 也改成深青色。 最后,把 buttonbackground-color 改成橙色。

调整颜色的色相

颜色具有多种特性,包括色相、饱和度和亮度。 CSS3 引入了hsl()函数,作为直接说明这些特征来挑选颜色的替代方法。

色相 是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。 以颜色光谱为例,光谱左边从红色开始,移动到中间的绿色,一直到右边的蓝色,色相值就是沿着这条线的取值。 在 hsl() 里面,色相用色环来代替光谱,色相值就是色环里面的颜色对应的从 0 到 360 度的角度值。

饱和度 是指色彩的纯度,也就是颜色里灰色的占比。 饱和度越高则灰色占比越少,色彩也就越纯;反之则完全是灰色。 饱和度的取值范围是表示灰色所占百分比的 0 至 100。

亮度 决定颜色的明暗程度,也就是颜色里白色或者黑色的占比。 其中,100% 的亮度表示纯白色, 0% 的亮度则表示纯黑色;而 50% 的亮度就表示在色相中选取的颜色。

下面是一些使用 hsl() 描述颜色的例子,颜色都为满饱和度,中等亮度:

颜色 HSL
hsl(0, 100%, 50%)
hsl(60, 100%, 50%)
绿 hsl(120, 100%, 50%)
蓝绿 hsl(180, 100%, 50%)
hsl(240, 100%, 50%)
品红 hsl(300, 100%, 50%)

调整颜色的色调

hsl() 使 CSS 更改颜色色调更加方便。 比如,给一个纯色添加白色可以调出更浅的色调;添加黑色可以创造更深的色调。 另外,还可以通过给纯色添加灰色来同时改变颜色的深浅和明暗。 回忆下 hsl() 里面的 ‘s’ 和 ‘l’ 分别代表饱和度和亮度。 饱和度代表灰色的占比,亮度代表白色和黑色的占比。 这在你想获取一个基准色的变种的情景下会十分有用。

创建一个 CSS 线性渐变

HTML 元素的背景色并不局限于单色。 CSS 还为我们提供了颜色渐变。 可通过 background 里的 linear-gradient() 实现线性渐变, 以下是它的语法:

1
background: linear-gradient(gradient_direction, color 1, color 2, color 3, ...);

第一个参数指定了颜色过渡的方向——它的值是角度,90deg 表示垂直渐变(从左到右),45deg 表示沿对角线渐变(从左下方到右上方)。 其他参数指定了渐变颜色的顺序:

例如:

1
background: linear-gradient(90deg, red, yellow, rgb(204, 204, 255));

使用 CSS 线性渐变创建条纹元素

repeating-linear-gradient() 函数和 linear-gradient() 很像,主要区别是前者会重复指定的渐变。 repeating-linear-gradient() 有很多参数,为了便于理解,本关只用到角度值和色标。

角度就是渐变的方向。 色标代表渐变颜色及发生渐变的位置,由百分比或者像素值表示。

在代码编辑器的例子里,渐变开始于 0 像素位置的 yellow,然后过渡到距离开始位置 40 像素的 blue。 由于下一个渐变颜色的起始位置也是 40 像素,所以颜色直接渐变成第三个颜色值 green,然后过渡到距离开始位置 80 像素的 red

下面的代码可以帮助理解成对的起止渐变颜色值是如何过渡的。

1
0px [yellow -- blend -- blue] 40px [green -- blend -- red] 80px

如果每对起止渐变颜色值的颜色都是相同的,由于是在两个相同的颜色间过渡,那么中间的过渡色也为同色,接着就是同色的过渡色和下一个起止颜色,最终产生的效果就是条纹。

使用 repeating-linear-gradient() 函数创建一个渐变角度为 45deg 的条纹,然后设置第一对渐变颜色为 yellow,第二对渐变颜色为 black

1
2
3
4
5
6
7
background: repeating-linear-gradient(
    45deg,
    yellow 0px,
    yellow 40px,
    black 40px,
    black 80px
);

通过添加细微图案作为背景图像来创建纹理

为了增加背景图的质感,我们可以为它添加一个不那么明显的纹理图案,这样可以让页面更讨喜。 但关键在于,我们需要找到一个平衡点,因为我们不希望背景图抢占了内容的风头,造成喧宾夺主的结果。 background 属性支持使用 url() 函数作为属性值,这让我们可以通过链接的方式引入纹理或样式的图片。 图片链接的地址应写在括号内,一般会用引号包起来。

形状

使用 CSS Transform scale 属性可以更改元素的大小

CSS 属性 transform 里面的 scale() 函数可以用来改变元素的显示比例。 下面的例子把页面的段落元素放大到了原来的 2 倍:

1
2
3
p {
  transform: scale(2);
}

使用CSS Transform scale 属性在悬停时缩放元素

transform 属性有很多函数可以调用,可以对元素进行调整大小、移动、旋转、翻转等操作。 当使用伪类选取元素的指定状态(如 :hover)时,我们可以通过 transform 属性非常方便地给元素添加交互。

下面是当用户悬停在段落元素时,段落大小缩放到原始大小 2.1 倍的例子:

1
2
3
p:hover {
  transform: scale(2.1);
}

注意:div 元素添加 transform 也会影响这个 div 包裹的子元素。

使用 CSS Transform skex 属性沿X轴倾斜元素

接下来要介绍的 transform 属性是 skewX():它使选择的元素沿着 X 轴(横向)倾斜指定的角度。

下面的代码沿着 X 轴倾斜段落元素 -32 度。

1
2
3
p {
  transform: skewX(-32deg);
}

使用 CSS Transform skex 属性沿Y轴倾斜元素

skewX 函数使指定元素沿 X 轴翻转指定的角度,想必你已经猜到了,skewY 属性使指定元素沿 Y 轴(垂直方向)翻转指定角度。

使用 CSS 创建一个图形

通过使用不同的选择器和属性,你可以做出有趣的形状, 一个简单的例子是新月形状。 在这个挑战中,我们会学习如何使用 box-shadow 属性来设置元素的阴影,以及使用 border-radius 属性控制元素的圆角边框。

首先我们来创建一个圆的、透明的图形,它具有模糊阴影并略微向两边递减。 如你所见,这个阴影其实就是新月形狀。

为了创建一个圆形的对象,border-radius 应该被设置成 50%。

你应该还记得之前关卡的 box-shadow 属性以及它的依次取值 offset-xoffset-yblur-radiusspread-radiuscolor 值。 其中 blur-radiusspread-radius 是可选的。

把编辑器变成新月形状。 首先,把 background-color 改为 transparent,接着把 border-radius 属性设置成 50%,以创建一个圆形。 最后,更改 box-shadow 属性,使其 offset-x 为 25px,offset-y 为 10px,blur-radius 为 0,spread-radius 为 0,colorblue

阴影部分的大圆,切去盒子的小圆,即一个新月形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style>
  .center {
    position: absolute;
    margin: auto;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100px;
    height: 100px;
    background-color: transparent;
    border-radius: 50%;
    box-shadow: 25px 10px 0px 0px blue;
  }
</style>
<div class="center"></div>

使用 CSS 和 HTML 创建更复杂的形状

世界上最流行的形状非心形莫属了,在本挑战中我们将用纯 CSS 创建一个心形。 但是首先你需要了解伪元素 ::before::after::before 创建一个伪元素,它是所选元素的第一个子元素; ::after 创建一个伪元素,它是所选元素的最后一个子元素。 在下面的代码中,::before 伪元素用来给 class 为 heart 的元素添加一个正方形:

1
2
3
4
5
6
7
8
9
10
.heart::before {
  content: "";
  background-color: yellow;
  border-radius: 25%;
  position: absolute;
  height: 50px;
  width: 70px;
  top: -50px;
  left: 5px;
}

::before::after 必须配合 content 来使用。 这个属性通常用来给元素添加内容诸如图片或者文字。 尽管有时 ::before::after 是用来实现形状而非文字,但 content 属性仍然是必需的,此时它的值可以是空字符串。 在上面的例子里,class 为 heart 元素的 ::before 伪类添加了一个黄色的长方形,长方形的高和宽分别为 50px70px。 这个矩形有圆角,因为它的 border-radius 为 25%,它的位置是绝对位置,位于离元素左边和顶部分别是 5px50px 的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<style>
  .heart {
    position: absolute;
    margin: auto;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: pink;
    height: 50px;
    width: 50px;
    transform: rotate(-45deg);
  }
  .heart::after {
    background-color: pink;
    content: "";
    border-radius: 50%;
    position: absolute;
    width: 50px;
    height: 50px;
    top: 0px;
    left: 25px;
  }
  .heart::before {
    content: "";
    background-color: pink;
    border-radius: 50%;
    position: absolute;
    width: 50px;
    height: 50px;
    top: -25px;
    left: 0px;
  }
</style>
<div class="heart"></div>

动画

了解 CSS 的关键帧和动画是如何工作的

如果要给元素添加动画,你需要了解 animation 属性以及 @keyframes 规则。 animation 属性控制动画的外观,@keyframes 规则控制动画中各阶段的变化。 总共有 8 个 animation 属性。 为了便于理解,本挑战中我们只会暂时涉及到两个最常用的属性。

animation-name 用来设置动画的名称,也就是我们稍后要在 @keyframes 里用到的名称。

animation-duration 设置动画所花费的时间。

@keyframes 可以通过设置特定时间点的行为来创建动画。 为此,我们只需要给持续时间内的特定帧(从 0% 到 100%)加上 CSS 规则。 如果用一部电影来做类比,那么 CSS 里面的 0% 关键帧就像是电影里面的开场镜头;100% 关键帧就像是电影里的片尾,就是那个之后会出现演职人员列表的片尾。 在动画设定的时间内,CSS 会根据关键帧的规则来给元素添加动画效果。 100% 位置的 CSS 属性就是元素最后的样子,相当于电影里的演职员表或者鸣谢镜头。 然后CSS 应用魔法来在给定的时间内转换元素以使其脱离场景。 下面举例说明 @keyframes 和动画属性的用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
#anim {
  animation-name: colorful;
  animation-duration: 3s;
}

@keyframes colorful {
  0% {
    background-color: blue;
  }
  100% {
    background-color: yellow;
  }
}

id 为 anim 的元素,我们在代码中将它的 animation-name 设置为 colorful,同时设置 animation-duration 为 3 秒。 然后我们把 @keyframes 规则添加到名为 colorful 的动画属性上。 在动画开始时(0%)的背景颜色为蓝色,在动画结束时(100%)的背景颜色为黄色。 注意我们不只可以设置开始和结束,而是从 0% 到 100% 间的任意位置都可以设置。

使用CSS动画更改按钮的悬停状态

你可以在按钮悬停时使用 @keyframes 改变按钮的颜色。

下面是在图片悬停时改变图片宽度的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
  img {
    width: 30px;
  }
  img:hover {
    animation-name: width;
    animation-duration: 500ms;
  }

  @keyframes width {
    100% {
      width: 40px;
    }
  }
</style>

<img src="https://cdn.freecodecamp.org/curriculum/applied-visual-design/google-logo.png" alt="Google's Logo" />

注意 ms 代表毫秒,1000ms 等于 1s。

修改动画的填充模式

太棒了,但是现在还不完美。 注意动画在 500ms 之后重置了,所以按钮又变成了之前的颜色。 而我们想要的效果是按钮在悬停时始终高亮。

为此,我们可以通过把 animation-fill-mode 设置成 forwards 来实现。 animation-fill-mode 指定了在动画结束时元素的样式: 你可以这样设置:

1
animation-fill-mode: forwards;

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style>
  button {
    border-radius: 5px;
    color: white;
    background-color: #0F5897;
    padding: 5px 10px 8px 10px;
  }
  button:hover {
    animation-name: background-color;
    animation-duration: 500ms;
    /* 只修改这一行下面的代码 */
    animation-fill-mode:forwards;
    /* 只修改这一行上面的代码 */
  }
  @keyframes background-color {
    100% {
      background-color: #4791d0;
    }
  }
</style>
<button>Register</button>

使用 CSS 动画创建动画

在元素的 position 已有指定值(如 fixed 或者 relative)时,CSS 偏移属性 rightlefttopbottom 可以用在动画规则里创建动作。

就像下面的例子展示的那样,你可以在 50% keyframe 处设置 top 属性为 50px,在开始(0%)和结束(100%)keyframe 处设置为 0px,以实现元素先向下运动,然后返回的动作效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@keyframes rainbow {
  0% {
    background-color: blue;
    top: 0px;
  }
  50% {
    background-color: green;
    top: 50px;
  }
  100% {
    background-color: yellow;
    top: 0px;
  }
}

通过从左到右淡化元素来创建视觉方向

在本挑战中,我们需要改变动画元素的 opacity 属性值,使其在到达屏幕右侧时渐隐。

在示例动画中,具有渐变背景的圆形元素在 @keyframes 为 50% 的节点向右移动。

使用无限的动画计数制作永不停止的动画

之前的关卡里介绍了一些动画属性以及 @keyframes 规则的用法。 还有一个常用的动画属性是 animation-iteration-count,这个属性允许你控制动画循环的次数。 下面是一个例子:

1
animation-iteration-count: 3;

在这里动画会在运行 3 次后停止,如果想让动画一直运行,可以把值设置成 infinite

使用无限的动画计数制作 CSS 心跳

这也是一个用 animation-iteration-count 属性创造持续动画的例子,它基于我们在前面挑战中创建的心形。

心跳动画的每一秒包含两个部分。 heart 元素(包括 :before:after)使用 transform 属性改变其大小,背景 div 使用 background 属性改变其颜色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<style>
  .heart {
    position: absolute;
    margin: auto;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: pink;
    height: 50px;
    width: 50px;
    transform: rotate(-45deg);
    animation-name: beat;
    animation-duration: 1s;
    animation-iteration-count:infinite;
  }
  .heart:after {
    background-color: pink;
    content: "";
    border-radius: 50%;
    position: absolute;
    width: 50px;
    height: 50px;
    top: 0px;
    left: 25px;
  }
  .heart:before {
    background-color: pink;
    content: "";
    border-radius: 50%;
    position: absolute;
    width: 50px;
    height: 50px;
    top: -25px;
    left: 0px;
  }

  @keyframes beat {
    0% {
      transform: scale(1) rotate(-45deg);
    }
    50% {
      transform: scale(0.6) rotate(-45deg);
    }
  }

</style>
<div class="heart"></div>

:after/::after和:before/::before的异同

相同点

  • 都可以用来表示伪类对象,用来设置对象前的内容
  • :before和::before写法是等效的; :after和::after写法是等效的

不同点

  • :before/:after是Css2的写法
  • ::before/::after是Css3的写法
  • css2的要比css3的兼容好
  • :before/:after 的兼容性要比::before/::after好 ,

不过在H5开发中建议使用::before/::after比较好

以可变速率来给元素添加动画

改变相似元素的动画频率的方法有很多。 目前我们接触到的就有 animation-iteration-count@keyframes

举例说明,动画示例包含了两个小星星,每个小星星都在 @keyframes 为 20% 处变小并且透明度变低,也就是一闪一闪的动画效果。 你可以通过改变其中一个元素的 @keyframes 规则以使小星星以不同的频率闪烁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<style>
  .stars {
    background-color: white;
    height: 30px;
    width: 30px;
    border-radius: 50%;
    animation-iteration-count: infinite;
  }

  .star-1 {
    margin-top: 15%;
    margin-left: 60%;
    animation-duration: 1s;
    animation-name: twinkle-1;
  }

  .star-2 {
    margin-top: 25%;
    margin-left: 25%;
    animation-duration: 0.9s;
    animation-name: twinkle-2;
  }

  .star-3 {
    margin-top: 10%;
    margin-left: 50%;
    animation-duration: 1.1s;
    animation-name: twinkle-3;
  }

  @keyframes twinkle-1 {
    20% {
      transform: scale(0.5);
      opacity: 0.5;
    }
  }

  @keyframes twinkle-2 {
    50% {
      transform: scale(0.5);
      opacity: 0.5;
    }
  }

  @keyframes twinkle-3 {
    80% {
      transform: scale(0.5);
      opacity: 0.5;
    }
  }

  #back {
    position: fixed;
    padding: 0;
    margin: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(black, #000099, #66c2ff, #ffcccc, #ffeee6);
  }
</style>

<div id="back"></div>
<div class="star-1 stars"></div>
<div class="star-2 stars"></div>
<div class="star-3 stars"></div>

使用关键字更改动画定时器

在 CSS 动画里,animation-timing-function 用来定义动画的速度曲线。 速度曲线决定了动画从一套 CSS 样式变为另一套所用的时间。 如果要描述的动画是一辆车在指定时间内(animation-duration)从 A 运动到 B,那么 animation-timing-function 表述的就是车在运动中的加速和减速等过程。

有一些预定义的关键字可用于常见的选项。 比如,默认值是 ease,动画以低速开始,然后加快,在结束前变慢。 其它常用的值包括 ease-out:动画以高速开始,以低速结束;ease-in,动画以低速开始,以高速结束;linear:动画从头到尾的速度是相同的。

学习贝塞尔曲线的原理

上一个内容中,我们介绍了 animation-timing-function 以及它的一些预设值,这些值定义了不同时间内的动画速度。 除了预定义值之外,CSS 还提供了贝塞尔曲线(Bezier curves)来更细致地控制动画的速度曲线。

在 CSS 动画里,我们可以用 cubic-bezier 来定义贝塞尔曲线。 曲线的形状代表了动画的速度。 曲线在 1 * 1 的坐标系统内, 其中 X 轴代表动画的时间间隔(类似于时间比例尺),Y 轴代表动画的改变。

cubic-bezier 函数包含了 1 * 1 网格里的4个点:p0p1p2p3。 其中 p0p3 是固定值,代表曲线的起始点和结束点,坐标值依次为 (0, 0) 和 (1, 1)。 你只需设置另外两点的 x 值和 y 值,设置的这两点确定了曲线的形状从而确定了动画的速度曲线。 在 CSS 里面通过 (x1, y1, x2, y2) 来确定 p1p2。 以下就是 CSS 贝塞尔曲线的例子:

1
animation-timing-function: cubic-bezier(0.25, 0.25, 0.75, 0.75);

在上面的例子里,两个点的 x 和 y 值相等(x1 = 0.25 = y1 和 x2 = 0.75 = y2)。如果你还记得几何课的知识,结果是从原点到点 (1, 1) 的一条直线。 元素在动画中的速度呈线性,效果和使用 linear 关键词的效果一致。 换言之,元素匀速运动。

使用贝塞尔曲线移动图形

前面的内容涉及了使用 ease-out 预定义值描述了动画以高速开始低速结束。 右边的动画展示了 ease-out 效果(蓝色的元素)和 linear 效果(红色的元素)的区别。 同样的,ease-out 预定义值也可以用贝塞尔曲线函数实现。

通俗的讲,将一条直线放在范围只有 1 的坐标轴中,并从中间拿 p1p2 两个点来拉扯(X 轴的取值区间是 [0, 1],Y 轴任意),最后形成的曲线就是动画的贝塞尔速度曲线。 下面是一个使用值来模仿 ease-out 样式的 Bezier 曲线示例:

1
animation-timing-function: cubic-bezier(0, 0, 0.58, 1);

记住所有的 cubic-bezier 函数都是从坐标为 (0, 0) 的 p0 开始,在坐标为 (1, 1) 的 p3 结束。 在这个例子里,曲线在 y 轴(从 0 开始,运动到 p1 的 0,然后运动到 p2 的 1)上移动得比在 x 轴(从 0 开始,运动到 p1 的 0,到 p2 的 0.58)上移动得快。 结果是,在这一段动画内元素运动得快。 到曲线的结尾,x 和 y 之间的关系反过来了,y 值保持为 1,没有变化,x 值从 0.58 变为 1,元素运动得慢。

使用贝塞尔曲线让运动更加自然

在这个挑战中,我们需要给元素添加动画来模拟杂耍中被抛接的球。 之前的挑战中,我们学习了 linearease-out 的贝塞尔曲线描述,但这两个都无法完美地描述杂耍球的运动。 在本关里你需要定制贝塞尔曲线。

animation-iteration-count 值为 infinite 时,animation-timing-function 会自动循环 keyframe。 由于我们是在动画周期的中间点(50% 处)设置的 keyframe 规则,最终的结果是球向上和球向下是两个同样的动画过程。

下面的例子模拟了杂耍球运动:

1
cubic-bezier(0.3, 0.4, 0.5, 1.6);

注意 y2 的值是大于 1 的。 虽然贝塞尔曲线是在 1*1 的坐标系统内,x 值只能在 0 到 1,但是 y 值是可以大于 1 的。 这样才能模拟杂耍球运动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<style>
  .balls {
    border-radius: 50%;
    position: fixed;
    width: 50px;
    height: 50px;
    top: 60%;
    animation-name: jump;
    animation-duration: 2s;
    animation-iteration-count: infinite;
  }
  #red {
    background: red;
    left: 25%;
    animation-timing-function: linear;
  }
  #blue {
    background: blue;
    left: 50%;
    animation-timing-function: ease-out;
  }
  #green {
    background: green;
    left: 75%;
    animation-timing-function: cubic-bezier(0.311, 0.441, 0.444, 1.649);
  }

  @keyframes jump {
    50% {
      top: 10%;
    }
  }
</style>
<div class="balls" id="red"></div>
<div class="balls" id="blue"></div>
<div class="balls" id="green"></div>

参考文献

  1. freecodecamp 应用视觉设计教程
  2. freecodecamp 基础css教程
  3. CSDN博主「寒酥_」的文章,原文链接:https://blog.csdn.net/weixin_49115895/article/details/108683791