一、语义化与文档结构
1.1 语义化分区标签
-
标签 :
<header>,<footer>,<main>,<nav>,<article>,<section>,<aside> -
作用 :
- 构建清晰的文档大纲(Document Outline),便于搜索引擎与辅助技术解析页面结构。
<main>标识核心内容,每个页面仅使用一次,有助于屏幕阅读器跳过重复区域直接定位内容。<article>表示可独立分发、复用的完整内容单元(如博客帖子、评论区每条留言)。<section>需配合标题使用,若无标题则不构成语义分区,此时用<div>更合适。
-
使用示例 :
html<body> <header>站点导航与Logo</header> <main> <article> <h1>文章标题</h1> <section><h2>小节</h2><p>小节内容</p></section> </article> </main> <footer>版权信息</footer> </body> -
架构师关注点 :不要因为 CSS 布局而滥用
<div>替代语义标签;在单页应用中,为动态内容合理嵌套<article>/<section>可提升辅助技术对不同路由视图的理解。
1.2 标题层级 (<h1>--<h6>)
-
作用:形成内容层次树。屏幕阅读器用户可通过标题跳转快速了解内容结构并导航,大约 60% 以上的读屏用户依赖标题导航。
-
规则 :
- 每页或每个
<main>区域仅一个<h1>(HTML 规范允许多个,但无障碍最佳实践建议单一h1)。 - 不跳级(h1 → h2 → h3,而非 h1 → h3)。
- 结合
<section>/<article>使用时,理论上浏览器会根据嵌套层级自动计算标题级别,但实际辅助技术支持极差,不应依赖此特性,始终显式使用正确的标题等级。
- 每页或每个
-
示例 :
html<h1>产品介绍</h1> <section><h2>特性</h2><h3>性能</h3></section>
1.3 <search> 元素
-
作用 :标记搜索表单或搜索功能区,成为 ARIA
role="search"的语义替代,辅助技术可识别为搜索地标(landmark)。 -
使用 :
html<search> <form role="search"> <input type="search" aria-label="站内搜索"> <button>搜索</button> </form> </search> -
注意 :
<search>本身不替代<form>的功能性,也不自动赋予role="search"的 ARIA 含义------搭配<form role="search">是最稳妥的双保险做法,确保新旧辅助技术均可识别。
二、可访问性(A11Y)
2.1 ARIA 属性集
使用前提:优先使用原生语义标签(如 <button> 而非 <div role="button">)。原生元素自带键盘交互和角色语义,ARIA 仅用于补充无法用原生表达的场景。
-
常用属性 :
role:定义元素角色,如role="alert"表示动态通知区域,被朗读时不会打断当前操作。aria-label/aria-labelledby:提供可访问名称。前者直接赋值文本;后者引用页面已有元素的id作为标签,支持多引用(空格分隔),会按顺序拼接。aria-describedby:提供补充描述(如字段格式提示),与标签分离,读屏会在朗读标签后追加描述。aria-hidden="true":对辅助技术完全隐藏元素(含子元素)。适用于纯装饰图标、折叠面板中当前不可见的面板内容。aria-expanded:表示折叠/展开状态,与aria-controls搭配,指向被控元素的id。aria-current:标记当前项(如导航当前页),取值为page、step、location、true等。aria-live:设置动态内容区域朗读策略:off(默认,不朗读)、polite(等待当前朗读完成)、assertive(立即打断朗读)。适用于表单验证消息、状态通知。aria-atomic:配合aria-live使用,true时整个区域内容变化都会被朗读,false时仅朗读变化部分。
-
示例 :
html<button aria-expanded="false" aria-controls="submenu">菜单</button> <div id="submenu" aria-hidden="true">子菜单内容</div> <span id="hint">请输入8位以上密码</span> <input aria-describedby="hint"> <div aria-live="polite" aria-atomic="true" id="status"></div>
2.2 表单无障碍
-
<label>关联:html<!-- 隐式关联:input 嵌套在 label 内 --> <label>姓名 <input type="text"></label> <!-- 显式关联(推荐,兼容性最佳):for 指向 id --> <label for="email">邮箱</label><input id="email" type="email">显式关联允许
<label>与控件在 DOM 中分离,灵活性更高,且兼容老旧辅助技术。 -
<fieldset>+<legend>:用于分组相关的表单控件(如单选框组、多字段地址组),<legend>作为整个分组的标签被朗读。html<fieldset> <legend>支付方式</legend> <label><input type="radio" name="pay" value="card"> 信用卡</label> <label><input type="radio" name="pay" value="alipay"> 支付宝</label> </fieldset> -
<output>元素 :展示计算结果或用户操作反馈,需用for关联参与计算的控件id(空格分隔)。html<input type="range" id="a" value="50"> + <input type="range" id="b" value="50"> = <output for="a b">100</output>
2.3 焦点管理
-
tabindex:0:加入自然 Tab 顺序(默认不可聚焦的元素如<div>变为可聚焦)。-1:程序可通过el.focus()聚焦,但不参与 Tab 导航。常用于模态框打开时聚焦到对话框容器。- 正值(危险):自定义 Tab 顺序,几乎总是导致混乱,避免使用。
-
autofocus:页面加载时自动聚焦到指定控件,每页仅一个元素生效。 -
inert属性 :让整个元素区域及其子元素对交互、辅助技术完全不可见(类似aria-hidden+ 禁用交互的叠加效果)。模态框打开时,给背景内容添加inert最为干净彻底。这是较新的全局属性,替代了之前需要手动遍历焦点和加aria-hidden的繁琐方案。html<main inert>隐藏内容</main> <dialog>模态框</dialog>
2.4 表格可访问性
-
基础 :使用
<caption>提供表格标题;<th>标识表头单元格。 -
scope属性 :scope="col"(列表头)、scope="row"(行表头)------明确<th>方向,适合简单表格。 -
headers+id:复杂表格(跨行跨列)通过headers属性引用关联的<th id>,空格分隔多个 id。辅助技术会按引用顺序朗读表头。html<th id="cat">分类</th> <td headers="cat">...</td>
三、性能优化
3.1 资源提示(Resource Hints)
-
dns-prefetch:提前完成 DNS 解析,适合即将跳转的第三方域名。html<link rel="dns-prefetch" href="//api.example.com"> -
preconnect:完成 DNS + TCP + TLS(HTTPS)握手,开销大于dns-prefetch。仅用于确定即将使用的关键第三方源(如字体、API),数量控制在 4--6 个以内,且对已知不需要的源应及时关闭连接避免浪费。html<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>注:连接字体资源时,
crossorigin属性必须与后续请求的 CORS 模式一致,否则浏览器会打开两个连接。 -
prefetch:低优先级预取未来可能用到的资源(如下一页的 JS),浏览器空闲时加载,不保证一定被使用。html<link rel="prefetch" href="/next-page.js" as="script"> -
preload:提前声明当前页面必定使用 的关键资源,浏览器尽早开始下载且不阻塞渲染。必须指定as来告知资源类型,否则可能重复下载。html<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="hero.webp" as="image" imagesrcset="hero@2x.webp 2x" imagesizes="100vw">警惕滥用
preload:若资源在 3 秒内未被使用,Chrome 会在控制台打印警告,且会挤占更关键资源的带宽。
3.2 懒加载
-
loading="lazy"(<img>,<iframe>):- 作用:推迟视口外资源的加载,直到用户滚动到附近(阈值约视口高度的 1--4 倍,由浏览器实现决定)。
- 注意:必须显式设定宽高(
width/height或 CSSaspect-ratio)以避免布局偏移(CLS);首屏关键图片不加loading="lazy"(可能被浏览器推迟导致 LCP 恶化)。
html<img src="photo.jpg" loading="lazy" width="800" height="600" alt="..."> -
<iframe loading="lazy">:同样支持,延迟加载嵌入内容(如 YouTube 视频)。
3.3 获取优先级 (fetchpriority)
-
作用 :在 HTML 标签级别调整资源加载优先级(
high/low),影响浏览器内部优先级队列。 -
适用元素 :
<img>,<link>,<script>等。 -
典型场景 :LCP 图片设为
high;非关键的背景图脚本设为low。html<img src="hero.jpg" fetchpriority="high" loading="eager"> <script src="analytics.js" fetchpriority="low" async></script> -
注意 :
fetchpriority只调整同类型资源的相对优先级,不能把图片优先级提到高于页面关键 CSS。且与loading="lazy"组合时可能产生冲突,LCP 图片应使用loading="eager"或省略。
3.4 脚本加载策略
-
<script>默认行为 :HTML 解析到<script>(无属性)时暂停解析,下载并立即执行,之后才继续解析------完全阻塞后续 DOM 构建。 -
defer:异步下载,不阻塞解析;HTML 解析完成后按 DOM 顺序依次执行,且在DOMContentLoaded事件之前。适用于依赖完整 DOM 的脚本。html<script src="app.js" defer></script>多个
defer脚本严格按文档顺序执行,即使某个脚本先下载完成也会等待前序脚本。 -
async:异步下载,不阻塞解析;下载完立即执行 ,执行时阻塞解析。执行顺序不可控(谁先下载完谁执行),适用于独立模块(如统计、广告)。html<script src="analytics.js" async></script> -
type="module":默认行为等同于defer(异步下载,解析后执行)。内联模块脚本也默认defer,可使用async覆盖。html<script type="module" src="main.js"></script>
四、安全
4.1 内容安全策略(CSP)---Meta 方式
-
作用 :通过
<meta>标签快速配置页面级策略,限制脚本、样式、图片等来源。与 HTTP 响应头Content-Security-Policy等效,但meta不支持frame-ancestors、report-uri(仅支持report-to)等指令。 -
示例 :
html<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.example.com 'nonce-{random}'; style-src 'self' 'unsafe-inline'"> -
nonce 机制 :服务端每次请求生成唯一随机数,同时注入
<script nonce="...">和 CSP 头中的script-src 'nonce-...',允许该特定脚本执行,阻止所有其他内联/外部脚本------XSS 即使注入<script>标签也因 nonce 不匹配而无法执行。
4.2 链接安全 (<a> / <area>)
-
rel="noopener":防止新页面通过window.opener访问原页面的window对象,避免 Tabnabbing 钓鱼攻击。所有target="_blank"的链接都应添加。 -
rel="noreferrer":额外阻止RefererHTTP 头发送,不暴露来源 URL。html<a href="https://external.com" target="_blank" rel="noopener noreferrer">外部链接</a>现代浏览器对
target="_blank"已隐式添加noopener,但为兼容旧浏览器,仍建议显式声明。
4.3 <iframe> 安全
-
sandbox属性 :默认施加最严格限制(禁止脚本、弹窗、表单提交、同源访问等),值用空格分隔以逐项放开 权限。allow-scripts:允许执行 JS(不能执行则无脚本攻击,但可能仍有其他风险)。allow-same-origin:允许被视为同源(此权限开启后allow-scripts会允许操作同源 DOM,结合时风险极高,慎用)。allow-popups:允许弹窗。allow-forms:允许表单提交。allow-top-navigation:允许修改顶层窗口。
html<iframe src="page.html" sandbox="allow-scripts allow-popups"></iframe> -
allow属性 (Permissions Policy / Feature Policy):控制嵌入内容能使用的浏览器特性(摄像头、麦克风、定位等)。底层依赖 Feature Policy 标准,HTTP 响应头名为Permissions-Policy。html<iframe src="videochat.html" allow="camera;microphone;fullscreen"></iframe>
4.4 Referrer Policy
- 作用 :控制请求中
Referer头的发送策略。 - 设置方式 :
<meta name="referrer" content="strict-origin-when-cross-origin">(默认推荐值:同源发完整 URL,跨域只发源,降级(HTTPS→HTTP)不发)- 单独元素属性:
<a>,<img>,<iframe>等可设referrerpolicy="no-referrer"等。 - 常见值:
no-referrer(完全不发)、same-origin(仅同源)、strict-origin(仅发源且降级不发)、unsafe-url(始终发完整 URL,隐私风险)。
五、SEO 与元数据
5.1 核心 Meta 标签
<meta charset="UTF-8">:必须在<head>最前面(前 1024 字节内),避免浏览器用错误编码解析后重新解码。<meta name="viewport" content="width=device-width, initial-scale=1">:移动端视口适配基础,缺省时移动浏览器会以 980px 左右的桌面视口渲染后缩放,导致文字极小。<meta name="description">:搜索结果摘要,虽不是排名直接因素,但影响点击率。<meta name="theme-color">:定义浏览器 UI 颜色(如地址栏),支持media属性适配亮暗模式。对 PWA 尤其重要。<meta name="color-scheme" content="dark light">:告知浏览器页面支持的配色方案,浏览器会据此调整默认表单控件、滚动条等原生 UI 的颜色,并与 CSSprefers-color-scheme协同。
5.2 Open Graph / Twitter Card
-
作用:控制分享至社交媒体(如微信、Facebook、Twitter)时展示的标题、描述、缩略图。
-
OG 标签 :
html<meta property="og:title" content="页面标题"> <meta property="og:description" content="页面描述"> <meta property="og:image" content="https://example.com/image.jpg"> <meta property="og:url" content="https://example.com/page"> <meta property="og:type" content="article"> -
Twitter Card (未配置时 Fallback 到 OG):
html<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="标题"> <meta name="twitter:image" content="...">
5.3 Canonical 链接
-
作用 :当同一内容有多个 URL 时(如带参数、排序、打印版本),指定权威 URL,避免搜索引擎索引重复内容并稀释排名权重。
html<link rel="canonical" href="https://example.com/product"> -
跨域 Canonical:支持指向不同域名的权威页面(如内容聚合场景),搜索引擎会将排名信号传递给指定的 URL。
5.4 结构化数据(Schema.org / JSON-LD)
-
作用:为搜索引擎提供机器可读的实体信息(产品、评价、食谱、组织等),有机会在搜索结果中展示为富文本摘要(星级、价格、库存等),显著提升点击率。
-
推荐格式 :JSON-LD(与 HTML 结构分离,维护成本低),放置在
<head>或<body>末尾均可。html<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "产品名称", "offers": { "@type": "Offer", "price": "99.00", "priceCurrency": "CNY" } } </script> -
验证工具:Google 富媒体搜索结果测试(Rich Results Test)和 Schema.org 验证器。
六、响应式与多媒体
6.1 <picture> 与 srcset/sizes
-
srcset+sizes(在<img>上):srcset:提供多张候选图及宽度描述符(300w指图片自身宽度 300px)或像素密度描述符(2x)。sizes:告知浏览器图片在不同视口条件下的显示宽度,帮助浏览器在选择加载哪张图之前就做出判断(不需要等到 CSS 布局计算完成)。
html<img src="default.jpg" srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w" sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw" alt="响应式图片">注意:
src作为不支持srcset的旧浏览器降级方案始终保留;sizes默认值100vw,省略时浏览器按全视口宽度选择。 -
<picture>元素:基于媒体查询的"艺术方向"(Art Direction)选择不同裁剪/比例的图片,或根据格式支持情况提供现代格式(如 WebP/AVIF)并降级。html<picture> <source srcset="image.avif" type="image/avif"> <source srcset="image.webp" type="image/webp"> <source media="(min-width: 800px)" srcset="desktop.jpg"> <img src="fallback.jpg" alt="兼容降级"> </picture>浏览器自上而下扫描
<source>,使用第一个 匹配的媒体条件和支持的格式,因此现代格式的<source>应放在最上方。
6.2 <video> / <audio>
-
preload:none:不预加载(节省带宽,用户点击播放才开始)。metadata(推荐):仅预加载元数据(时长、首帧尺寸),不下载媒体数据。auto:浏览器可能预加载整个文件(移动端通常忽略auto,为避免浪费用户流量)。
-
autoplay策略 :大部分浏览器只允许静音自动播放(muted必须同时设置),或有用户手势交互历史。 -
<track>字幕 :html<video controls> <source src="video.mp4" type="video/mp4"> <track kind="captions" src="subs.vtt" srclang="zh" label="中文" default> <track kind="subtitles" src="subs-en.vtt" srclang="en" label="English"> </video>kind取值:subtitles(翻译字幕)、captions(听障字幕,含音效描述)、descriptions(画面描述,读屏朗读)、chapters(章节导航)、metadata(脚本使用的不可见数据)。- WebVTT 格式(
.vtt)是标准字幕文件,可附带样式和定位信息。
七、现代交互与 Web 组件
7.1 <dialog> 元素
-
作用 :原生模态/非模态对话框。使用
showModal()打开时:- 自动置于顶层(top layer) ,无需手动设
z-index。 - 自动焦点管理(聚焦到对话框内第一个可聚焦元素)。
- 阻止对背景内容的交互(类似
inert)。 - 按
Esc键自动关闭。
- 自动置于顶层(top layer) ,无需手动设
-
关闭方式 :内部
<form method="dialog">提交可关闭对话框,<button value="cancel">会将dialog.returnValue设为cancel。html<dialog id="dlg"> <form method="dialog"> <p>确认删除?</p> <button value="confirm">确认</button> <button value="cancel">取消</button> </form> </dialog> <script> const dlg = document.getElementById('dlg'); dlg.showModal(); dlg.addEventListener('close', () => console.log(dlg.returnValue)); </script> -
::backdrop伪元素:自定义模态对话框背景遮罩样式。
7.2 popover 属性
-
作用 :声明式弹出层,无需 JS 即可控制显示隐藏。全局属性,适用于工具提示、下拉菜单、通知等。
- 自动顶层显示,自动焦点管理。
- Light dismiss:点击外部区域、按 Esc、切换窗口时自动关闭。
-
类型 :
popover="auto"(默认):同一时间仅允许打开一个 auto 型 popover,点外部即关闭。popover="manual":需程序控制打开/关闭,适用于互不排斥的弹出层。
-
触发 :使用
popovertarget属性指向 popover 的id;popovertargetaction可设show、hide、toggle。html<button popovertarget="tooltip">提示</button> <div popover id="tooltip">帮助文本</div>
7.3 <details> / <summary>
-
作用 :原生可折叠面板组件,不依赖 JS。
<summary>点击展开/收起内容。- 默认关闭,添加
open属性默认展开。 - 支持
<details name="group">实现手风琴效果(同name组中仅一个可打开)。
- 默认关闭,添加
-
示例 :
html<details name="faq"> <summary>常见问题一</summary> <p>答案</p> </details> <details name="faq"> <summary>常见问题二</summary> <p>答案</p> </details>
7.4 Web Components
Web Components 四件套,允许创建可复用、样式隔离的自定义元素。
-
Custom Elements(自定义元素):
- 两种类型:Autonomous custom elements(继承
HTMLElement)和 Customized built-in elements(继承内置元素如HTMLButtonElement,需extends选项,Safari 不支持,应避免使用)。 - 必须包含短横线命名(如
my-element),以防止与未来标准标签冲突。 - 生命周期回调:
constructor()(设置初始状态,不应操作 DOM 或属性)、connectedCallback()(挂载到 DOM,初始化渲染/事件)、disconnectedCallback()(清理)、attributeChangedCallback(name, oldVal, newVal)(属性变更时同步响应)、adoptedCallback()(移到新文档时触发,如iframe间移动)。
jsclass MyEl extends HTMLElement { static get observedAttributes() { return ['title']; } connectedCallback() { this.render(); } attributeChangedCallback(name, o, n) { this.render(); } render() { this.textContent = this.getAttribute('title'); } } customElements.define('my-el', MyEl); - 两种类型:Autonomous custom elements(继承
-
Shadow DOM:
- 封装内部结构和样式,防止外部 CSS 侵入,内部样式也不会泄露到外部。
mode: 'open':外部可通过element.shadowRoot访问;'closed':不可访问(极少使用,调试困难,安全性等同于open,因为攻击者仍可劫持attachShadow)。
jsthis.attachShadow({ mode: 'open' }).innerHTML = `<style>:host { display:block }</style><slot></slot>`;:host选择器:定义 Shadow DOM 宿主元素的样式。:host-context():根据宿主在外部 DOM 中的祖先选择器来应用样式(如.dark :host-context(.dark)),性能较差,谨慎使用。- CSS 自定义属性(
--)可穿透 Shadow 边界,是实现主题化的主要手段。
-
<template>与<slot>:<template>内容不渲染,需 JS 克隆后激活。适用于在 HTML 中预定义 Shadow DOM 模板。<slot>:内容投影点。默认插槽(匿名)和命名插槽(name属性)。外部放置在自定义元素内部的 DOM 子节点会被分配到对应插槽。
html<!-- 使用 --> <my-card> <span slot="title">卡片标题</span> <p>默认插槽内容</p> </my-card> <!-- 组件 Shadow DOM 中 --> <slot name="title"></slot> <slot></slot>::slotted(selector):为投影到插槽中的内容节点施加有限样式(仅能影响直接子节点,不能穿透更深层级)。
-
声明式 Shadow DOM:
- 通过服务器端 HTML 直接写出 Shadow DOM,无需 JS 即可封装。
- 非常适合 SSR/静态站点,避免 FOUC(样式闪烁),因为封装在 HTML 到达时已完成。
html<my-element> <template shadowrootmode="open"> <style>p { color: red; }</style> <slot></slot> </template> <p>这是内容</p> </my-element>注意:客户端
customElements.define仍需定义同名的 Custom Element 类(可为空),否则元素表现为普通HTMLElement,但 Shadow 封装依然生效。 -
ElementInternals:
- 使自定义元素能参与表单:被
<form>关联、提供值、触发校验和状态(:valid/:invalid)。 - 关键方法:
attachInternals()(构造函数中调用);setFormValue(value)设置表单提交值;setValidity(flags, message)设置校验状态和自定义错误消息;reportValidity()触发浏览器原生校验 UI。
jsclass MyInput extends HTMLElement { static formAssociated = true; // 关键:声明为表单关联元素 constructor() { super(); this.internals = this.attachInternals(); } setValue(v) { this.internals.setFormValue(v); this.internals.setValidity(v ? {} : { valueMissing: true }, '必填'); } } - 使自定义元素能参与表单:被
八、基础 API 与全局属性
8.1 data-* 与 dataset
- 作用 :在元素上存储自定义数据,JS 使用
element.dataset.propName读写(驼峰命名:data-user-id→dataset.userId)。 - 使用场景:传递配置给 JS 组件,避免额外查询或映射。
- 注意 :
dataset中所有值都是字符串;HTML 属性名大小写不敏感,横线分隔转驼峰时遵循规则(data-my-test→dataset.myTest)。频繁读写的性能开销极小,但在视觉上不可见的数据推荐用 JS 变量维护,避免 DOM 污染。
8.2 contenteditable
- 作用:使元素变为可编辑区域,常用于富文本编辑器。
- 属性值 :
true/false/plaintext-only(仅允许纯文本,自动将粘贴的富文本转为纯文本,大多数现代浏览器支持)。 - 注意 :生成的内容结构不可控(用户可插入任意 HTML),需配合
document.execCommand(已废弃)或现代 Selection/Range API 进行控制;安全性需谨慎,输出时应消毒(sanitize)。
8.3 inputmode 与 enterkeyhint
-
inputmode:提示移动设备应显示何种虚拟键盘。- 常用值:
text、numeric(数字键盘但允许符号)、decimal(数字键盘含小数点)、tel(电话键盘)、email、url、search(搜索按钮)。
- 常用值:
-
enterkeyhint:定义虚拟键盘回车键的显示文本/图标(enter、done、go、next、previous、search、send)。html<input type="text" inputmode="numeric" enterkeyhint="done"> -
注意 :
inputmode仅影响键盘类型,不强制输入格式------需配合pattern属性或 JS 校验才能约束输入内容。
8.4 <base>
-
作用 :设置文档中所有相对 URL 的基准路径,以及默认
<a>的target。 -
用法 :
html<base href="https://cdn.example.com/" target="_blank">之后
<img src="img/logo.png">实际指向https://cdn.example.com/img/logo.png。 -
注意 :一个文档仅一个
<base>,需放在<head>中且在所有相对 URL 的标签之前。会影响页内锚点(#section将被解析为相对于基准 URL),可能导致<a href="#section">失效,需要使用绝对路径或 JS 处理。
8.5 PWA 清单(Manifest)
-
作用 :提供 Web 应用元数据(名称、图标、主题色、启动样式、显示模式等),实现"添加到主屏幕"和类似原生应用的体验。
html<link rel="manifest" href="/manifest.json">示例
manifest.json:json{ "name": "应用名称", "short_name": "短名", "start_url": "/", "display": "standalone", "icons": [{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }], "theme_color": "#ffffff", "background_color": "#ffffff" } -
注意 :
display: "standalone"隐藏浏览器 UI,应用作为独立窗口运行;iOS Safari 对部分 manifest 字段支持滞后(如图标仍依赖<link rel="apple-touch-icon">),需单独处理。
8.6 hidden 属性
- 作用 :与
display: none效果类似,隐藏元素及其子元素,且元素不再参与布局和辅助技术树。是一个布尔属性,支持hidden或hidden="hidden"。 - 注意 :
hidden的优先级低于 CSS 显式设置display(如display: flex !important会覆盖hidden)。现代标准新增hidden="until-found":页面搜索(Ctrl+F)命中隐藏内容时可自动显示,之后可通过beforematch事件或 CSS:hidden伪类检测。
九、浏览器解析与渲染原理
9.1 预加载扫描器(Preload Scanner)
- 作用:浏览器在 HTML 解析器被同步脚本阻塞时,利用辅助扫描器提前"偷看"后续的 HTML,寻找可提前下载的子资源(图片、样式、脚本等),发起预请求。
- 架构启示 :
<img>的src放在<head>中不会被预加载扫描器发现(因为它不渲染),但在<body>中即使被<script>阻塞,扫描器也会发起图片请求。因此关键资源的 URL 应尽早暴露给扫描器(如使用<link rel="preload">帮助其发现隐藏资源,如 CSS 中引用的字体)。
9.2 渲染阻塞
- CSS 阻塞渲染 :浏览器必须构建完 CSSOM 才进行布局和绘制。因此所有
<link rel="stylesheet">(无论是否media匹配)和<style>都会阻塞渲染。media属性仅当不匹配 时不会阻塞(如media="print")。 - JS 阻塞解析 :无
async/defer的<script>会阻塞 HTML 解析,因为它可能使用document.write修改文档内容。 - 优化策略 :关键 CSS 内联(
<style>),非关键 CSS 使用media="print" onload="this.media='all'"异步加载;JS 使用defer/async避免阻塞。
9.3 DOM 和 CSSOM 构建顺序
- 解析 HTML 构建 DOM(边下载边解析,非一次性)。
- 遇到 CSS,构建 CSSOM(CSS Object Model),无法增量渲染------必须等整个 CSSOM 就绪(CSS 规则可能互相覆盖)。
- DOM + CSSOM → Render Tree → Layout → Paint → Composite。
- 同步
<script>会阻塞 DOM 构建,同时如果前面有尚未加载完的 CSS,脚本执行也会被阻塞(因为脚本可能查询样式,浏览器需确保 CSSOM 就绪),这意味着CSS 间接阻塞了后续 JS 的执行。
9.4 defer 与 async 对执行时机的影响
defer:在DOMContentLoaded事件之前、HTML 解析完成后按顺序执行。适合依赖完整 DOM 且彼此有顺序依赖的脚本。async:完全独立,下载完立即执行,可能在DOMContentLoaded前或后。适合统计、广告等无关 DOM 的独立脚本。type="module":默认defer,使用async可覆盖;内联模块脚本也默认defer(旧版浏览器不支持)。- 事件触发顺序 :
- 所有
defer脚本执行完毕 →DOMContentLoaded - 同步脚本 → 解析继续 →
DOMContentLoaded(若同步脚本在<body>末尾,DOM 树基本完整) async脚本可能与DOMContentLoaded没有确定先后关系
- 所有
9.5 回流(Reflow)与重绘(Repaint)
- 回流 :布局变更导致几何属性重新计算(改变宽高、添加/删除 DOM、更改
display等)。 - 重绘 :仅外观改变(颜色、背景色、
visibility等)不涉及布局。 - 强制同步布局 :JS 中读取布局属性(如
offsetHeight、getBoundingClientRect())并立即修改样式会触发回流,即典型的"强制回流"陷阱。应在读取前做批量写操作,或使用requestAnimationFrame分离读写。
掌握这些深入知识,架构师能够从 HTML 层面规划出健壮、高性能、高可访问性、且安全的前端架构。这份笔记可作为日常开发与方案评审的参考。