从零开始的前端学习手记 构建篇

整个学习路线构建在:HTML 简介 - 学习网络开发 | MDN Web 中文网之上。

构建,顾名思义,就是很浅地过一遍。

HTML

我开始写前端的时候已经比较晚了,因为学校有相关的作业要求,故HTML这个板块用成果为楔,慢慢道来。

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>作业1</title>

</head>

<body style="text-align: center;">

<header id="top">

<h1 title="纯html会直接在元素里被看到吗...那很坏了">

这是我的html网页

</h1>

</header>

<main>

<a href="http://8.137.71.164">点击跳转至我的博客(还很简陋,见谅,而且是ip地址,等成年就好了)</a>

<p>不过既然要写自我介绍,我就先把博客里的自我介绍内容搬过来吧</p>

<h1>你好呀</h1>
<p>这是一篇自我介绍,接下来我将非全方位介绍自己。</p>
<hr>

<table border="1" cellpadding="10" style="margin: 20px auto;
border-collapse: collapse;text-align: center;">
<thead>
<tr>
<th>项目</th>
<th>内容</th>
<th>嘻嘻</th>
</tr>
</thead>
<tbody>
<tr>
<td>音乐</td>
<td><a href="https://music.163.com/song?id=1462753116&uct2=U2FsdGVkX1+s8V8FYxSPFzs+hVRjGbk5X20skBrxebk=">
21 ——Gracie Abrams</a></td>
<td>不好听来打我。</td>
</tr>
<tr>
<td style="color:#f6cec1;">淡桃红</td>
<td style="color:#483332;">海报灰</td>
<td style="color:#f4a83a;">中国色!</td>
</tr>
<tr>
<td>状态</td>
<td>持续学习中,欢迎交流</td>
<td>有点强迫症</td>
</tr>
</tbody>
</table>

</main>

<footer>
<div>
<a href="http://8.137.71.164" style="display: inline-block;width: 25%;">
<img src="https://cdn.jsdelivr.net/gh/Shengzb0/scaling-eureka@main/image/20251107013537174.png"
alt="替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本"
style="display:block;width:100%;height:auto;display:block;margin:0 auto;">
</a>
</div>
<p style="text-align:center;">点小黑照片,也可以跳转到博客 · <a href="#top">返回顶部</a></p>
</footer>

</body>

</html>

这是一段html代码,用浏览器打开它,我们可以得到一个网页。

网页的效果是这样的:

image-20251116132851486

HTML是什么?

HTML(超文本标记语言)会告诉浏览器如何构建你访问的网页,它由一系列元素(elements)组成。

1
2
3
4
<a> </a>
<h1> </h1>
<p> </p>
<table> </table>

元素

元素就是这种由标签(tags<>)包裹的东西,你可以使用它们来包围、封装、标记内容的不同部分,使它们以某种方式显示或运行。

现在把视角看向网页最上方的文字,image-20251116143931878

我们希望文本独立存在,就可以通过<p></p>(paragraph)元素指定。

比如第一句,这是我的html网页,将由

1
2
3
<p>
这是我的html网页
</p>

来实现。

image-20251116153456372

中间就是元素的内容。

但是,这个代码只能达到这样的效果:

image-20251116154034753

我想要他居中,就需要用到元素的属性(attributes)。

属性

1
2
3
<p style="text-align:center;">
这是我的html网页
</p>
image-20251116154244547

属性包含元素的额外信息。image-20251116154544376

比如<img>元素(image)可以拥有众多属性,

  • src:指定图片位置(url地址/图片路径)
  • alt:指定图片文本描述(图片刷不出来的替代文本)
  • width/height:分别制定图片宽度和高度
123

属性有这些(从HTML 属性 | 菜鸟教程转):

image-20251116161901235

初步了解,按需使用,要用再学。

看代码:

html一般分为head和body,head代表创建一个包含html内容的容器,页面不会显示head其中的内容。

关于声明:

image-20251117224246157

前两行, 第一行声明必须加,声明此文件是html文件。

​ 第二行规定页面语言,这将影响浏览器跳不跳翻译功能。

​ >>> 中文用zh-Hans/zh-CN,英文用en.

关于头(head):

image-20251116165211009

头元素包含的这些也很重要。

  • <meta charset="UTF-8">:表示元数据。 其中的charset属性指定字符编码为UTF-8,通常是要加上的。
  • <meta name=" " content=" ">:指定这个页面将随设备宽度变化而变化,初始不缩放。
  • <title>代表该网站的标题,image-20251116165647379比如我们在浏览器里看到的这些。

关于体(body):

现在再回头看代码的主体:

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
<body style="text-align: center;">

<header id="top">

<h1 title="纯html会直接在元素里被看到吗...那很坏了">

这是我的html网页

</h1>

</header>

<main>

<a href="http://8.137.71.164">点击跳转至我的博客(还很简陋,见谅,而且是ip地址,等成年就好了)</a>

<p>不过既然要写自我介绍,我就先把博客里的自我介绍内容搬过来吧</p>

<h1>你好呀</h1>
<p>这是一篇自我介绍,接下来我将非全方位介绍自己。</p>
<hr>

<table border="1" cellpadding="10" style="margin: 20px auto;
border-collapse: collapse;text-align: center;">
<thead>
<tr>
<th>项目</th>
<th>内容</th>
<th>嘻嘻</th>
</tr>
</thead>
<tbody>
<tr>
<td>音乐</td>
<td><a href="https://music.163.com/song?id=1462753116&uct2=U2FsdGVkX1+s8V8FYxSPFzs+hVRjGbk5X20skBrxebk=">
21 ——Gracie Abrams</a></td>
<td>不好听来打我。</td>
</tr>
<tr>
<td style="color:#f6cec1;">淡桃红</td>
<td style="color:#483332;">海报灰</td>
<td style="color:#f4a83a;">中国色!</td>
</tr>
<tr>
<td>状态</td>
<td>持续学习中,欢迎交流</td>
<td>有点强迫症</td>
</tr>
</tbody>
</table>

</main>

<footer>
<div>
<a href="http://8.137.71.164" style="display: inline-block;width: 25%;">
<img src="https://cdn.jsdelivr.net/gh/Shengzb0/scaling-eureka@main/image/20251107013537174.png"
alt="替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本替代文本"
style="display:block;width:100%;height:auto;display:block;margin:0 auto;">
</a>
</div>
<p style="text-align:center;">点小黑照片,也可以跳转到博客 · <a href="#top">返回顶部</a></p>
</footer>

</body>
image-20251116164812657
  • 第一行:body

    body是和head相对应的元素。

    我在这里直接style="text-align: center;",给了他一个居中的属性,意味着在这个body之中的所有元素全部默认居中。

  • header(页眉)

    header元素相当于这个网站内容的一个标题(其实就是字体变大)。当然现在的header更加自由,已经变成了<h1><h6>,拥有更加多的字体大小。

    其中<h1>元素的属性title,是将鼠标悬停时将看到的文字。

  • main

    image-20251117000521890

    像main主函数一样,这里就是我们网页内容的主体。

    • <a></a>超链接:

      拥有一个href属性,该属性表示前往的链接。

    • <p></p>段落:

      正常文本。

    • <hr>

      水平分割线(horizontal rule),类似于:


    • <table></table>

      表格,其中的属性有通用的id,class,style等,表格的样式一般都已经靠class+CSS的组合来控制了。
      但是单html,我们使用border作为边框宽度、cellpadding作为单元格内边距、cellspacing作为单元格之间的间距、width/height作为表格宽高、align作为表格对齐方式、bgcolor作为背景色,还有不太常用的frame(控制表格外边框哪几边显示)、rules控制内部线条显示方式。

      依然是按需取用。

      • style中的参数都是什么?

        image-20251117133257436

        margin:外边距,写两个值时分别是上下外边距和左右外边距

        ​ 这里就是让表格上下空出20px的距离。

        border-collapse:是表格的特有属性,用来控制单元格边框的合并方式。

        ​ 默认是separate->每个单元格有自己的边框。

        ​ 而collapse->把相邻单元格的边框合并成一条线。

        text-align:控制文字的对齐方式,将被子元素(<td>/<th>)继承。

        ​ 有left/right/center.

      • <thead></thead>:

        image-20251117134135608

        表头(table head),就是第一行的内容。

        • <tr></tr>:

          表格的一行(table row)。

        • <th></th>:

          表头单元格(table header cell)。

      • <tbody></tbody>:

        image-20251117134531173

        表格主体(table body)。

        • <td></td>:普通单元格
          然后其中有一行嵌套了一个超链接,所以嵌套元素也就这样,

          依然可以被style等修改样式,这个是改的字体颜色。

      总结一下:

      • <thead>:表头

      • <tbody>:表格内容

        <thead>/<tbody>需要搭配<tr>(表格的一行)使用,内部需要<th>(表头单元格)/<td>普通单元格来填充。

  • footer(页脚):

    image-20251117230114412

    页脚就是页面最下面的内容。

    <div>:定义一个块级容器,没有什么含义,但是方便CSS控制样式。
    在这里我规定超链的宽度为父容器宽度的25%,那么在我超链内的图片,就也默认继承超链区域的宽度。

    我们介绍一下display:inline-block;

    display:规定元素怎么在页面里排队占位,其中三种常见的参数,可以看一看:

    block(块级元素) 独占一整行(前后自动换行) 可以设置宽高、调整内外边距 <div> <p> <h1>默认就是 block
    inline(行内元素) 不会换行,元素会像文字排在一整行里 不能设置宽高(宽高由内容决定) <a>, <span>, <em> 默认是 inline
    inline-block(行内块元素) 可以一行放多个、不一定换行 可以设置宽高、调整内外边距 适合按钮、卡片、图标一行排多个的布局

    在这里我将超链设置为行内块元素,意味着我可以调整这个“超链盒子”的宽高了。

    ​ 而超链盒子,又意味着这一整块区域都将是超链区域,点击跳转。它的子容器img,我调整宽度100%,意味着图片将铺满这个25%宽度的盒子。

    ​ 这样,就避免了超链可点区域远大于图片显示区域的问题。

    最后超链返回顶部,#top锁定页眉的top.

    (这个id就是CSS给的钩子)

    image-20251117235203289

然后我们就可以过渡到CSS阶段了🤓,虽然说用style很方便很高级,但是既然要学css,就少用这种内联样式,单独开css文件写样式才是正解。

CSS

在这里,我们目标是修饰html阶段的结业文件,让他更有网页味。

我们以html为锚点向外推进。

了解CSS

  • 什么是CSS?

    CSS(Cascading Style Sheets,层叠样式表)可以给HTML文档和XML应用添加样式,扩展名是.css.

    听过html的很难没听过css,后者功能的强大有目共睹。

  • 如何引入CSS?

    只需要在html文件的<head>里添加一行:

    1
    <link href="style.css" rel="stylesheet" />

    注意href要指向css文件。

  • 怎么使用CSS?

    需要了解基本选择器(元素选择器例:h1、类选择器例:.card、ID选择器例:#top)、声明块。

    CSS规则由两个主要的部分构成:选择器、一条或多条声明

    img
    • 选择器通常是需要改变样式的HTML元素,声明由一个属性和一个组成。
      声明以分号结束,由大括号括起。

    例如,我想给我的top一个红色字体,我就可以在css中写:

    1
    2
    3
    #top{
    color:red;
    }

    然后在head里用link指向该css文件就可以了。

盒子模型(Box Model):

任何HTML元素都可以看成矩形的盒子。

在这里我们弄懂margin(外边距)/padding(内边距)/border(边框).

CSS box-model

margin是边框外的透明区域,

border是内边距和内容外的边框,你可以把他变粗变细,甚至是删除他。

padding是内容周围的透明区域,

content就是盒子的内容,比如文本、图像。

当然盒子还有宽高width/height

Flexbox布局:

flexbox(弹性盒子)是一种响应式布局方式,这种布局方式在显示设备不同(屏幕大小、设备类型)的情况下,可以依然确保元素拥有恰当的行为。
可以尽量规避CSS中元素溢出和奇怪缩放的问题。

当我们写display: flex,我们就开启了一个flexbox。(只要html元素可以容纳文本等内容,就可以成为flexbox)

让我们用Flexbox Froggy - A game for learning CSS flexbox打开flexbox的新篇章。

image-20251120003515792

一个池塘,代表一个容器。既然已经是flexbox,那他就会有flexbox拥有的所有属性。我们慢慢讲:

image-20251120004018588

横着的叫主轴(初始方向从左到右),竖着的叫交叉轴(初始方向从上到下)。

正常情况下,我们的元素将从两个轴的起点开始堆叠–>青蛙的位置,如果存在两个元素,那将先按主轴的方向堆叠,比如第二关的青蛙:

image-20251120172913318
关于justify-content属性(主轴对齐):

我们需要知道justify-content属性,控制对齐位置的属性。其中三个值:

flex-start(默认) flex-end center
把flex项目对齐到主轴的起点 把flex项目对齐到主轴的终点 把flex项目对齐到主轴的中央
左对齐 居中对齐 右对齐

那很明显,这一关我们要把青蛙放到右边,只需要写一行:

1
justify-content: flex-end;

第二关写:

1
justify-content: center;

还有三个值:

space-between space-around space-evenly
两侧紧贴边缘,间隙平均 两侧不贴边缘,但是由于中间容器将共用间隙,因此中央间隙是两侧间隙的两倍大小 中央两侧间隙等大
image-20251120180740969 image-20251120180623303 image-20251120180644569

image-20251120180913311
关于align-items/align-self属性(交叉轴对齐):

如果要在交叉轴上对齐这几个青蛙,就要用到align-items属性,其中几个值:flex-start/flex-end/center都和上面主轴的justify-content类似。

我们同时写:

1
2
align-items: center;
justify-content: center;

就可以让元素在屏幕上居中。

此外,使用align-self将定义单个元素的交叉轴对齐逻辑,这将覆盖父容器align-items属性的继承。

关于flex-direction属性(主轴方向):

还有一个属性:flex-direction,默认值为row,表示主轴水平从左到右;row-reverse表示主轴水平从右到左;column表示主轴竖直从上到下;column-reverse表示主轴竖直从下到上。

这些将影响justify-contentalign-items的逻辑。

image-20251120193110938
关于order属性:

你可以使用order属性指定单个项目,更改它的显示位置。

image-20251120183058047

order值范围是:-2~2.


关于flex-wrap属性(换行):

flex-wrap属性接受以下取值:

nowrap wrap wrap-reverse
元素将固定在一行里,收缩页面对应元素也会收缩。 元素在空间不够时会绕到第二行。 元素将反向绕行,从下到上排列。
image-20251120183524143 image-20251120183659859 image-20251120183759681

收缩是因为每一个元素都有一个属性:flex-shrink:1,这将给予他们收缩的能力。如果改成0,元素将在保持原来大小的情况下溢出容器

​ 还有一个类似的属性:flex-grow:1,这将让元素尝试填满父容器的可用空间,如果容器有额外空间,元素就会变宽。

其他的数字仅在相互比较时有意义,如果某一个元素的flex-grow值为5,其他元素为1,意味着这个元素的增长速度是其他元素的五倍。

给元素设置max-width/min-width将设置他们增长或收缩的尺寸的最值。

flex-direction:column共用,可以达到竖着绕行的效果。

但是这个绕行一点都不均匀,你可以理解成每一行有一个独立的主轴和交叉轴。在这种情况下,align-items只会控制各自交叉轴的对齐情况,这时候我们就需要其他的属性控制他们整体的对齐,

它就是:align-contentimage-20251120185728733

关于align-content属性(交叉轴全局对齐):

他的值和justify-content差不多,拥有flex-start/flex-end/center,它还有space-between/space-evenly/space-around

还有比较特殊的stretch(默认),它将把每一行拉伸得足够长,尽量填满交叉轴上的可用空间,所以绕行不均匀。

比如这是align-content: flex-start;的效果。

image-20251120194431545

在尝试上面这些值时,推荐加一个属性:gap: 20px;,以此代替margin


关于flex-flow属性(主轴方向、换行):

flex-wrapflex-direction的结合体,在这个属性里,你将可以融合二者,直接写出:

1
flex-flow: row wrap;

这表示横向正排列,换行。image-20251120193819680

因此这个布局,我们也可以使用flex-flow:column wrap;实现。


Level 23:

是的,已经Level 23了。

image-20251120194804670

用如下css布局即可让青蛙回家:

image-20251120194740052
Level 24:

是的,最终章!

image-20251120195710946

用如下css布局就可以让青蛙回家:

image-20251120195635222

结业项目:

这个项目也是博采众长了,去各种网站里找了css代码,一点一点扒过来学,还有就是自己的一些奇思妙想,前端真好玩。

Flexbox属性的继承关系:

在此之前,我们得讲讲Flexbox的家规:只管亲儿子,不管孙子。

比如在这里:

image-20251121111607031

我给menu设置了display:flex,但是当我在给buttons设置gap时,却发现无效。

这是因为父容器menu只负责分开这里的icon1buttons,不会把属性继续继承到button上,所以我们需要给buttons再写一个display:flex;

粘性定位:

1
2
3
4
5
6
7
8
<div class="menu">
<img src="https://luoxblack.oss-cn-chengdu.aliyuncs.com/img/png.png" class="icon1">
<div class="buttons">
<a href="https://luoxblack.top" class="btn-item"><span>博客</span></a>
<a href="#" class="btn-item"><span>首页</span></a>
<a href="#" class="btn-item"><span>关于我</span></a>
</div>
</div>

我想让menu一直悬浮在页面最上方,就可以使用position: sticky;粘性定位,但是需要注意的是,需要设置top/left/bottom/right中的任意一个属性、以确定元素何时固定。

例如:

1
2
3
4
.menu{
position: sticky; /*粘性定位*/
top: 0; /*设置菜单紧贴网页顶端*/
}

top: 0;代表当菜单元素紧贴网页顶端时开始固定。

阴影:

CSS中可以给元素设置阴影,用box-shadow属性即可。

可以指定五个值,X轴偏移量、Y轴偏移量、模糊半径、扩散半径、颜色

比如我写:

1
box-shadow: 5px 5px 5px rgba(0,0,0,0.5); 

就可以得到左上角光源的阴影效果。

自定义滚动条:

我们可以针对 WebKit 内核(Chrome, Edge, Safari)使用伪元素,设置其scrollbar属性,具体实现方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
::-webkit-scrollbar:{
width: 8px; /*滚动条宽度*/
}
::-webkit-scrollbar-track{
background: #242323; /*滚动条背景颜色*/
}
::-webkit-scrollbar-thumb{
background: #158bb8; /*滚动条滑块颜色*/
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover{
background: #127a9e; /*滚动条鼠标悬停效果*/
}

流光按钮:

我们得先认识一下::before/::after伪元素:

::before/::after

我们完全可以把伪元素当做一个正常的html元素,但是伪元素是添加在css中的,因此我们可以用伪元素在不污染html结构的情况下添加一些特殊样式。

伪元素绝对需要加的属性是content,不想拥有任何内容就写content: "";,没有这个就不会显示。

before和after的区别是一个在父元素的前面,一个在父元素的后面。但是真的有区别吗?

他的位置会被我们用position: absolute;定义(别忘了给父元素写上position: relative;),再使用top/left/bottom/right去精确控制位置,所以前后在这里就没有意义了。

因为伪元素默认是行内元素,所以有时候还需要单独设置display: block;.


1
2
3
4
5
6
7
8
<div class="menu">
<img src="https://luoxblack.oss-cn-chengdu.aliyuncs.com/img/png.png" class="icon1">
<div class="buttons">
<a href="https://luoxblack.top" class="btn-item"><span>博客</span></a>
<a href="#" class="btn-item"><span>首页</span></a>
<a href="#" class="btn-item"><span>关于我</span></a>
</div>
</div>
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
.btn-item{
display: inline-block;
position: relative; /*让里面的伪元素以它为基准定位*/
text-decoration: none; /*去掉下划线*/
border-radius: 8px;
overflow: hidden; /*防止彩色溢出*/
padding: 1.8px;
}

.btn-item::before{
content:""; /*没有这个不会显示伪元素*/
position: absolute;
top: 0; left: 0;

width:400%; height: 100%;
background: linear-gradient(100deg, #4fcf70, #fad648, #a767e5, #12bcfe, #44ce7b); /*闭环色*/
background-size: 25% 100%;
z-index: -1;
animation: radium 0.75s linear infinite;
animation-play-state: paused;
}

.btn-item:hover::before{
animation-play-state: running;
}

.btn-item span{
display: block;
background: #232323;
color: #fff;
padding: 6px 15px;
border-radius: 6px;
}

@keyframes radium{
0%{
transform: translateX(0%);
}
100%{
transform: translateX(-25%);
}
}

这是一个流光按钮的css代码,实现逻辑很简单:

  • 第一层是一个class: btn-item的容器,他规定了按钮的边界;
  • 第二层是一个带渐变光效动画的伪元素;
  • 第三层是一个<span>遮罩,深灰色的板子盖住大部分动画,只留下一个边框,就实现了彩色光带按钮。
image-20251123110052945

这个overflow,可以删掉看看。image-20251123110347442

功能是隐藏溢出的部分,这句话就是核心。

image-20251123110446964

为什么这里要写四倍宽?这里先要讲一下动画的逻辑,就是直接让这个元素平移,如果我们能每次平移一个按钮的宽度,就可以无缝衔接(因为我们的渐变色是首尾相接的)。四倍宽和我们接下来动画里的-25%刚好联动,
简单计算:400% * 25% = 100%.

linear-gradient

linear-gradient:linear–>线性的,gradient–>渐变,这个函数就是css用来创建线性渐变图像的,这个图像是由浏览器实时绘制的(通常用在background-image(简写为background)中)。

有两个参数,第一个是方向(决定渐变线的走向),两种写法:

  • 关键词:

    to right/bottom/...:从左往右、从上到下(默认),

    还可以写to bottom right:从左上到右下。

  • 角度deg:

    • 0deg:从下往上 (12点方向) ⬆️
    • 90deg:从左往右 (3点方向) ➡️
    • 180deg: 从上往下 (6点方向) ⬇️
    • 270deg: 从右往左 (9点方向) ⬅️

第二个参数就是颜色:

既可以写成red, blue这种均匀分布,也可以写成 red, orange, yellow, green, blue这样的均匀分布,想写多少颜色就多少颜色。

当然还可以控制位置,在颜色后面加百分比,告诉浏览器这个颜色最纯的位置在哪。

比如:

1
background: linear-gradient(to right, red 50%, blue 50%);

前50%都是红色的,然后马上变成蓝色。其实我们上面的只是省略了%,我们写成red, blue的时候已经默认red 0%, blue 100%了。

这是Gemini给的形象解释:

image-20251123114125710
image-20251123110446964

书接上文,那为啥不直接写100% * 100%呢?

原因在width不大,动画就不能小,这样太慢不丝滑。所以background-size我们也对应弄小,因为有四倍的图片所以不怕穿帮了。

z-index是层级,设成负数就可以把图层往下移,成为背景。

animation是在调用动画,第一个值代表动画名字,第二个值代表动画周期,第三个值代表匀速,第四个值代表无限循环。默认设置暂停,因为下面我们要设置:hover,鼠标移上去再动。

1
2
3
.btn-item:hover::before {
animation-play-state: running; /* 鼠标悬停时,解除暂停,动画开始跑 */
}

image-20251123115319805

顶层遮罩,我们要遮住中间的部分。内部圆角通常要比外层圆角小一点点,视觉才协调。


image-20251123115636709

动画帧@keyframes radium,定义radium这个动画的逻辑。

0%理解成开始,100%理解成结束,从起始位置0%到终止位置,向左移动25%,就这么简单。


背景渐变动画:

类似地,我们看看这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
body {
text-align: center;
background: linear-gradient(-45deg, #1a1a1a, #1d2934, #242323, #281949);
background-size: 200% 200%;
animation: BG 10s ease infinite; /*BG 10s 平滑移动 无限循环*/
color: var(--text-color);
font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
margin: 10px;
min-height: 100vh; /*保证背景铺满屏幕*/
}

/*逻辑:左右交替横扫*/
@keyframes BG {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}

font-family:字体栈,逻辑是规定浏览器使用字体的优先级。既有兼容性,又美观。

  • "Helvetica Neue", Helvetica, Arial:这是mac和windows的经典字体,英文字体,所以放在最开头。当浏览器遇到汉字,英文字体就显示不出来了,这时候就会向后找中文字体。

  • "PingFang SC", "Heiti SC", "Microsoft YaHei", "WenQuanYi Micro Hei":mac、windows、linux自带的中文字体,中文字体里的英文一般没有英文字体的英文好看。

  • sans-serif:保底的无衬线字体。

    (这段代码感觉有点啰嗦)


字体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text1 h1 {
font-size: 3rem; /* 大标题 */
margin-bottom: 10px;
letter-spacing: 2px;
}

.text1 span{
color: var(--main-color);
}

.text1 p {
font-size: 1.2rem;
color: #ccc;
}
  • rem:相对单位,r代表root根目录,指向浏览器的根字体设置,3rem就是三倍默认字体大小。

    所以字体大小就用rem解决。

  • 视觉层级:越重要的内容用对比度越高的颜色。


滚动吸附 scroll-snap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
html {
scroll-behavior: smooth;
scroll-snap-type: y mandatory; /*竖直吸附*/
}

.main-page, .page {
min-height: 100vh;
scroll-snap-align: start; /*滚动吸附到页顶*/
display: flex;
justify-content: center;
align-items: center;
}

.main-page{
min-height: 90vh;
}

从html开始,因为这个滚动吸附我也研究了一会。

滚动吸附需要在html全局生效,否则可能出现双层容器,配上我们设置的::webkit滚动条,场面一度无法控制。

其中的两个属性:scroll-behavior让滚动更丝滑(点击#top锚点链接时竟然是慢慢滑过去的),scroll-snap-type设置了滚动吸附的方向为垂直方向,然后用mandatory将页面强制拉到最近的一个指定位置去。

这是滚动的一些基础设置,然后就是吸附点:

我们给子元素main-pagepage带上了一些样式,scroll-snap-align决定对齐方式。

start:表示当吸附发生时,板块的顶部要和容器的顶部对齐。

vh=Viewport Height.设成100代表这个板块和屏幕一样高,保证了每一页都能占满整个屏幕。main-page设成90是因为第一页用90看起来舒服点。


点击下载结业文件

JavaScript

学习JS,我们的路线依然是以实用主义为纲领,但这次我们尝试继续美化结业文件。

JavaScript是什么?它是Web的编程语言,可以控制网页的行为,功能同样十分强大。

和css一样,我们用外联脚本,在html里写一个src指向js脚本。

1
<script src="a.js"></script>

到js文件内部,就得用理解编程语言的思维去理解了。

实现打字机动效

我想实现如下效果,要怎么做?

可以尝试循环迭代的思路,变量i一次次指向不同的字符,是不是就行了。

1
const text = "一个热爱 Web 的人";

使用const定义一个text常量(注意是常量),让它作为待打印的字符库。

1
let i = 0;

使用let定义一个i变量,作为迭代变量。

1
2
3
if (i < text.length) {
i++;
}

就这样实现迭代,但是我们还需要一个循环,循环无非就是让这个i++重复执行,可以用while和for,但是我们这里有更简单的方法:

1
2
3
4
5
6
function typewriter(){
if (i < text.length){
i++;
setTimeout(typewriter,150);
}
}

使用function定义一个typewriter函数,函数内部是一个if迭代,通过setTimeout()来实现循环。

setTimeout()是延迟执行函数的方法,参数有三个,第一个是要延迟执行的函数,第二个是延迟时间(单位毫秒),第三个是传参。

举两个例子应该差不多了:

1
2
3
setTimeout(function(){
console.log("延迟三秒执行");
},3000);

console.log()算是入门级的js代码了,类似python里的print,c里的printf,只不过这个是以一个浏览器弹窗的形式打印出来的。

或者这样写:

1
2
3
setTimeout(()=>{
console.log("延迟三秒执行");
},3000);

第二个例子(传参):

1
2
3
4
function a(title,content){
console.log("${title}的内容:${content}");
}
setTimeout(a,3000,'高数作业','P137题3,4,5');

不要写成a(),不然会立即执行。

取消延迟执行用clearTimeout(),将常量指向setTimeout()的定时器ID(const a = setTimeout()),后续写clearTimeout(a);就好了。

所以在typewriter内部延迟执行typewriter,实现了间隔输出和循环(递归)的效果。

那怎么实现一个个输出呢,这点我们还是没有弄好。

理解一下逻辑,我们如果把原来的p段落清空,image-20251201021818004

就可以通过一次递归,向其中加一个字符的方法实现“打字”效果。具体操作是先选择typer,再+=。

选择typer的脚本:

1
const element = document.getElementByID("typer");

document指向全局文档,使用get Element By ID()的方法,选择其中ID为typer的元素,并赋值到element常量上。

+=的脚本:

1
element.textContent += text.charAt(i);

这和英文有什么区别。。。

合起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
const text = "一个热爱 Web 的人";
const element = document.getElementByID("typer");
let i = 0;

function typewriter{
if (i < text.length) {
element.textContent += text.charAt(i);
i++;
setTimeout(typewriter,150);
}
}

typewriter();

最后一行,执行函数。