一. 如何理解HTML语义化?

对web、html语义化的理解:使用恰当语义的HTML标签和CSS,class等内容,让页面具有良好的语义和结构;从而方便人类和机器都可以快速理解网页内容。
其核心内容分为以下4点:

  1. 用正确的标签做正确的事情
  2. 页面结构化
  3. 无CSS的情况下也能进行网页阅读
  4. 方便浏览器,搜索引擎解析;有利于SEO

以下是各个标签的语义化含义:

1. header

header代表网页或者内容块(section)的页眉,通常包含hgroup,h1-h6标签;
作为整个网页或者内容块的标题,可以包裹一节的目录部分,一个搜索框,,一个nav,相关logo等内容。
示例:
image.png

2. footer

footer代表网页或者内容块(section)的页脚,包含网页的基本信息如:文档创作的作者,文档的版权信息,使用条款的链接,联系信息等。
示例:
image.png

3. hgroup

hgroup代表网页或者内容块(section)的标题,文章主标题和副标题组合时可以使用hgroup包裹;
连续使用多个h1-h6时需要用hgroup包裹;
只是用单个h1-h6时不需要用hgroup包裹。
示例:
image.png

4. nav

nav标签用于页面的导航链接区域,规定只适用于页面的主要导航区域
image.png

5. aside

  1. aside在article中可以作为主要内容的附属信息,如与当前文章有关的资料,标签,名词解释
  2. aside在article外作为页面或者站点的全局附属信息部分,如侧边栏,可以包含其他组的导航,广告等

示例:
image.png

6. article

article代表一个在文档,页面或者网站自成一体的内容;可以包含header和footer
是特殊的section,比section有更明确的语义;当一段内容脱离语境后还是完整独立的,应该使用article;
应用场景:新闻博客文章,论坛帖子,用户评论等
示例:
image.png

7. ARIA

ARIA无障碍富互联网应用,目的是使有功能障碍的人群更容易访问web网页和web应用
属性role标识元素的作用
示例:
image.png
参考:如何理解HTML结构的语义化?

二. scrpit中defer和async的区别

defer和async属性用于异步加载外部的script资源,他们有如下的区别

类型 执行顺序 是否阻塞解析HTML 与DOMContentLoaded执行顺序
<script> HTML中的排列顺序 阻塞 在DOMContentLoaded之执行,算是解析HTML的一部分
<script async>``<script defer async> 请求返回的顺序,谁先返回先执行谁 可能阻塞,请求返回后HTML没有解析完成则阻塞解析HTML 在DOMContentLoaded之执行,不算解析HTML的一部分
由此可见DOMContentLoaded触发不需要等待async脚本,样式图片加载
<script defer> HTML中的排列顺序 不阻塞,HTML解析完成后执行脚本 在DOMContentLoaded之执行,算是解析HTML的一部分

使用图片更加清晰的展示区别:
一. 前端整理 HTML CSS - 图8
以下是实际情况的示例效果

1. script在中,没有添加任何属性

image.png

2. script在底部,没有添加任何属性

image.png

3. script在中,添加async标签;同时添加defer,async标签

image.png

4. script在中,添加defer标签

image.png
问题:DOMContentLoaded和load区别?
答:DOMContentLoaded是在DOM解析完成后执行
load是所有外部资源加载完成后执行,包括css,图片等

三. 从浏览器输入URL到请求返回发生了什么

1. 输入网址并解析

1)url的组成

URI只支持ASCII编码,所以引入URI编码将非ASCII字符界定符转换为16进制字节值,并加上%
从左到右如图所示

协议(scheme) 常见http,https,ftp。。。
主机(host) 可以时域名或者IP地址
端口(port) 不加默认80端口
路径(path) 路径可以不包含文件名,访问默认文件,取决于服务器实现
查询参数(query) 以?开头,key=value的形式
锚点(anchor) 以#开头,网页内部的定位点,文件内部位置

一. 前端整理 HTML CSS - 图13

2)浏览器缓存

强缓存
浏览器首先会判度请求是否命中了强缓存或者协商缓存。根据上次请求的响应头Cache-ControlExpires判断是否命中强缓存;根据If-None-MatchIf-Modified-Since判断是否命中协商缓存
如果命中强缓存,浏览器不会真正发送请求,而是从浏览器缓存中(from disk cache或from memery cache)读取数据并返回状态码200(firefox是304);
强缓存的使用场景:公共js、css,图片。。。
以下是两个参数的对比

响应头 协议版本 优先级 格式 命中条件 响应头其他值 请求头
Cache-Control http1.1 高,如果两者同时存在忽略Expires Cache-Control:max-age=3600
max-age的单位是秒
服务响应头中若有Cache-Control会自动添加Date属性,如果发送请求时间超过Date+maxAge则没有命中缓存 客户端是否缓存数据,数据过期时间由服务端决定
- no-cache或max-age=0:客户端缓存;不使用强缓存,验证协商缓存
- no-store:客户端不缓存;强缓存和协商缓存都不使用,直接向服务端请求
客户端不想使用缓存数据的时候可以添加Cache-Control控制
- max-age=0:不使用强缓存,验证协商缓存
- no-cache:不使用强缓存和协商缓存,直接请求

其他值无效 | | Expires | http1.0 | 低,现在基本不会使用。作为兼容可以保留 | Expires: Wed, 22 Nov 2019 08:41:00 GMT
(GMT格式的日期) | 服务响应头中若有Expires会自动添加Date属性,如果超过Expires的过期时间则没有命中缓存 | | |

下面是验证的情况:
请求命中了Cache-Control强缓存
image.png

请求命中了Expires强缓存
image.png
没有命中强缓存,因为Cache-Control含有max-age或s-max-age时会忽略Expires
image.png

协商缓存
如果没有命中强缓存,就可以由服务器决定是否使用缓存数据,称为协商缓存;协商缓存实际发送请求并由服务端决定是否使用缓存。
本次请求会根据上次请求的响应头ETag自动在请求头中添加If-None-MatchLast-Modified自动添加If-Modified-Since,如果命中缓存服务端返回304状态码
协商缓存的使用场景:HTML

第一次请求响应头 第二次请求请求头 版本 优先级 优点
ETag If-None-Modified http1.1 高(由服务端决定)
1. 针对周期更新,但文件内容不一定真正改变的情况,ETag能检查文件是否真的改变了
1. 提高控制细粒度,If-Modified-Since的单位是秒,低于秒级的文件改动可由ETag检查到
1. 某些服务器不能获取文件的修改时间
Last-Modified If-Modified-Since http1.0 低(由服务端决定)

第一次请求服务器返回ETagheader,第二次请求自动带上if-None-Match,命中了协商缓存
image.pngimage.png

第一次请求服务器返回Last-Modifiedheader,第二次请求自动带上if-Modified-Since,命中了协商缓存
image.pngimage.png

3) DNS解析

DNS(Domain Name System)域名系统。DNS域名解析就是将域名转换成IP地址。DNS解析使用UDP的连接方式
DNS解析流程是一个递归+迭代的过程;从客户端到(ISP的)本地DNS服务器的查询是递归的过程;从本地服务器到根/域服务器的查询是迭代的过程

  1. 客户端到本地DNS服务器的递归查询,在统称为DNS高速缓存中查询,流程如下:

image.png

  1. 如果从本地DNS服务器上查不到IP地址,就要本地DNS服务器从根/域服务器上迭代查询,如果在某个根/域服务器上查到直接返回给客户端并在DNS高速服务器中缓存

迭代查询的流程如下:假设需要查询mail.goole.com的地址,本地DNS服务器首先向根服务器查询mail.google.com的IP地址,根服务器说:我不知道,但是我有com顶级域名服务器的地址,你去问他吧;本地DNS服务器继续向com域名服务器地址查询mail.google.com的IP地址,com服务器说,我不知道但我知道google.com的IP地址,你去问他吧。。。直到找到mail
.google.com的地址返回给本地DNS服务器,IP地址返回给客户端并在DNS高速服务器中缓存。流程如下所画
image.png

  1. DNS负载均衡

现在网站都有多个服务器,当一个网站访问量过大,如果所有的请求都访问同一个服务器,这个服务器可能会崩掉。
当一个网站有多个服务器时,每次应答DNS查询时可以解析成不同的IP地址,引导用户访问不同的服务器,从而达到负载均衡的目的。
应答的IP地址可以根据服务器负载情况,距离用户远景而定。

  1. DNS预解析

大型网站有很多资源需要,需要预加载的时候考虑使用DNS预解析。可以解析当前页面没有跨域资源的DNS。
使用link标签<link rel="dns-prefetch" href="//google.com">,有如下几个注意点

  • 必须是跨域资源,因为本站的IP已经被解析
  • 考虑配合preconnect预先建立TCP/IP连接,TLS握手使用,进一步减少跨域请求的延迟
  • 预解析的数量适当,否则适得其反

截屏2022-03-08 23.11.37.png
问题:大家都访问DNS根服务器,能承受的住吗?
答:有DNS缓存技术和DNS负载均衡,大多数查询都绕过了根服务器。
参考:是时候搞懂DNS了

2. TCP/IP连接

4)TCP/IP:三次握手

TCP/IP协议族是互联网普遍使用的4层网络模型,和OSI的七层网络模型对比如下:

OSI TCP/IP 作用
应用层 应用层 为应用程序提供网络服务
表示层 数据格式化,加密,解密
会话层 建立,维护,管理会话连接
传输层 传输层 建立,维护,管理端到端连接
网络层 网络层 IP寻址与路由控制
数据链路层 链路层 控制网络层与物理层之间的通信
物理层 比特流传输

TCP/IP连接的三次握手的流程如下:

  1. 第一次:客户端A发送SYN=1,产生随机数Seq Number=X(123456)的数据包发动到服务端B,B由控制位的SYN=1知道A需要建立连接。
  2. 第二次:B发送SYN=1,ACK=X+1,Seq Number=Y,随机数Seq Number=Y的数据包发送到A。这一步B确认了A的发送能力。此时B处于半连接状态SYN_RCVD
  3. 第三次:A收到后检查SYN==1,ACK==X+1是否正确。然后发送ACK=Y+1,Seq Number=Z的数据包给B,B收到后确认ACK和Seq Number后就代表连接完成。这里A确认了B的发送和接收能力,B确认了A的接收能力

一. 前端整理 HTML CSS - 图24
参考:浏览器输入url后发生了什么

TCP/IP断开连接的四次挥手
TCP/IP的连接是全是双工的,允许任何一端优先发起断开连接的操作。如果主机A发起断开连接的数据包,意味着它不再发送信息,但可以接收信息,所以需要两个方向上分别断开连接。
流程如下:

  1. 第一次挥手:主机A发送FIN=1,Seq Number=X的断开请求;
  2. 第二次挥手:主机B接受到后,发送ACK=X+1。主机B知道主机A需要断开连接
  3. 第三次挥手:主机B发送FIN=1,Seq Number=Y的数据包
  4. 第四次挥手:主机A接受后,发送ACK=Y+1的数据包;主机B接收后确认连接断开

image.png

3. HTTP请求

5) HTTP

HTTP的特点如下:

  1. 灵活可拓展:报文只规定了基本的格式,可以请求各种类型的数据
  2. 可靠传输:基于TCP/IP传输报文
  3. 无状态:请求之间没有上下文信息,都是独立的
  4. 请求-应答机制:代理服务器也可以发送请求
  5. 明文传输:报文头部使用文本传输,带来安全隐患
  6. 队头阻塞:当http开启长连接,共用一个TCP连接,一次只能处理一个请求;如果当前请求处理时间过长,造成对头阻塞
    1. HTTP报文的结构
    HTTP请求和响应的报文一致,都为起始行+请求头+空行+实体
    请求报文:
    1. GET /home HTTP/1.0 // 请求起始行组成:方法 + URI + HTTP版本
    2. Host: mcs.snssdk.com // 请求头:字段名不区分大小写
    3. Connection: keep-alive // 字段名不能有空格
    4. Content-Length: 1020 // 字段后紧跟:
    5. // 空行:分隔请求头和实体
    6. Hello World // 实体:空行后面全是实体内容,可以没有实体
    响应报文: ```http HTTP/1.1 200 OK // 响应起始行组成:HTTP版本 + 状态码 + 响应短语
    Cache-Control: private, max-age=0, no-cache Content-Length: 43 Content-Type: image/gif

Hello World

  1. <a name="ffLgj"></a>
  2. ###### 2. 请求方法和作用
  3. | 请求方法 | 支持HTTP版本 | 作用 |
  4. | --- | --- | --- |
  5. | Get | 1.0,1.1 | 获取指定uri上的资源 |
  6. | Post | 1.0,1.1 | 提交,上传数据 |
  7. | Head | 1.0,1.1 | 获取响应头信息 |
  8. | Put | 1.0(非标准支持),1.1 | 修改指定uri上的资源 |
  9. | Delete | 1.0(非标准支持),1.1 | 删除指定资源上的数据 |
  10. | Options | 1.1 | 列出可以对资源请求的方法,用于跨域 |
  11. | Trace | 1.1 | 追踪请求-响应的传输路径 |
  12. | Connect | 1.1 | 建立连接隧道,用于代理服务器 |
  13. <a name="ICXQc"></a>
  14. ###### 3. 状态码
  15. | 状态码 | 功能 | 举例详情 |
  16. | --- | --- | --- |
  17. | 1xx | 告知请求的进度和状态 | 100 continue 继续<br />101 Switching Protocols 切换协议 |
  18. | 2xx | 请求成功的状态码 | 200 OK 请求成功<br />204 No Content 请求成功没有响应体<br />206 Partial Content 分块返回,这知识部分内容 |
  19. | 3xx | 重定向等,需要进一步操作完成请求 | 301 Moved Permanently 永久重定向<br />302 Found 临时重定向<br />304 Not Modified 未修改 请求命中协议缓存 |
  20. | 4xx | 请求报文错误 | 400 Bad Request 请求语法错误<br />401 Unauthorized 要求用户身份认证<br />403 Forbidden 权限不够<br />404 Not Found 请求的资源服务器上不存在<br />405 Method Not Allowed 请求的方法不支持 |
  21. | 5xx | 服务器错误 | 500 Internal Server Error 服务器内部发生错误<br />501 Not Implemented 不支持请求的功能<br />502 Bad Gateway 作为代理服务器向上游请求的服务无效 |
  22. 参考:[状态码](https://www.runoob.com/http/http-status-codes.html)<br />问题:Get和Post的区别?<br />答:从5个角度回答这个问题
  23. 1. 从**语义**的角度,Get用于获取资源,Post用于上传资源
  24. 2. 从**参数**的角度,Get参数放在URL中,URL总长度限制为2048字符,Post参数放在请求体中,更加安全
  25. 2. 从**编码**的角度:Get只能URL,只允许ASCII类型的字符,Post没有限制
  26. 2. 从**缓存**的角度:Get默认被浏览器缓存,可以收藏,Post默认不会被缓存
  27. 2. 从**幂等**的角度:Get是幂等的,Post不是(幂等:执行相同的操作,结果也相同
  28. 问题:HTTP/1.0和HTTP/1.1的区别<br />答:
  29. 1. **支持长连接**:支持长连接和请求流水线,在同一个TCP连接上传送多个请求和响应,默认`Connection: keep-alive`
  30. 1. **缓存处理**:http1.1增加强缓存`Cache-Control`的和协商缓存的`ETag`和`If-None-Match`header支持
  31. 1. **分块传输/断点续传**:增加状态码206(Partial Content)和header`range`,允许只请求部分资源,提供断点续传支持
  32. 1. **host头处理**:增加`host`header以支持一个IP上有不同的服务
  33. <a name="KblRX"></a>
  34. ##### 6) HTTPS
  35. HTTPS是将HTTP数据包通过SSL/TLS加密后传输,TLS是SSL的升级版,目前主流在用版本是TLS1.3,默认端口是443;使用**非对称加密+对称加密**的方式通信。HTTPS通信在传输层需要7次握手(TCP/IP 3次 <br />+ TLS 4次)<br />HTTPS的**优点**是:更加安全,增加中间人攻击的成本。**缺点**是加密耗费资源,响应时间增加,CA认证收费<br />**TLS四次握手的流程:**<br />**客户端**
  36. 1. 客户端发送`Client Hello`消息,包含支持的协议版本,加密协议,压缩算法,客户端生成的随机数X
  37. **服务端**
  38. 2. 服务端收到请求,发送`Server Hello`消息,包含选择的协议版本,加密协议,压缩算法,服务端生成的随机数Y;
  39. 2. 发送`Certificate`消息,即证书链,包含支持的域名,有效日期,发行商信息
  40. 发送`Server Key Exchange`消息,将公钥Pub,Certificate Signature签名给客户端<br />发送`Server Hello Done`消息,表明消息发送完成<br />**客户端**
  41. 4. 客户端收到证书,校验证书合法性,如果不合法现实HTTPS警告信息
  42. 4. 校验通过,发送`Client Key Exchange`消息,客户端随机生成key,使用证书内公钥Pub加密生成预主密钥发送给服务端
  43. 4. 发送`Change Cipher Spec`消息,通知服务端后面的消息加密发送,会话密钥由**X+Y+预主密码**生成
  44. 4. 发送`Finished`消息,包含加密后的握手信息
  45. **服务端**
  46. 8. 服务端使用私钥Private得到随机key(会话密钥),发送`Server Key Exchange`消息,通知客户端后面消息使用加密发送
  47. 8. 发送`Finished`消息,验证客户端的`Finished`消息并完成TLS握手
  48. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1646743360626-59925bfe-eae4-4ca3-9dd8-257d59073ed6.png#clientId=u632c1995-f932-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=414&id=u4bb4fc49&margin=%5Bobject%20Object%5D&name=image.png&originHeight=910&originWidth=1304&originalType=binary&ratio=1&rotation=0&showTitle=false&size=350929&status=done&style=none&taskId=u7109fda5-d383-4eef-8ae2-8bbb52494a4&title=&width=592.7272598802554)<br />参考:[HTTPS详解](https://juejin.cn/post/6844904127420432391)<br />**证书合法性校验:**<br />数字证书包含以下信息:
  49. - 公钥
  50. - 持有者的信息
  51. - 证书认证机构的信息(CA)
  52. - 证书的数字签名(Certificate Signature)
  53. - 证书有效期
  54. - 其他信息
  55. CA签发证书的过程:
  56. 1. CA机构将持有者的公钥,用途,颁发机构,有效日期打包,并使用在哈希算法生成哈希Hash1
  57. 1. 使用CA私钥生成数字签名Certificate Signature,这一步是CA对证书做了签名
  58. 1. 将签名包含在文件证书中,形成数字证书
  59. 证书验证过程:
  60. 1. 客户端将从服务端收到的数字证书分解成明文Text和签名Sign
  61. 1. 将明文Text使用同样的哈希算法生成Hash2
  62. 1. 使用操作系统或浏览器中的CA公钥解密签名Sign得到Hash3
  63. 1. 对比Hash2和Hash3,如果相同说明证书通过
  64. 下图是证书验证的过程<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1646743276137-5d599e35-ad12-4a41-9670-d064e0d6b077.png#clientId=u632c1995-f932-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=272&id=u7c8279d8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=598&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=308049&status=done&style=none&taskId=u68e747a0-2851-45cf-bcf8-89558ec44f7&title=&width=490.90908026892316)<br />参考:[浏览器是如何验证HTTPS证书的合法性?](https://www.zhihu.com/question/37370216/answer/1914075935)
  65. <a name="M4fYp"></a>
  66. ##### 7) HTTP2
  67. **特点:**
  68. 1. 二进制分帧层(Binary Framing Layer)
  69. 使用二进制传输代替原来的明文传输,一个HTTP消息被分解为一个或多个帧。这样头部也能压缩了。最小的传输单位是帧<br />![](https://cdn.nlark.com/yuque/0/2022/svg/23168078/1650272079433-030b3154-4ed2-4226-9e48-e02d4d9d84f4.svg#clientId=u9d8a8796-a2db-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u1ea6f910&margin=%5Bobject%20Object%5D&originHeight=150&originWidth=291&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u7f228c39-6abc-4da6-86e5-0668e1075da&title=)
  70. 2. 流,消息和帧(Stream,message and frames)
  71. 1. 通信只需要一次TCP连接,可以传输任意数量的**双向流**
  72. 1. 每一个流都有一个唯一ID和可选的优先级参数
  73. 1. 一个HTTP消息由一个或多个帧组成
  74. 1. 帧是传输的最小单位,帧可以在不同的流之间传输,通过帧头的标识符组装
  75. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1650293883478-bca8f449-37c1-452e-ac43-3f426a872fab.png#clientId=ua0c34180-32e3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=381&id=u6d1cfdb1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1248&originWidth=1516&originalType=binary&ratio=1&rotation=0&showTitle=false&size=143388&status=done&style=none&taskId=u9c042c1b-0df3-4df1-9711-186ab9b3144&title=&width=463.09088134765625)
  76. 3. 请求和响应的多路复用(Request and response multiplexing)
  77. HTTP2将一个请求/响应消息分解为多个帧放在流中传输,和HTTP1.x一个TCP连接只允许同时传输一个消息不同,HTTP2允许在一个TCP连接中同时传输多个请求/响应的帧。有效的解决了队头阻塞和并行请求限制的问题<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1650296320803-f129a4d3-56f8-4876-a053-195504c51766.png#clientId=ua0c34180-32e3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=204&id=u61832e81&margin=%5Bobject%20Object%5D&name=image.png&originHeight=448&originWidth=1500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=76254&status=done&style=none&taskId=u077b270c-0a79-41fe-ac38-012e23eef11&title=&width=681.818167040171)
  78. 4. 流的优先级(Stream prioritization)
  79. 流的优先级由它可选的依赖和权重决定;权重取值1-256。如果一个流中A,B依赖于另一个流D。那全部资源优先处理D,然后处理A,B。如果A权重12,B权重4。那A获得3/4资源处理,B获得1/4资源处理(不是100%保证)。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1650296548361-3c01db61-f55b-4cb1-a65d-1899a7dda7ed.png#clientId=ua0c34180-32e3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=298&id=u2aad8156&margin=%5Bobject%20Object%5D&name=image.png&originHeight=656&originWidth=1514&originalType=binary&ratio=1&rotation=0&showTitle=false&size=67387&status=done&style=none&taskId=ubef90cd7-279f-460e-b6d1-8a7a613abea&title=&width=688.1818032658794)
  80. 5. 同源请求只需要一次连接(One connection per origin)
  81. HTTP2的连接是持久的,因为一个连接允许多个流同时传输,所以同一个源的请求只需要一次TCP连接。减少了TCP,TLS连接次数;也就减少了网络上数据传输量<br />参考:[Introduction to HTTP/2](https://web.dev/performance-http2/https://web.dev/performance-http2/)
  82. 6. 流控制(Flow control)
  83. HTTP2允许客户端和服务端在HTTP层面控制流的传输,避免发送端发送接受端无法处理/不想要的数据
  84. 7. 服务端推送(Server push)
  85. 允许服务端推送,如果服务器已经知道客户端需要哪些内容,可以直接提前推送的到客户端,无需客户端先请求再响应。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1650298512488-6c24b360-2159-4541-bd20-6cc2f4247eca.png#clientId=ua0c34180-32e3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=278&id=u0edc6537&margin=%5Bobject%20Object%5D&name=image.png&originHeight=612&originWidth=1504&originalType=binary&ratio=1&rotation=0&showTitle=false&size=109808&status=done&style=none&taskId=u36bd0384-b7a6-47a6-b126-bc8225d516e&title=&width=683.6363488189448)
  86. 8. 头部压缩(Header compression)
  87. HTTP1.x采用明文传输,头部无法压缩。HTTP2使用HPACK压缩头部,包含以下内容:
  88. 1. 允许头部使用静态哈夫曼编码,减少数据量
  89. 1. 客户端和服务端都维护和更新之前请求的头部字段索引列表;下一次只需要传输不变的头部的索引值
  90. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1650299119390-3a9df807-1c5b-47a1-ab1c-d62e6dd11e8c.png#clientId=ua0c34180-32e3-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=581&id=u5a406b70&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1278&originWidth=1520&originalType=binary&ratio=1&rotation=0&showTitle=false&size=196001&status=done&style=none&taskId=uab629e4a-6ba1-49ca-8675-438de2778af&title=&width=690.90907593404)
  91. <a name="oF549"></a>
  92. #### 4. 服务端返回HTTP报文
  93. 服务端处理请求并返回HTTP报文
  94. <a name="TWsmZ"></a>
  95. #### 5. 浏览器渲染页面
  96. <a name="Td0GZ"></a>
  97. ##### 1) 构建DOM树
  98. 渲染器按照如下的顺序构建DOM树<br />![](https://cdn.nlark.com/yuque/0/2022/jpeg/23168078/1646835001042-d7f53446-03ec-4e0c-a052-7930a66232a1.jpeg)<br />流程如下
  99. 1. 从网络或磁盘读取HTML原始字节
  100. 1. 根据指定的编码格式(UTF-8)将字节转化成字符串
  101. 1. 将字符串转换成token,如`<html>`,`<body>`等,token会标识出**起点标签,终点标签,文本**等信息
  102. 1. 将token转化为节点对象并构建DOM树,通过起点标签,终点标签等确定节点之间的关系;
  103. token到DOM树是同步转化的,即生成的token会立马转化成节点对象Node并添加到DOM树中<br />如果遇到**link标签的css节点**会并行请求并构建CSSOM树;<br />如果**遇到同步脚本会暂停构建DOM树,请求并构建CSSOM树(js可能修改css),然后执行脚本;最后继续构建DOM树**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1646842706603-af3a1a7f-0179-46fa-a904-77f9ec769ab3.png#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=384&id=u29ee5321&margin=%5Bobject%20Object%5D&name=image.png&originHeight=629&originWidth=1093&originalType=url&ratio=1&rotation=0&showTitle=false&size=110805&status=done&style=none&taskId=ud62cc640-08ea-4400-add7-4aed4ca4fae&title=&width=668)<br />![](https://cdn.nlark.com/yuque/0/2022/webp/23168078/1646837499411-763df984-21e8-4918-a679-488124bb1705.webp#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=364&id=u638d90a9&margin=%5Bobject%20Object%5D&originHeight=622&originWidth=1123&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u7b3939c6-68a8-420e-91cd-e930b3c56bb&title=&width=658)
  104. <a name="C3eWq"></a>
  105. ##### 2) 构建CSSOM树
  106. 构建CSSOM树和DOM树类似,他们之间并行运行,互不影响,除非遇见阻塞DOM的js脚本<br />这一步确定每个节点样式<br />![](https://cdn.nlark.com/yuque/0/2022/jpeg/23168078/1646835929511-4efc5e99-b647-4997-9717-f8e25fd05e39.jpeg)<br />![](https://cdn.nlark.com/yuque/0/2022/webp/23168078/1646837483672-311de61e-fc32-4da2-900a-6c92558f3f97.webp#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=261&id=u811b936b&margin=%5Bobject%20Object%5D&originHeight=299&originWidth=582&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u4a54188c-5d60-4ee7-867c-cd30485be65&title=&width=508)
  107. <a name="ye4Hm"></a>
  108. ##### 3) 构建渲染树Render Tree
  109. 将DOM树和CSSOM组合成渲染树,渲染树中**只包含显示的节点**和节点的样式信息,如`display:none`的元素不会在渲染树中<br />![](https://cdn.nlark.com/yuque/0/2022/webp/23168078/1646837468036-8a9e1834-a713-4092-bc13-502701f05439.webp#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=281&id=u61e92c5d&margin=%5Bobject%20Object%5D&originHeight=537&originWidth=1150&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u569c1ce9-3d29-40eb-9e6f-59f6fcd24c0&title=&width=601)
  110. <a name="zAVEn"></a>
  111. ##### 4) 构建布局树(布局/回流)
  112. 根据渲染树布局计算**元素的位置和大小**,构建布局树
  113. <a name="WMuBT"></a>
  114. ##### 5) 分层阶段,构建图层树
  115. 将拥有**层叠上下文属性**的节点和**需要被裁剪**的节点提升为渲染图层,构建图层树<br />![](https://cdn.nlark.com/yuque/0/2022/webp/23168078/1646840761266-79a844b7-fe09-4b2c-b6e6-6052a431f613.webp#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=292&id=u950c70b4&margin=%5Bobject%20Object%5D&originHeight=674&originWidth=1142&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u43ff2ce6-ac1b-4b10-9f5f-7b2640543e5&title=&width=494)
  116. <a name="Akfx3"></a>
  117. ##### 6) 绘制阶段/合成与栅格化(重绘)
  118. 1. 创建绘制列表:图层根据绘制指令按顺序创建绘制列表
  119. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/23168078/1646840281501-2c1bf93f-aace-44f8-90d6-7e79c35ca703.png#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=345&id=u3569638a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=880&originWidth=895&originalType=binary&ratio=1&rotation=0&showTitle=false&size=154927&status=done&style=none&taskId=u20c34c80-bc7a-4460-bd8c-a65cfad4853&title=&width=351)
  120. 2. 栅格化和合成:
  121. 上个的步骤都在渲染器主线程中进行;接下来主线程把绘制列表交给**合成线程**1,图层绘制列表即图层的信息<br />由于各个图层的大小不一,合成线程会把图层划分为图块,交给**栅格化线程池**,会优先栅格化视图附近的图块<br />栅格化线程池调用GPU加速栅格生成位图,**每一个图层对应一个位图**,保存在GPU内存中<br />合成线程将不同图层的位图合成为**合成帧**,交给浏览器主线程显示<br />![](https://cdn.nlark.com/yuque/0/2022/webp/23168078/1646842461389-315b49de-0591-4d7d-b2b7-f917b5b61032.webp#clientId=u1e312de1-56a7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=364&id=u5037e044&margin=%5Bobject%20Object%5D&originHeight=857&originWidth=1142&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u09fa7b6b-be9b-42fa-9f66-e0323ca1ab7&title=&width=485)
  122. <a name="XMFrs"></a>
  123. ##### 1. 问题:引发重排的css属性有哪些?
  124. 答:<br />改变元素几何信息(位置和大小)的操作都会引发重排;<br />但不是每次更新都引发一次重排,而是**异步更新**,修改的属性会存在队列中,每隔一个时间间隔便一起更新。当时如果用户**查询某些属性**,为确保属性值的精确性会清空队列更新引发重排
  125. 1. 页面首次渲染
  126. 1. 浏览器窗口大小发生变化
  127. 1. 元素大小或位置发生变化
  128. 1. 元素内容发生变化(文字数量,图片大小)
  129. 1. 元素内字体大小发生变化
  130. 1. 添加或删除**可见**的DOM元素
  131. 1. 激活css伪类
  132. 1. 查询某些参数(表格黑字部分)
  133. | width | height | margin | padding |
  134. | --- | --- | --- | --- |
  135. | display | border | position | overflow |
  136. | clientWidth | clientHeight | clientTop | clientLeft |
  137. | offsetWidth | offsetHeight | offsetTop | offsetLeft |
  138. | scrollWidth | scrollHeight | scrollTop | scrollLeft |
  139. | scrollIntoView() | scrollTo() | getComputedStyle()(存疑,测试发现不会清空队列) | getBoundingClientRect() |
  140. | scrollIntoViewIfNeeded() | | | |
  141. 对上面元素的注解,参考:[什么是client,offset,scroll](https://shubo.io/element-size-scrolling/)<br />clientWidth = width + 2 * padding<br />offsetWidth = width + 2 * padding _+ 2 _* border<br />![](https://cdn.nlark.com/yuque/0/2022/png/23168078/1646901141490-58861824-b4b8-4046-bb2e-e8d267eb588f.png#clientId=u6ef1036c-aa34-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=368&id=u4a2d0241&margin=%5Bobject%20Object%5D&originHeight=567&originWidth=630&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u9451b54d-e024-42b3-b200-5f54e781e8e&title=&width=409)<br />参考:[What forces layout / reflow](https://gist.github.com/paulirish/5d52fb081b3570c81e3a)
  142. <a name="AETo6"></a>
  143. ##### 2. 问题:引发重绘的css属性有哪些?
  144. 答:<br />元素样式的改变并不影响元素大小和位置的时候引发重绘
  145. | color | border-style | visibility | background |
  146. | --- | --- | --- | --- |
  147. | background-size | background-image | background-position | background-repeat |
  148. | outline | outline-style | outline-color | outline-width |
  149. | outline-radius | box-shadow | text-decoration | |
  150. <a name="SwCaq"></a>
  151. ##### 3. 问题:如何减少重排?
  152. css:
  153. 1. 避免使用table布局
  154. 1. 尽量在DOM树末端改变CSS,减少重排范围
  155. 1. 使用translate替代top、left等,translate使用GPU加速,不会引起重排重绘
  156. 1. 避免使用CSS表达式`calc()`
  157. 1. 避免设置多层的内联样式,如`div > p > span`
  158. 1. 将有动画效果应用在`position: absolute`或`position: fixed`的元素上
  159. js:
  160. 1. 分离读写操作
  161. 分离修改(引起重排的)属性的操作和读取(引起重排的)属性的操作
  162. ```javascript
  163. /** 每次读取offset都会强制刷新重排队列 */
  164. div.style.left = '10px';
  165. console.log(div.offsetLeft);
  166. div.style.top = '10px';
  167. console.log(div.offsetTop);
  168. div.style.width = '20px';
  169. console.log(div.offsetWidth);
  170. div.style.height = '20px';
  171. console.log(div.offsetHeight);
  172. div.style.left = '10px';
  173. div.style.top = '10px';
  174. div.style.width = '20px';
  175. div.style.height = '20px';
  176. console.log(div.offsetLeft);
  177. console.log(div.offsetTop);
  178. console.log(div.offsetWidth);
  179. console.log(div.offsetHeight);
  1. 集中改变样式

尽量将样式用一次修改操作完成

  1. // bad
  2. var left = 10;
  3. var top = 10;
  4. el.style.left = left + "px";
  5. el.style.top = top + "px";
  6. // good
  7. el.className += " theclassname";
  8. // good
  9. el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
  1. 缓存布局信息

通过缓存的方式保存强制刷新队列的属性,避免频繁读取

  1. // bad 强制刷新 触发两次重排
  2. div.style.left = div.offsetLeft + 1 + 'px';
  3. div.style.top = div.offsetTop + 1 + 'px';
  4. // good 缓存布局信息 相当于读写分离
  5. var curLeft = div.offsetLeft;
  6. var curTop = div.offsetTop;
  7. div.style.left = curLeft + 1 + 'px';
  8. div.style.top = curTop + 1 + 'px';
  1. 离线改变DOM
  • 隐藏DOM:先使用display:none,然后修改元素属性,这里不会影响DOM,最后设置display:block
  • documentFragment,批量插入DOM时可以使用
  1. 优化动画

对有复杂动画使用绝对定位,使其脱离文档流;避免父元素和后续元素频繁重排
合理启动硬件加速:对opacity,transform,filter应用动画

4. 问题:如何提升节点为渲染图层?

答:
拥有相同坐标空间的布局对象(LayoutObject)属于同一个渲染层(PaintLayer),满足形成层叠上下文条件的布局对象(LayoutObject)一定会为其创建渲染层
普通布局对象(NormalLayoutObject)

  1. 根元素(HTML)
  2. 有明确的定位属性(relative, fixed,sticky)
  3. 透明度小于1(opacity)
  4. 有CSS filter属性
  5. 有CSS mask属性
  6. 有CSS mix-blend-mode属性(不为normal)
  7. 有CSS transform属性(不为none)
  8. 有CSS backface-visibility属性(为hidden)
  9. 有CSS reflection属性(-webkit-box-reflection)
  10. 有CSS column-count,column-width属性(不为auto)
  11. 对当前元素的opacity,transform,filter,backdrop-filter应用动画

Overflow裁切渲染层(OverflowClipPaintLayer)

  1. overflow不为visible

NoPaintLayer

  1. 没有视觉元素的空div

其他的布局对象(LayoutObject)与其拥有第一个独立渲染层的父元素共用一个渲染层

5. 问题:如何提升为合成层呢?有哪些好处

答:满足某些特殊条件的渲染层会被提升为合成层;注意渲染层和合成层是不同的

  1. 3D transform属性:translatez,translate3d
  2. video,canvas,iframe等元素
  3. position:fixed元素
  4. 具有will-change的元素
  5. 对当前元素的opacity,transform,filter,backdrop-filter应用动画

合理的提升好处如下:

  1. 元素交由GPU渲染,更快
  2. 元素重绘只重绘本身
  3. 对于transform,opacity效果,不会触发重排和重绘

参考:深入浅出渲染器原理
从图层的角度去看关键渲染路径的布局到合成
对布局树进行分层,以及图层的绘制
浏览器渲染之图层绘制与栅格化操作
深入了解现代浏览器之三 - 渲染
浏览器层合成与页面渲染优化
无线性能优化:Composite

6. 断开TCP连接

四. CSS

1. 常见的定位方案

1) 普通流

普通流分为行内元素和块级元素,行内元素排列成一行,每个块级元素单独占一行;他们有不同的性质:
行内元素:

  • css属性为inlineinline-blockinline-table
  • 设置宽度width和高度height无效,宽度是内容的宽度,设置行高line-height有效
  • 只能容纳文本和其他行内元素

块级元素:

  • css属性为blocklist-itemtable
  • 可以容纳其他行内元素和块级元素
  • 外边距坍缩:

    • 嵌套的块级元素父元素与第一个直接块级子元素。最后一个块级上下边距会合并,取较长的那一个

      1. <!-- 上外边距和下外边距都产生了塌陷 -->
      2. <style>
      3. .parent {
      4. /* 如果不设置父元素的border,会导致外边距坍缩 */
      5. /* border: 1px solid black; */
      6. margin: 50px;
      7. background-color: aquamarine;
      8. }
      9. .son-top {
      10. margin: 50px;
      11. background-color: greenyellow;
      12. width: 50px;
      13. height: 50px;
      14. }
      15. .next {
      16. background-color: pink;
      17. margin-left: 50px;
      18. height: 50px;
      19. }
      20. </style>
      21. <div class="parent">
      22. <div class="son-top">son</div>
      23. </div>
      24. <div class="next"></div>
      25. </body>

      image.png

    • 元素之间上下外边距坍缩

      2) 浮动

      浮动可以设置向左浮动或向右浮动float:right,它有如下特性;

  1. 浮动脱离文档流,移动到包含块的边缘或另一个浮动元素的边缘按行排列,如果行宽容不下浮动元素则另起一行。
  2. 后面的块级元素会忽略浮动元素的存在
  3. 浮动元素虽然不影响其他元素布局,但是会影响其他元素的内容,其他元素的内容会围绕它
  4. 清除浮动:正常元素使用clear:both说明元素左右两边都不能有浮动元素

一. 前端整理 HTML CSS - 图27
一. 前端整理 HTML CSS - 图28一. 前端整理 HTML CSS - 图29

3) 定位技术

position属性,它有如下值:
static:默认值,元素按照普通流排序
relative:相对定位,元素仍然占有普通流的位置,可以使用top,left等让元素相对普通流位置偏移
absolute:绝对定位,元素脱离文档流,定位相对于最近relative父元素或body,可以用top,left偏移
fixed:绝对定位,元素脱离文档流,定位相对于视窗

2. 盒模型

块级元素的content + padding + border + margin构成了盒模型,分为标准盒模型和IE盒模型
标准盒模型:宽高width,height只包含content,CSS设置box-sizing:content-box
IE盒模型:宽高width,height包含content + padding + border,CSS设置box-sizing:border-box
image.pngimage.png

3. BFC 块级格式化上下文

BFC(Block Formatting Contexts)可以看作是迷你的独立容器,容器内部的元素不会再布局上影响到外部元素
创建BFC

  1. 根元素<html>
  2. 绝对定位元素positionfixedabsolute
  3. 浮动元素flex
  4. overflow不为none的元素
  5. 无副作用的display:flow-root
  6. 行内块display为inline-block的元素
  7. 表格标题和表格单元格displaytable-captiontable-cell
  8. 表格和行内表格displaytableinline-table
  9. 弹性布局display:flex的直接子元素
  10. 网格布局display:grid的直接子元素

BFC特性:

  1. BFC的元素包含float元素(因为容器内的元素不影响外部元素布局,即使是脱离文档流的)

image.png

  1. BFC可以解决父子元素的外边距坍缩(还是因为容器内的元素不影响外部元素布局)

image.png

  1. BFC可以阻止环绕float元素(因为float和环绕的元素都是BFC,互相独立)

image.png

4. 实现两栏布局(左侧固定,右侧自适应)

  1. <div class="outer">
  2. <div class="left"></div>
  3. <div class="right"></div>
  4. </div>

1) 浮动:

左侧float元素,宽度width固定,高度height固定全高;右侧设置BFC,固定的margin-left(可以不设置),宽度width自动,高度height固定全高

  1. .outer {
  2. height: 500px;
  3. }
  4. .left {
  5. float: left;
  6. width: 200px;
  7. height: 100%;
  8. background: lightcoral;
  9. }
  10. .right {
  11. display: flow-root;
  12. margin-left: 100px;
  13. height: 100%;
  14. background: lightseagreen;
  15. }

2) flex布局:

左侧固定宽度,右侧设置flex:1

  1. .outer {
  2. display: flex;
  3. height: 500px;
  4. }
  5. .left {
  6. float: left;
  7. width: 200px;
  8. height: 100%;
  9. background: lightcoral;
  10. }
  11. .right {
  12. flex: 1;
  13. margin-left: 100px;
  14. height: 100%;
  15. background: lightseagreen;
  16. }

3) 绝对定位:

父元素设为relative,左边元素absolute定位,固定宽度width,右边元素的margin-left设为左边的元素宽度

  1. .outer {
  2. position: relative;
  3. height: 500px;
  4. }
  5. .left {
  6. position: absolute;
  7. width: 200px;
  8. height: 100%;
  9. background: lightcoral;
  10. }
  11. .right {
  12. /** 200+100 */
  13. margin-left: 300px;
  14. height: 100%;
  15. background: lightseagreen;
  16. }

4) 绝对定位:

父元素设为relative,左边元素固定宽度width,右边元素absolute定位,left为左侧元素固定宽度,right, top, bottom设为0(让子元素填满没有明确高度和宽度的父元素)

  1. .outer {
  2. position: relative;
  3. height: 500px;
  4. }
  5. .left {
  6. width: 200px;
  7. height: 100%;
  8. background: lightcoral;
  9. }
  10. .right {
  11. position: absolute;
  12. /** 200+100 */
  13. left: 300px;
  14. top: 0;
  15. right: 0;
  16. bottom: 0;
  17. height: 100%;
  18. background: lightseagreen;
  19. }

5. 实现三栏布局(左右固定宽度,中间自适应)

1) 理解margin负值:

圣杯布局和双飞翼布局都用到了margin负值,所以先理解margin负值时元素的状态

  1. 没有浮动,没有设置定位position:static

设置margin-topmargin-left本元素向上或向左移动;
设置margin-rightmargin-bottom后续元素向左或者向上覆盖本元素。

  1. 没有浮动,设置相对定位position:relative

设置margin-topmargin-left本元素向上或向左移动(和1相同);
设置margin-rightmargin-bottom本元素向左或者向上覆盖本后续元素(和1相反)。

  1. 没有浮动,设置相对定位position:absolute

设置margin-topmargin-left本元素向上或向左移动(和1相同);
设置margin-rightmargin-bottom对后续元素没有影响(已经脱离文档流)。

  1. 设置浮动

浮动方向和负值margin方向一致则元素向相应位置移动
浮动方向和负值margin方向相反则后续、前续元素移动;按元素在HTML位置覆盖
参考:理解并运用 CSS 的负 margin 值

2) float布局实现三栏布局
  1. <style>
  2. .outer {
  3. display: flex;
  4. height: 600px;
  5. }
  6. .left {
  7. width: 100px;
  8. background: lightcoral;
  9. }
  10. .middle {
  11. flex-grow: 1;
  12. background: lightsteelblue;
  13. }
  14. .right {
  15. width: 100px;
  16. background: lightseagreen;
  17. }
  18. </style>
  19. <div class="outer">
  20. <div class="left"></div>
  21. <div class="middle"></div>
  22. <div class="right"></div>
  23. </div>

2) 圣杯布局
  1. 容器为BFC,设置padding,padding的宽度为左右元素的固定宽度;
  2. center,left,right都向左浮动
  3. center在最前面,且宽度占满屏幕;
  4. left和right都使用相对定位
  5. left的margin-left设置-100%,left向左移动左边元素的宽度
  6. right设置margin-right为-右边元素的宽度

    1. <style>
    2. .container {
    3. display: flow-root;
    4. padding: 0 200px 0 100px;
    5. height: 600px;
    6. }
    7. .center {
    8. float: left;
    9. width: 100%;
    10. height: 100%;
    11. background: lightblue;
    12. }
    13. .left {
    14. float: left;
    15. position: relative;
    16. margin-left: -100%;
    17. left: -100px;
    18. width: 100px;
    19. height: 100%;
    20. background: lightgreen;
    21. }
    22. .right {
    23. float: left;
    24. position: relative;
    25. width: 200px;
    26. height: 100%;
    27. margin-right: -200px;
    28. background: lightpink;
    29. }
    30. </style>
    31. <div class="container">
    32. <div class="center"></div>
    33. <div class="left"></div>
    34. <div class="right"></div>
    35. </div>

    参考:圣杯布局

    3) 双飞翼布局
  7. 容器为BFC

  8. center,left,right都向左浮动
  9. center在最前面,宽度依然占满屏幕。这次不通过容器设置padding,而是通过在center内部添加一个div,设置div的margin
  10. left和right不需要设置相对定位
  11. left的margin-left设为-100%
  12. right的margin-left设为负右元素的宽度

    1. <style>
    2. .container {
    3. display: flow-root;
    4. height: 600px;
    5. }
    6. .center {
    7. float: left;
    8. width: 100%;
    9. height: 100%;
    10. }
    11. .inner {
    12. margin: 0 200px 0 100px;
    13. height: 100%;
    14. background: lightblue;
    15. }
    16. .left {
    17. float: left;
    18. margin-left: -100%;
    19. width: 100px;
    20. height: 100%;
    21. background: lightgreen;
    22. }
    23. .right {
    24. float: left;
    25. margin-left: -200px;
    26. width: 200px;
    27. height: 100%;
    28. background: lightpink;
    29. }
    30. </style>
    31. <div class="container">
    32. <div class="center">
    33. <div class="inner"></div>
    34. </div>
    35. <div class="left"></div>
    36. <div class="right"></div>
    37. </div>

    6. 水平垂直居中的方法

    1) 绝对定位+translate

    对子元素没有要求

    1. <style>
    2. .father {
    3. position: relative;
    4. border: 4px dotted powderblue;
    5. width: 400px;
    6. height: 400px;
    7. }
    8. .son {
    9. position: absolute;
    10. top: 50%;
    11. left: 50%;
    12. transform: translate(-50%, -50%);
    13. background: lightcoral;
    14. }
    15. </style>
    16. <div class="father">
    17. <div class="son">这是一段文字</div>
    18. </div>

    2) 绝对定位+margin

    让子元素占满父元素,然后使用margin:auto平分可分配空间;需要子元素有明确的宽高

    1. <style>
    2. .father {
    3. position: relative;
    4. border: 4px dotted powderblue;
    5. width: 400px;
    6. height: 400px;
    7. }
    8. .son {
    9. position: absolute;
    10. top: 0;
    11. right: 0;
    12. bottom: 0;
    13. left: 0;
    14. margin: auto;
    15. width: 100px;
    16. height: 100px;
    17. background: lightcoral;
    18. }
    19. </style>
    20. <div class="father">
    21. <div class="son"></div>
    22. </div>

    参考:margin 实现水平居中,垂直居中原理

    3) 绝对定位+负值margin

    将子元素的左上角定位到父元素中心,再利用负值margin向上向右移动子元素一半宽高,需要子元素有明确的宽高

    1. <style>
    2. .father {
    3. position: relative;
    4. border: 4px dotted powderblue;
    5. width: 400px;
    6. height: 400px;
    7. }
    8. .son {
    9. position: absolute;
    10. top: 50%;
    11. left: 50%;
    12. margin-top: -50px;
    13. margin-left: -50px;
    14. width: 100px;
    15. height: 100px;
    16. background: lightcoral;
    17. }
    18. </style>
    19. <div class="father">
    20. <div class="son"></div>
    21. </div>

    4) flex布局
    1. <style>
    2. .father {
    3. display: flex;
    4. justify-content: center;
    5. align-items: center;
    6. border: 4px dotted powderblue;
    7. width: 400px;
    8. height: 400px;
    9. }
    10. .son {
    11. width: 100px;
    12. height: 100px;
    13. background: lightcoral;
    14. }
    15. </style>
    16. <div class="father">
    17. <div class="son"></div>
    18. </div>

    7. flex布局

    flexbox根元素的属性

  13. display:定义弹性布局

  14. flex-flow:flex- direction和flex-wrap的缩写
    1. flex-direction:弹性布局的行,列,正,反方向
    2. flex-wrap:定义布局是否换行
  15. justify-content:定义主轴上元素的对齐方式
  16. align-items:定义交叉轴上元素的对齐方式
  17. align-content:定义交叉轴剩余空间的对齐方式
  18. gap:定义元素间空格的大小
    1. row-gap:定义每一行的宽度
    2. column-gap:定义每一列的宽度

flexbox子元素的属性

  1. order:元素的排列顺序,按数字大小排列
  2. flex:flex-grow,flex-shrink和flex-basis的缩写,默认flex-grow
    1. flex-grow,定义主轴上剩余空间的分配比例,默认0
    2. flex-shrink:当主轴上空间不足时定义压缩比例,默认1
    3. flex-basis:定义分配剩余空间之前元素占用的空间
  3. align-self:允许某个元素脱离align-items,自己在交叉轴上的对齐方式

参考:css-tricks,flexbox

8. display布局

太复杂啦,直接参考:css-tricks,grid

9. CSS优先级

css优先级按一定规则运算;!important优先级最高;其余由A,B,C,D的值确定;ABCD
组成数组从前向后比较;值大的优先级高。优先级相同后面覆盖前面。

  1. A是内联选择器;如果存在内联选择器,则A=1;否则A=0;
  2. B是id选择器出现的次数
  3. C是属性选择器,类选择器,伪类选择器出现次数的综合
  4. D是标签选择器出现的次数、

    10.CSS动画之transition

    transition动画是4个属性的集合transition: <transition-property> <transition-duration> <transition-delay> <transition--timing-function>;第一个时间属性分配给duration,第二个时间属性分配给delay。多个属性同时设定用分号间隔。

  5. transition-property:需要动画变换的属性,all表示所有变动的属性都加上过渡动画

  6. transition-duration:间隔时间
  7. transition-delay:延迟多少秒开始动画
  8. transition-timing-function:动画函数,是一个贝塞斯曲线;有预设值ease-out, ease-in等

transition的属性:

  1. 有一个事件transitionend
  2. 需要明确的开始和结束状态属性数值;auto属性可能会失效;如width:100pxwidth:auto
  3. 只能定义开始状态和结束两个状态
  4. transition是一次性的,不能重复发生,除非再次触发
  5. transition需要事件触发,所以没法在加载的时候自动触发

    11.CSS动画之animation

    animation是多个属性的集合:

  6. animation-name:动画名称,可以用keyframes定义

  7. animation-duration:动画持续时间
  8. animation-delay:动画延迟时间
  9. animation-timing-function:动画的时间函数
  10. animation-direction:动画播放顺序:normal,reverse,alternative,alternative-reverse等
  11. animation-iteration-count:动画重复次数,默认1;一直动下去设为infinite
  12. animation-play-state:设置播放running还是暂停paused

示例:

  1. <head>
  2. <style>
  3. .div {
  4. ...
  5. .
  6. animation-name: move, size;
  7. animation-duration: 3s;
  8. animation-timing-function: ease-in-out;
  9. animation-play-state: paused;
  10. animation-iteration-count: infinite;
  11. animation-direction: alternate
  12. }
  13. @keyframes move {
  14. 0% {
  15. left: 0;
  16. transform: rotate(0deg);
  17. }
  18. 100% {
  19. left: 500px;
  20. transform: rotate(720deg);
  21. }
  22. }
  23. @keyframes size {
  24. from { font-size: 25px; }
  25. to { font-size: 50px; }
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="div">
  31. 😊
  32. </div>
  33. <div>
  34. <button id="run">run</button>
  35. <button id="pause">pause</button>
  36. </div>
  37. <script>
  38. var ele = document.getElementsByClassName('div')[0];
  39. document.getElementById('run').addEventListener('click', function() {
  40. ele.style.animationPlayState = 'running'
  41. });
  42. document.getElementById('pause').addEventListener('click', function() {
  43. ele.style.animationPlayState = 'paused'
  44. });
  45. </script>
  46. </body>

12. css选择器

其他选择器都很简单;

1) 属性选择器:

[attr]包含这个属性的元素
[attr=value]包含这个属性,且值为value的元素
[attr~=value] 以空格分隔的多个值且至少一个为value
[attr|=value]属性值以value或value-开头
[attr^=value] 值以value开头
[attr$=value]值以value结尾
[attr*=value]值子串包含value

2) 组合选择器

`空格,后代选择器<br />>直接子代选择器<br />~一般兄弟选择器<br />+`紧邻兄弟选择器

3) 伪选择器

:伪类:元素的状态来选择,如a:visited
::伪元素:无法用HTML语义表达的元素,如p::first-line``div::before``div::after

13. 媒体查询media

1) @media查询媒体属性

匹配不同的CSS,@media是可嵌套的。分为几个不同的部分:

  1. @media css的@规则
  2. [media type] 可选的媒体类型,可以是screen,print,speech等
  3. (media feature)媒体属性,用括号包裹,里面是css规则;常见的(min-width: 100px)``max-``height``width``color
  4. operator逻辑运算符,有三个值and,or,not

    2) 在HTML CSS JS中的应用
  5. CSS:@media规则,可嵌套,@import可以使用。会执行匹配的那部分css代码

    1. @import url("./common.css") screen;
    2. .block {
    3. width: 100px;
    4. height: 100px;
    5. }
    6. @media screen and (min-width: 800px) {
    7. .block {
    8. background: red;
    9. }
    10. }
    11. @media screen and (max-width: 800px) {
    12. .block {
    13. background: green;
    14. }
    15. }
  6. HTML:可以在style,source,link等标签使用。匹配的css link会优先加载,但是当前不匹配的css link也会加载 ```html

花儿

  1. 3. JS:使用`windw.matchMedia`使用,`mediaQuery.addListener(cb)`添加监听。每当有**条件越过(匹配到或匹配离开)**的时候便会触发回调
  2. ```javascript
  3. const mediaQuery = window.matchMedia('(min-width: 700px)');
  4. function handler(e) {
  5. console.log('只要条件越界就会触发');
  6. }
  7. mediaQuery.addListener(handler);
  8. handler(mediaQuery);

五. 移动端布局

viewport适配方案

1) 单位:
  1. vw:viewport’s width的简写;1vw = 1%的window.innerWidth
  2. vh:viewport’s height的简写;1vh = 1%的window.innerHeight
  3. vmax: vw和vh中较小的那一个
  4. vmin:较大的那一个

    2) html中viewport设置
  5. viewport:利用meta viewport设置布局视口;content有如下属性 | 属性 | 作用 | | —- | —- | | width | 布局视口的宽度,可以是device-width或一个正整数 | | initial-sacle | 页面初始缩放值 | | minimun-scale | 允许用户缩放的最小级别 | | maximun-scale | 允许用户缩放的最大级别 | | user-scalable | yes或no,是否允许用户缩放 | | viewport-fit | ios11新增;
    contain、auto:可视化窗口完全包含内容
    cover:内容完全覆盖可视化窗口 |

一. 前端整理 HTML CSS - 图36

3) px自动转化为vw

使用postcss的插件postcss-px-to-viewport将px单位转换为vw单位;方便开发和调试
参考:2022 年移动端适配方案指南