前端知识体系之 HTML 指南

65 阅读16分钟

HTML 指南

本文档用于梳理 HTML 的重难点知识,用于复习巩固, 也用于面试谈经。

HTML 入门

官方文档:developer.mozilla.org/zh-CN/docs/…

HTML 元素

1 meta 元素

meta 元素用于定义浏览器的元数据(描述数据)。

在 meta 元素中,可以指定 SEO 相关的数据:Keywords - 关键字、description - 网页描述信息,比如:

<meta name="Keywords" content="React,Vue">
<meta name="description" content="The MDN Web Docs .." />

在 meta 元素中,可以指定 CSP(内容安全策略),比如:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; img-src https://*; child-src 'none';" />

其中,CSP 用于在 HTML 中限制内容(资源文件)的访问域名和运行方式,从而检测并削弱 XSS(跨站脚本)和数据注入等攻击。

在 meta 元素中,可以实现重定向,比如:

<head>
  <meta http-equiv="Refresh" content="0; URL=http://example.com/" />
</head>

在 meta 元素中,可以指定浏览器窗口大小,比如:

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

其中,"width=device-width" 代表浏览器窗口大小等于浏览器分辨率,"initial-scale=1" 代表页面的初始化缩放比例为 1。

注意:

  • 在 PC 端,浏览器窗口大小默认等于浏览器分辨率;在移动端,浏览器窗口大小默认不等于浏览器分辨率,所以需要进行指定。
  • user-scalable 属性用于控制界面缩放,但是实际测试后发现没有效果。

2 script 元素

script 元素用于执行内部 JS 代码,或者加载外部 JS 文件,示例:

<script src="./tool.js"></script>
<script>
  console.log('测试');
</script>

2.1 ES module

在 ES6 中,浏览器支持 ES module,通过 import 和 export 语法加载模块。在浏览器中使用 ES module,需要指定 script 元素的 type 为 module,示例:

<script type="module" src="./tool.js"></script>
<script type="module">
  import {test} from './tool.js';
  test();
</script>

2.2 async 与 defer 属性

async 与 defer 属性用于将 JS 文件变成非阻塞资源,从而加快浏览器的解析。

async 与 defer 属性有以下区别:

  • async 脚本的执行顺序由网络响应的顺序决定;defer 脚本的执行顺序由 HTML 中的顺序决定。
  • async 脚本不会阻塞 DOMContentLoaded 事件;defer 脚本会阻塞。

注意

  • 模块脚本(type="module" 的脚本)默认相当于 defer 脚本,添加 async 属性后会变成 async 脚本。
  • JS 文件作为阻塞资源的意义在于,防止 JS 修改 Dom 导致的界面重绘。如果需要将 JS 文件通过 async、defer 属性变成非阻塞资源,那么 JS 文件中最好不要修改 Dom,或者将修改 Dom 的代码单独提出来。

3 form 元素

forrm 元素一般用于提交用户信息。

3.1 表单提交

表单提交有两种方式:

  • HTML 方式:点击 submit 类型的按钮时,自动根据 form 的 action 属性提交请求。注意:按钮的类型默认为 submit 。
  • JS 方式:点击按钮时,先通过 e.preventDefault() 阻止 HTML 方式的提交,然后使用 AJAX 提交请求。

两种提交方式的区别:

  • HTML 方式会跳转页面;JS 方式不会跳转页面,而是局部更新 DOM。
  • HTML 方式发送的数据由表单决定;JS 方式发送的数据可以完全自定义。
  • HTML 方式没有同源限制;JS 方式有同源限制。
  • HTML 方式更加简单;JS 方式相对复杂。

3.2 表单校验

表单校验用于验证用户输入的数据是否正确,也用于保护网站安全。

为了用户的体验,表单校验需要遵循以下规范:

  • 显示明确的错误消息。
  • 放宽输入格式限制。
  • 指出错误发生的位置(特别是在大型表单中)。

3.3 文件上传

表单可以上传文件,只序进行以下设置:

  • input 元素指定 file 类型
  • Content-Type 指定 "multipart/form-data"

如何指定 Content-Type?

  • 在 HTML 方式中,通过 form 的 enctype 属性指定
  • 在 JS 方式 中,通过请求头的 Content-Type 指定

3.4 表单安全

常见的表单安全问题:

  • XSS(跨站脚本)攻击:向网页中插入恶意脚本代码。说明: 目前的浏览器已经能够过滤 XSS攻击。
  • CSRF(跨站点请求伪造)攻击:利用用户的登录信息执行不安全的请求。应对方案: 通过 SameSite 禁止跨站获取 Cookie。
  • SQL 注入:向服务端中插入恶意的 SQL 代码。应对方案: 对特殊字符进行转义。

对于表单安全,有一些通用的解决方法:

  • 对特殊字符进行转义
  • 对于输入内容的长度、格式进行限制。
  • 沙箱上传文件:将文件保存在专门的服务器中,防止有毒的文件感染主服务器。

4 input 元素

input 元素也叫输入框,一般用于录入用户信息。

4.1 input 的类型

input 的类型非常多,几乎可以实现任何功能。按照功能,可以对它进行以下分类:

  • 基本类型:

    • 文本:type="text",用于文本编辑。
    • 密码:type="password",用于密码编辑
    • 隐藏:type="hidden",用于数据占位。
  • 选择类型:

    • 单选:type="radio",用于单选框。
    • 多选:type="checkbox",用于多选框。
  • 按钮类型:

    • 按钮:type="button",用于普通按钮。
    • 提交:type="submit",用于表单提交按钮。
    • 重置:type="reset",用于表单重置按钮。
  • 校验类型:

    • 数字:type="number",用于表单提交时的数字校验。
    • 号码:type="tel",用于表单提交时的号码校验。
    • 邮箱:type="email",用于表单提交时的邮箱校验。
    • 网址:type="url",用于表单提交时的网址校验。
  • 日期类型:

    • 日期和时间:type="datetime-local",用于日期和时间选择。
    • 日期:type="date",用于日期选择。
    • 时间:type="time",用于时间选择。
    • 月:type="month",用于月份选择。
    • 周:type="week",用于周选择。
  • 其它类型:

    • 图片:type="image",用于图片展示。
    • 文件:type="file",用于文件选择。
    • 查询:type="search"。查询类型在输入时,会显示关闭按钮,点击关闭按钮,会清空输入框数据。
    • 滑块:type="range",用于滑块展示。
    • 颜色:type="color",用于颜色选择。

4.2 自动填充

浏览器默认会自动填充输入框的用户名和密码,如果想禁止这种行为,需要对密码框设置 autocomplete=“new-password”,比如:

<input type="password" autocomplete="new-password"/>

5 img 元素

img 元素属于替换元素(内容和尺寸由外部资源决定的元素),用于展示图片,

5.1 响应式图片

在小屏手机上加载大图片时,会浪费宽带。可以通过响应式图片,来解决这个问题。

创建响应式图片有两种方式:根据尺寸、根据像素比。

第一种是根据尺寸进行创建,在 img 中指定 srcset 和 sizes 属性,比如:

<img
  srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w"
  sizes="(max-width: 600px) 480px, 800px"
  src="elva-fairy-800w.jpg"
  alt="Elva dressed as a fairy"
/>

其中,srcset 表示可选图片的 URL 和尺寸,sizes 表示可选媒体条件和预期图片宽度。浏览器会根据窗口大小和 img 的 sizes 属性获取预期图片宽度,然后从 srcset 中选择最接近的图片。

注意:在谷歌浏览器上调试时,需要禁用缓存,否则修改视口宽度时,图片不会切换。

第二种是根据像素比进行创建,在 img 中指定 srcset 属性,在 srcset 中指定像素比,比如:

<img
  srcset="elva-fairy-320w.jpg, elva-fairy-480w.jpg 1.5x, elva-fairy-640w.jpg 2x"
  src="elva-fairy-640w.jpg"
  alt="Elva dressed as a fairy"
/>

其中,srcset 中的 x 代表像素比(可以通过 window.devicePixelRatio 获取)。根据像素比这种方式一般用于移动端,因为 PC 端的像素比固定为 1。

6 video 元素

video 元素属于替换属性,用于播放视频。

6.1 自动播放

出于用户体验的考虑,浏览器禁止了自动播放。但是不是完全禁止,无声的自动播放还是支持的。比如:

<video src="movie.webm" controls autoplay muted></video>

7 iframe 元素

iframe 元素用于加载其他 HTML 页面。

7.1 X-Frame-Options

X-Frame-Options:HTTP 响应头,用于标记网页在 iframe、embed、object 元素中的展示方式,从而避免点击劫持攻击。

X-Frame-Options 的可选值如下:

  • DENY:不允许在 frame 中展示
  • SAMEORIGIN:只允许在相同域名的页面中展示。

8 svg 元素

svg 元素用于展示矢量图。

8.1 svg 的使用方式

在 HTML 中使用 svg 时,有两种方式:

第一种,直接使用 svg 元素。

第二种,在 img 或 iframe 元素中引用外部的 svg 文件

在 CSS 中使用 svg 时,有三种方式:

第一种,使用 CSS 的 mask 属性展示 svg 中的 mark 元素,用于实现遮罩效果

第二种,使用 CSS 的 clip-path 属性展示 svg 中的 clipPath 元素,用于实现裁剪效果

第三种,使用 CSS 的 filter 属性展示 svg 中的 filter 元素,用于实现滤镜效果

8.2 svg 的优缺点

svg 的优点:

  • 高保真:放大后不模糊
  • 体积小:仅需储存少量的算法,而不是每个像素的信息
  • 可编辑:可以在 HTML 中直接编辑,而不需要通过图片编辑器
  • 可访问:svg 中的文本可以被访问,有利于 SEO

svg 的缺点:

  • 无法产生色彩艳丽、复杂多变的图像。

9 文本元素

一些不常见但是有用的文本元素如下:

  • sup :用于展示上标,比如:平方的符号
  • sub :用于展示下标,比如:二氧化碳的符号
  • del:用于展示文字的中划线。
  • ins:用于展示文字的下划线。
  • pre:用于保留空白字符。
  • kbd:用于展示电脑的按键。
  • code:用于展示计算机代码,一般在 pre 元素内部使用。

如果想展示隐藏内容(鼠标放入时会自动展示内容),可以使用 title 属性。

HTML 属性

1 crossorigin 属性

crossorigin 属性定义 link / script / img / video / audio 元素如何处理跨源请求。注意:处理跨域请求还需要服务端设置合适的 CROS 响应头。

crossorigin 属性具有以下可能的值:

  • anonymous:不需要身份验证,就能跨源下载
  • use-credentials:需要经过身份验证,才能跨域下载。
  • 空值:等同于设置 anonymous 。格式: crossorigincrossorigin=""

一般情况下,不需要指定 crossorigin 属性。但是在以下场景中使用跨域资源时,不指定 crossorigin 属性会遇到问题:

元素限制
img、audio、video当资源被放置在 canvas 中时,元素会标记为被污染的
script对错误日志 window.onerror 的访问将会被限制。
link使用了不合适的 crossorigin 标头的请求可能会被丢弃。

2 数据属性

数据属性就是 data-* 属性,允许我们在标准内于 HTML 元素中存储额外的信息,比如:

<div id="data" data-columns="3" data-index-number="12314">测试</div>

数据属性可以通过 JS 访问,比如:

<script>
  let data = document.querySelector('#data');
  console.log(data.dataset.columns);      // 3
  console.log(data.dataset.indexNumber);  // 1234
</script>

数据属性可以通过 CSS 访问,比如:

<style>
  div::before {
    content: attr(data-index-number);
  }
</style>

HTML 机制

1 浏览器的运行流程

浏览器网页的运行流程,从逻辑上可以分为以下五步:

  • 发送请求
  • 下载文件
  • 解析文件
  • 渲染页面
  • 用户交互

注意: 实际的运行流程中,有些步骤是并行的,这里只是为了方便讲解,才采用串行的方式。

1.1 发送请求

打开网站的步骤如下:

  1. 用户在浏览器上输入 URL(网址)
  2. 浏览器校验 URL 格式并获取域名
  3. 浏览器通过 DNS 解析域名,从而获取 IP 地址
  4. 浏览器通过三次握手与服务器建立 TCP 连接
  5. 浏览器通过 TLS 协商与服务器建立安全(基于 HTTPS)的连接
  6. 浏览器向服务器发送 HTTP 请求(一般是通过 GET 方式请求 HTML 文件)

1.2 下载文件

下载文件的步骤如下:

  1. 浏览器收到服务器返回的 HTML 文件后,就开始下载 HTML 中的资源文件,分为两种情况:

  2. 第一种是高级资源(html、css、font、js等),使用预加载扫描器在后台下载

    1. 预加载扫描器扫描到 HTML 中的外链资源时,就按照优先级创建请求对象放入请求队列中
    2. 预加载扫描器同时从请求队列中取出高优先级的请求对象,放入下载队列(最多六个下载任务)中开始下载。
    3. 当下载队列出现空闲时,预加载扫描器再次从请求队列中取出高优先级的请求对象进行下载。
  3. 第二种是低级资源(image、vedio、audio等),当解析器解析到该资源时开始下载。由于 js 会阻塞 HTML 的解析,所以低级资源会在所有的 js 文件下载后开始下载。

在同一个请求队列中,请求对象的优先级由资源文件的默认优先级决定,具体规则如下:

  • 高等:html、css、font、同步请求
  • 中等:js、ajax
  • 低等:manifest、preload 资源
  • 更低:image、vedio、audio
  • 最低:prefetch 资源、defer 资源。

注意

  • 下载资源的顺序由资源在 HTML 中的位置和默认优先级共同决定。在 body 中加载 js、css 时,它们的下载顺序由 HTML 中的位置决定。
  • TCP 传输时,第一个数据包为 14 KB,后面的数据包依次倍增。如果 HTML 文件大于 14 KB,那么浏览器收到第一个数据包后也会对其解析。
  • 浏览器为每个域名最多建立 6 个 TCP连接,如果尝试大于这个数字,就有触发服务器 DoS 保护的风险。所以,下载队列中最多只能放入六个请求对象。
  • prefetch 资源会在浏览器空闲时下载,用于后续页面的预加载;preload 资源用于当前页面的预加载。但是在最新版本的谷歌浏览器中测试发现,preload 并不能提高资源的优先级。

1.3 解析文件

解析文件是将资源文件转化为 DOM 和 CSSOM 的过程,解析过程分为以下部分:

  • 构建 DOM 树:

    1. 浏览器收到 HTML 文件后,解析器就开始解析 HTML 的元素并按照树形结构创建 DOM 树
    2. 解析器遇到非阻塞的资源文件(比如:图片、CSS 文件)后,就继续解析,同时下载低级资源。
    3. 解析器遇到阻塞的资源文件(比如:JS 文件)后,就等待资源文件下载、解析并执行后,继续解析。
    4. 当 HTML 元素解析完了,DOM 树就构建好了。
  • 构建 CSSOM 树:

    1. 当 CSS 文件下载后,解析器就开始解析它,并创建 CSSOM 树
    2. 解析器遍历 CSS 中的每个规则集,根据 CSS 选择器创建具有父、子和兄弟关系的节点树。
    3. 当 CSS 的规则集解析完,CSSOM 树就构建好了。
  • JS 编译:

    • 当 JS 文件下载后,会被解析成抽象语法树
    • 浏览器引擎会将抽象语法树传给解释器,输出在主线程上执行的字节码

1.4 渲染页面

渲染页面的步骤如下:

  • 计算样式:所有节点的最终样式。

    • 当所有的 CSS 文件解析完,就开始渲染并创建 Render(渲染) 树。此时,DOM 树如果没有解析完,就继续并行解析。
    • 遍历 DOM 树,找到非隐藏元素加入 Render 树中
    • 遍历 Render 树的节点,根据其 style 属性和 CSSOM 树中的样式,确定节点的最终样式
  • 确定布局:确定所有节点的大小和位置。

    • Render 树从根节点开始遍历
    • 根据当前节点及其子节点的最终样式,确定当前节点的大小和位置。
    • 如果遇到未定义尺寸的替换元素(比如:图片),就先给给它提供占位空间。
    • 当前所有节点的大小和位置确定好,布局就确定好了。
    • 如果样式发生了变化(比如:图片的大小确定了),就会修改节点的大小和位置,这个过程叫作回流
  • 绘制页面:将布局后的每个节点换为屏幕上的实际像素

    • 如果 HTML 中不包含 video 和 canvas 元素,那么就直接将所有节点绘制到屏幕中
    • 如果 HTML 中包含 video 和 canvas 元素,那就 video 、canvas、其他节点分为多个层,每个层单独绘制,最后合成到一起。

注意:

  • CSS 文件决定了元素的样式和布局,所以要等到所有 CSS文件解析完,才开始渲染。
  • 为了不造成卡顿,包括计算样式、回流、绘制的渲染过程,需要在 16.67 毫秒内完成。

1.5 用户交互

用户交互:

  • 当页面渲染完成,用户就可以看到完整的页面了
  • 当 JS 执行完成后,用户就可以进行交互了,因为 JS 的执行会阻塞浏览器主线程。

2 分辨率与像素比

浏览器展示内容的大小跟以下内容有关:

  • 设备分辨率:设备的屏幕像素宽高。例如,vivo X21 的设备分辨率是:2280x1080 像素
  • 浏览器分辨率:设备在展示浏览器页面时,使用的屏幕像素宽高。例如,vivo X21 的浏览器分辨率是:760x360 像素。
  • 浏览器窗口大小:浏览器实际展示内容的像素宽高。例如,vivo X21 的默认浏览器窗口(也叫虚拟窗口)大小是:1693 x 980 像素。
  • 像素比(drp): 设备分辨率 / 浏览器分辨率。例如,vivo X21 的像素比是 3x。

在 PC 端,浏览器分辨率与设备分辨率相同;在移动端,浏览器分辨率与设备分辨率不同,因为移动手机的高分辨率是为了展示高清图片,如果用这么高的分辨率展示浏览器页面,那就会看不清。

在 PC 端,浏览器的默认窗口大小跟浏览器分辨率一致;在移动端,虽然对浏览器分辨率做了优化,但是浏览器不清楚实际的展示内容,所以默认窗口大小跟浏览器分辨率不一致。例如,vivo X21 默认使用 1693 x 980 的窗口大小渲染页面,然后页面将缩小以适应 360px 的空间。

浏览器的分辨率可以通过 JS 查看:

let width = window.screen.width; // 屏幕的宽度
let height = window.screen.height; // 屏幕的高度:包含电脑底部任务栏的高度
let availWidth = window.screen.availWidth; // 屏幕的可用宽度
let availHeight = window.screen.availHeight; // 屏幕的可用高度:不包含电脑底部任务栏的高度

浏览器的窗口大小可以通过 JS 查看:

let clientWidth = document.documentElement.clientWidth; // 浏览器的窗口宽度
let clientHeight = document.documentElement.clientHeight; // 浏览器的窗口高度:不包含浏览器的标签栏
let scrollWidth = document.documentElement.scrollWidth; // 浏览器的窗口滚动条宽度
let scrollHeight = document.documentElement.scrollHeight; // 浏览器的窗口滚动条高度

像素比可以通过 JS 查看:

let drp = window.devicePixelRatio; // 像素比