语义化与兼容性

Web标准、语义化与兼容性

核心概念(3大维度)

记忆口诀:标准 → 语义 → 兼容

1
2
3
1. Web标准:结构、表现、行为分离
2. 语义化:用正确的标签做正确的事
3. 兼容性:跨浏览器、跨设备一致体验

1. Web标准

1.1 三层分离

结构层(HTML)

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 负责页面结构和内容 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>页面标题</title>
</head>
<body>
<header>头部</header>
<main>主体内容</main>
<footer>底部</footer>
</body>
</html>

表现层(CSS)

1
2
3
4
5
6
7
8
9
10
11
/* 负责页面样式和布局 */
header {
background: #333;
color: white;
padding: 20px;
}

main {
max-width: 1200px;
margin: 0 auto;
}

行为层(JavaScript)

1
2
3
4
// 负责页面交互和逻辑
document.querySelector('button').addEventListener('click', () => {
alert('按钮被点击');
});

1.2 Web标准的优势

开发维护

  • 代码结构清晰,易于维护
  • 团队协作效率高
  • 降低维护成本

性能优化

  • 减少代码冗余
  • 提升加载速度
  • 利于缓存

SEO友好

  • 搜索引擎易于抓取
  • 提升网站排名

可访问性

  • 屏幕阅读器友好
  • 键盘导航支持
  • 无障碍访问

2. HTML语义化

2.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
<!-- ❌ 不语义化 -->
<div class="header">
<div class="nav">
<div class="nav-item">首页</div>
<div class="nav-item">关于</div>
</div>
</div>
<div class="content">
<div class="article">
<div class="title">文章标题</div>
<div class="text">文章内容</div>
</div>
</div>

<!-- ✅ 语义化 -->
<header>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
</nav>
</header>
<main>
<article>
<h1>文章标题</h1>
<p>文章内容</p>
</article>
</main>

2.2 常用语义化标签

页面结构标签

1
2
3
4
5
6
7
<header>    <!-- 页面或区块头部 -->
<nav> <!-- 导航链接 -->
<main> <!-- 主要内容(页面唯一) -->
<article> <!-- 独立的文章内容 -->
<section> <!-- 文档中的节 -->
<aside> <!-- 侧边栏、附加信息 -->
<footer> <!-- 页面或区块底部 -->

内容标签

1
2
3
4
5
6
7
8
9
10
<h1>-<h6>   <!-- 标题,h1最重要 -->
<p> <!-- 段落 -->
<strong> <!-- 重要文本(加粗) -->
<em> <!-- 强调文本(斜体) -->
<mark> <!-- 高亮文本 -->
<time> <!-- 时间日期 -->
<address> <!-- 联系信息 -->
<blockquote><!-- 引用 -->
<code> <!-- 代码 -->
<pre> <!-- 预格式化文本 -->

列表标签

1
2
3
4
5
6
<ul>        <!-- 无序列表 -->
<ol> <!-- 有序列表 -->
<dl> <!-- 定义列表 -->
<dt> <!-- 定义术语 -->
<dd> <!-- 定义描述 -->
</dl>

表单标签

1
2
3
4
5
6
7
8
<form>      <!-- 表单 -->
<label> <!-- 表单标签 -->
<input> <!-- 输入框 -->
<textarea> <!-- 多行文本 -->
<select> <!-- 下拉选择 -->
<button> <!-- 按钮 -->
<fieldset> <!-- 表单分组 -->
<legend> <!-- 分组标题 -->

多媒体标签

1
2
3
4
5
6
7
8
<img>       <!-- 图片 -->
<figure> <!-- 图片容器 -->
<figcaption> <!-- 图片说明 -->
</figure>
<audio> <!-- 音频 -->
<video> <!-- 视频 -->
<canvas> <!-- 画布 -->
<svg> <!-- 矢量图 -->

2.3 语义化实战示例

博客文章页面

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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文章标题 - 我的博客</title>
</head>
<body>
<!-- 页面头部 -->
<header>
<h1>我的博客</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
<li><a href="/contact">联系</a></li>
</ul>
</nav>
</header>

<!-- 主要内容 -->
<main>
<article>
<header>
<h1>前端性能优化实践</h1>
<p>
<time datetime="2026-03-09">2026年3月9日</time>
作者:<address>张三</address>
</p>
</header>

<section>
<h2>引言</h2>
<p>性能优化是前端开发的重要课题...</p>
</section>

<section>
<h2>优化方案</h2>
<p>主要包括以下几个方面:</p>
<ol>
<li>资源压缩</li>
<li>代码分割</li>
<li>缓存策略</li>
</ol>
</section>

<footer>
<p>标签:<a href="/tag/performance">性能优化</a></p>
</footer>
</article>

<!-- 侧边栏 -->
<aside>
<section>
<h3>相关文章</h3>
<ul>
<li><a href="/post1">文章1</a></li>
<li><a href="/post2">文章2</a></li>
</ul>
</section>
</aside>
</main>

<!-- 页面底部 -->
<footer>
<p>&copy; 2026 我的博客. All rights reserved.</p>
</footer>
</body>
</html>

2.4 语义化的好处

1. SEO优化

1
2
3
4
5
<!-- 搜索引擎更容易理解页面结构 -->
<article>
<h1>主标题</h1> <!-- 搜索引擎知道这是最重要的标题 -->
<p>内容...</p>
</article>

2. 可访问性

1
2
3
4
5
6
7
8
<!-- 屏幕阅读器可以正确朗读 -->
<nav aria-label="主导航">
<ul>
<li><a href="/">首页</a></li>
</ul>
</nav>

<img src="logo.png" alt="公司Logo"> <!-- alt提供图片描述 -->

3. 代码可读性

1
2
3
4
5
6
7
8
9
<!-- 开发者一眼就能看懂页面结构 -->
<header>头部</header>
<main>主体</main>
<footer>底部</footer>

<!-- vs -->
<div class="header">头部</div>
<div class="main">主体</div>
<div class="footer">底部</div>

4. 易于维护

1
2
3
<!-- 语义化标签自带样式,减少CSS代码 -->
<strong>重要</strong> <!-- 自动加粗 -->
<em>强调</em> <!-- 自动斜体 -->

3. 浏览器兼容性

3.1 常见兼容性问题

CSS兼容性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 1. 浏览器前缀 */
.box {
-webkit-transform: rotate(45deg); /* Chrome, Safari */
-moz-transform: rotate(45deg); /* Firefox */
-ms-transform: rotate(45deg); /* IE */
-o-transform: rotate(45deg); /* Opera */
transform: rotate(45deg); /* 标准 */
}

/* 2. Flexbox兼容 */
.container {
display: -webkit-box; /* 老版本 */
display: -webkit-flex; /* Chrome */
display: -ms-flexbox; /* IE10 */
display: flex; /* 标准 */
}

/* 3. Grid兼容 */
.grid {
display: -ms-grid; /* IE10-11 */
display: grid; /* 标准 */
}

JavaScript兼容性

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
// 1. ES6+特性兼容
// 箭头函数
const add = (a, b) => a + b;
// 转译为
var add = function(a, b) { return a + b; };

// Promise
new Promise((resolve) => resolve());
// 需要polyfill

// 2. API兼容
// fetch(IE不支持)
if (window.fetch) {
fetch('/api/data');
} else {
// 使用XMLHttpRequest
}

// 3. 事件兼容
// addEventListener(IE8不支持)
if (element.addEventListener) {
element.addEventListener('click', handler);
} else {
element.attachEvent('onclick', handler);
}

3.2 兼容性解决方案

方案1:CSS Reset/Normalize

1
2
3
4
5
6
7
8
9
10
/* CSS Reset - 重置所有样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

/* Normalize.css - 保留有用的默认样式 */
/* 推荐使用 */
@import 'normalize.css';

方案2:Autoprefixer(自动添加前缀)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// PostCSS配置
module.exports = {
plugins: {
autoprefixer: {
browsers: ['last 2 versions', '> 1%', 'ie >= 9']
}
}
};

// 输入
.box {
display: flex;
}

// 输出
.box {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}

方案3:Babel转译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// .babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["last 2 versions", "ie >= 11"]
},
"useBuiltIns": "usage",
"corejs": 3
}]
]
}

// ES6代码
const arr = [1, 2, 3];
const doubled = arr.map(x => x * 2);

// 转译后(IE11)
var arr = [1, 2, 3];
var doubled = arr.map(function(x) { return x * 2; });

方案4:Polyfill(功能补丁)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. core-js(全面的polyfill)
import 'core-js/stable';
import 'regenerator-runtime/runtime';

// 2. 按需引入
import 'core-js/features/promise';
import 'core-js/features/array/includes';

// 3. 条件加载
if (!Array.prototype.includes) {
Array.prototype.includes = function(searchElement) {
return this.indexOf(searchElement) !== -1;
};
}

方案5:特性检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Modernizr - 特性检测库
if (Modernizr.flexbox) {
// 支持Flexbox
} else {
// 使用降级方案
}

// 手动检测
function supportsGrid() {
return CSS.supports('display', 'grid');
}

if (supportsGrid()) {
// 使用Grid布局
} else {
// 使用Flexbox或Float
}

方案6:条件注释(IE专用)

1
2
3
4
5
6
7
8
<!--[if IE]>
<link rel="stylesheet" href="ie.css">
<![endif]-->

<!--[if lt IE 9]>
<script src="html5shiv.js"></script>
<script src="respond.js"></script>
<![endif]-->

3.3 移动端兼容性

视口设置

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

1px边框问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 方案1:transform缩放 */
.border {
position: relative;
}
.border::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #000;
transform: scaleY(0.5);
}

/* 方案2:使用图片 */
.border {
border-bottom: 1px solid transparent;
border-image: url(border.png) 2 repeat;
}

/* 方案3:viewport缩放 */
<meta name="viewport" content="width=device-width, initial-scale=0.5">

点击延迟(300ms)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 方案1:禁用缩放 -->
<meta name="viewport" content="user-scalable=no">

<!-- 方案2:使用FastClick库 -->
<script src="fastclick.js"></script>
<script>
FastClick.attach(document.body);
</script>

<!-- 方案3:CSS touch-action -->
<style>
* {
touch-action: manipulation;
}
</style>

安全区域适配(刘海屏)

1
2
3
4
5
6
7
/* iPhone X适配 */
body {
padding-top: constant(safe-area-inset-top); /* iOS 11.0 */
padding-top: env(safe-area-inset-top); /* iOS 11.2+ */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}

横竖屏适配

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 竖屏 */
@media screen and (orientation: portrait) {
.container {
width: 100%;
}
}

/* 横屏 */
@media screen and (orientation: landscape) {
.container {
width: 50%;
}
}
1
2
3
4
5
6
7
8
// JavaScript检测
window.addEventListener('orientationchange', () => {
if (window.orientation === 90 || window.orientation === -90) {
console.log('横屏');
} else {
console.log('竖屏');
}
});

3.4 响应式设计

媒体查询

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
/* 移动端优先 */
.container {
width: 100%;
}

/* 平板 */
@media (min-width: 768px) {
.container {
width: 750px;
}
}

/* 桌面 */
@media (min-width: 1024px) {
.container {
width: 1000px;
}
}

/* 大屏 */
@media (min-width: 1440px) {
.container {
width: 1200px;
}
}

弹性布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Flexbox */
.container {
display: flex;
flex-wrap: wrap;
}

.item {
flex: 1 1 300px; /* 最小300px,自动伸缩 */
}

/* Grid */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}

相对单位

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
/* rem(相对根元素) */
html {
font-size: 16px;
}

.title {
font-size: 2rem; /* 32px */
}

/* em(相对父元素) */
.parent {
font-size: 16px;
}

.child {
font-size: 1.5em; /* 24px */
}

/* vw/vh(相对视口) */
.hero {
width: 100vw;
height: 100vh;
}

/* %(相对父元素) */
.container {
width: 80%;
}

4. 可访问性(Accessibility)

4.1 ARIA属性

角色(role)

1
2
3
4
<div role="navigation">导航</div>
<div role="main">主内容</div>
<div role="button">按钮</div>
<div role="alert">警告信息</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
<!-- aria-label:提供标签 -->
<button aria-label="关闭">×</button>

<!-- aria-labelledby:引用标签 -->
<h2 id="dialog-title">对话框标题</h2>
<div role="dialog" aria-labelledby="dialog-title">
内容...
</div>

<!-- aria-describedby:提供描述 -->
<input type="text" aria-describedby="username-help">
<span id="username-help">用户名长度3-20个字符</span>

<!-- aria-hidden:隐藏元素 -->
<span aria-hidden="true">装饰性图标</span>

<!-- aria-expanded:展开状态 -->
<button aria-expanded="false">展开菜单</button>

<!-- aria-disabled:禁用状态 -->
<button aria-disabled="true">提交</button>

<!-- aria-live:动态内容 -->
<div aria-live="polite">加载中...</div>

4.2 键盘导航

Tab键导航

1
2
3
4
5
6
7
8
9
10
<!-- tabindex控制焦点顺序 -->
<input type="text" tabindex="1">
<input type="text" tabindex="2">
<button tabindex="3">提交</button>

<!-- tabindex="-1":不参与Tab导航,但可通过JS聚焦 -->
<div tabindex="-1">内容</div>

<!-- tabindex="0":按DOM顺序参与Tab导航 -->
<div tabindex="0">可聚焦的div</div>

键盘事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 支持Enter和Space键触发
button.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
button.click();
}
});

// ESC键关闭对话框
dialog.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeDialog();
}
});

4.3 焦点管理

焦点陷阱(模态框)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function trapFocus(element) {
const focusableElements = element.querySelectorAll(
'a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])'
);

const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];

element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
});
}

焦点恢复

1
2
3
4
5
// 打开模态框前保存焦点
const previousFocus = document.activeElement;

// 关闭模态框后恢复焦点
previousFocus.focus();

5. 面试口述版本

面试官:请说说你对Web标准、语义化和兼容性的理解

回答框架:

“这三个概念是前端开发的基础规范:

1. Web标准(三层分离)

  • 结构层(HTML):负责页面内容和结构
  • 表现层(CSS):负责页面样式和布局
  • 行为层(JavaScript):负责页面交互和逻辑

优势:代码清晰、易维护、性能好、SEO友好

2. HTML语义化

  • 定义:用正确的标签做正确的事情
  • 常用标签:header、nav、main、article、section、aside、footer
  • 好处:
    • SEO优化:搜索引擎更容易理解页面结构
    • 可访问性:屏幕阅读器友好
    • 代码可读性:开发者易于理解
    • 易于维护:结构清晰

3. 浏览器兼容性

  • 问题:不同浏览器对标准支持程度不同
  • 解决方案:
    • CSS:Autoprefixer自动添加前缀、Normalize.css
    • JavaScript:Babel转译、Polyfill补丁
    • 特性检测:Modernizr、CSS.supports
    • 响应式设计:媒体查询、弹性布局、相对单位

4. 移动端兼容

  • 视口设置:viewport meta标签
  • 1px边框:transform缩放
  • 点击延迟:FastClick、touch-action
  • 安全区域:env(safe-area-inset-*)

5. 可访问性

  • ARIA属性:role、aria-label、aria-hidden
  • 键盘导航:tabindex、焦点管理
  • 语义化标签:提升屏幕阅读器体验

实际开发中,我会遵循Web标准,使用语义化标签,通过工具链解决兼容性问题,确保网站在各种环境下都能正常使用。”


6. 高频追问

Q1: 为什么要使用语义化标签?

SEO优化:

  • 搜索引擎通过标签理解页面结构
  • h1标签权重最高,告诉搜索引擎这是最重要的内容
  • article、section等标签帮助搜索引擎识别内容区块

可访问性:

  • 屏幕阅读器根据标签朗读内容
  • nav标签会被识别为导航区域
  • alt属性为视障用户提供图片描述

代码可读性:

  • 开发者一眼就能看懂页面结构
  • 减少注释,代码自解释

易于维护:

  • 结构清晰,修改方便
  • 团队协作效率高

Q2: div和section的区别?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- div:无语义的容器,纯粹用于布局 -->
<div class="wrapper">
<div class="content">内容</div>
</div>

<!-- section:有语义的章节,表示文档中的一个区块 -->
<section>
<h2>章节标题</h2>
<p>章节内容</p>
</section>

<!-- 使用原则 -->
<!-- 如果只是为了样式或布局,用div -->
<!-- 如果是文档的一个独立章节,用section -->

Q3: 如何解决浏览器兼容性问题?

开发阶段:

  1. 使用成熟的框架(React、Vue)
  2. 使用CSS预处理器(Sass、Less)
  3. 配置Autoprefixer自动添加前缀
  4. 使用Babel转译ES6+代码
  5. 引入Polyfill补丁

测试阶段:

  1. 使用BrowserStack等工具测试
  2. 真机测试
  3. 检查Can I Use网站

降级方案:

  1. 特性检测(Modernizr)
  2. 渐进增强:基础功能优先,高级功能可选
  3. 优雅降级:先实现完整功能,再兼容老浏览器

Q4: CSS兼容性常见问题?

1. 浏览器前缀

1
2
3
4
5
.box {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}

2. Flexbox兼容

1
2
3
4
5
/* IE10需要-ms-前缀 */
.container {
display: -ms-flexbox;
display: flex;
}

3. Grid兼容

1
2
3
4
5
/* IE10-11使用旧语法 */
.grid {
display: -ms-grid;
-ms-grid-columns: 1fr 1fr;
}

4. 盒模型

1
2
3
4
/* IE6-7默认是border-box */
* {
box-sizing: border-box;
}

Q5: 移动端1px边框问题如何解决?

原因:

  • 设备像素比(DPR)导致
  • iPhone 6的DPR=2,1px实际显示2个物理像素

解决方案:

方案1:transform缩放(推荐)

1
2
3
4
5
6
7
8
9
10
.border::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #000;
transform: scaleY(0.5);
}

方案2:viewport缩放

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

方案3:使用图片

1
2
3
4
.border {
border-bottom: 1px solid transparent;
border-image: url(border.png) 2 repeat;
}

方案4:使用box-shadow

1
2
3
.border {
box-shadow: 0 1px 0 0 #000;
}

Q6: 如何实现响应式设计?

1. 媒体查询

1
2
3
4
5
6
7
8
9
10
/* 移动端优先 */
.container { width: 100%; }

@media (min-width: 768px) {
.container { width: 750px; }
}

@media (min-width: 1024px) {
.container { width: 1000px; }
}

2. 弹性布局

1
2
3
4
5
6
7
8
9
10
11
/* Flexbox */
.container {
display: flex;
flex-wrap: wrap;
}

/* Grid */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

3. 相对单位

1
2
3
4
5
6
7
8
9
/* rem:相对根元素 */
html { font-size: 16px; }
.title { font-size: 2rem; }

/* vw/vh:相对视口 */
.hero { width: 100vw; height: 100vh; }

/* %:相对父元素 */
.container { width: 80%; }

4. 图片响应式

1
2
3
4
5
6
7
8
9
10
11
<!-- srcset -->
<img src="small.jpg"
srcset="medium.jpg 768w, large.jpg 1024w"
sizes="(max-width: 768px) 100vw, 50vw">

<!-- picture -->
<picture>
<source media="(min-width: 1024px)" srcset="large.jpg">
<source media="(min-width: 768px)" srcset="medium.jpg">
<img src="small.jpg" alt="responsive image">
</picture>

Q7: 什么是渐进增强和优雅降级?

渐进增强(Progressive Enhancement)

1
2
3
4
5
6
7
8
9
基础功能 → 高级功能

1. 先实现基础功能(所有浏览器都支持)
2. 再添加高级功能(现代浏览器支持)
3. 老浏览器能用,新浏览器体验更好

示例:
- 基础:表单提交刷新页面
- 增强:AJAX无刷新提交

优雅降级(Graceful Degradation)

1
2
3
4
5
6
7
8
9
完整功能 → 降级方案

1. 先实现完整功能(现代浏览器)
2. 再为老浏览器提供降级方案
3. 新浏览器体验好,老浏览器能用

示例:
- 完整:CSS Grid布局
- 降级:Flexbox或Float布局

选择建议:

  • 新项目:渐进增强(移动端优先)
  • 老项目:优雅降级(兼容老浏览器)

7. 实战案例

案例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
37
38
39
40
41
42
43
44
45
46
<!-- 重构前 -->
<div class="header">
<div class="logo">Logo</div>
<div class="nav">
<div class="nav-item">首页</div>
<div class="nav-item">关于</div>
</div>
</div>
<div class="content">
<div class="post">
<div class="title">文章标题</div>
<div class="date">2026-03-09</div>
<div class="text">文章内容</div>
</div>
</div>
<div class="footer">
<div class="copyright">版权信息</div>
</div>

<!-- 重构后 -->
<header>
<h1>Logo</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h2>文章标题</h2>
<time datetime="2026-03-09">2026年3月9日</time>
<p>文章内容</p>
</article>
</main>
<footer>
<p>&copy; 2026 版权信息</p>
</footer>

<!-- 改进点 -->
<!-- 1. 使用语义化标签(header、nav、main、article、footer) -->
<!-- 2. 使用h1、h2表示标题层级 -->
<!-- 3. 使用time标签表示时间 -->
<!-- 4. 使用ul、li表示列表 -->
<!-- 5. 使用a标签表示链接 -->

案例2:移动端适配

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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 视口设置 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<style>
/* 1. 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

/* 2. rem适配 */
html {
font-size: calc(100vw / 3.75); /* 375px设计稿 */
}

/* 3. 1px边框 */
.border::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #ddd;
transform: scaleY(0.5);
}

/* 4. 安全区域适配 */
.container {
padding-bottom: env(safe-area-inset-bottom);
}

/* 5. 响应式布局 */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(1rem, 1fr));
gap: 0.2rem;
}
</style>
</head>
<body>
<div class="container">
<div class="grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>
</body>
</html>

案例3:可访问性优化

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
<!-- 优化前 -->
<div class="modal">
<div class="close">×</div>
<div class="title">提示</div>
<div class="content">确认删除吗?</div>
<div class="btn">确定</div>
<div class="btn">取消</div>
</div>

<!-- 优化后 -->
<div role="dialog"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc"
aria-modal="true">

<button aria-label="关闭对话框"
class="close"
tabindex="0">×</button>

<h2 id="dialog-title">提示</h2>

<p id="dialog-desc">确认删除吗?</p>

<button tabindex="0">确定</button>
<button tabindex="0">取消</button>
</div>

<script>
// 焦点管理
const dialog = document.querySelector('[role="dialog"]');
const focusableElements = dialog.querySelectorAll('button');
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];

// 打开时聚焦第一个元素
firstElement.focus();

// 焦点陷阱
dialog.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}

// ESC关闭
if (e.key === 'Escape') {
closeDialog();
}
});
</script>

<!-- 改进点 -->
<!-- 1. 使用role="dialog"标识对话框 -->
<!-- 2. aria-labelledby关联标题 -->
<!-- 3. aria-describedby关联描述 -->
<!-- 4. aria-modal="true"标识模态框 -->
<!-- 5. aria-label为关闭按钮提供描述 -->
<!-- 6. tabindex控制焦点顺序 -->
<!-- 7. 键盘导航支持(Tab、Shift+Tab、ESC) -->
<!-- 8. 焦点陷阱和焦点管理 -->