前言
本文整理了小编学习的一些(其实是大量)的面试题,这里主要是HTML方面的面试题,会对每一个面试题进行详尽的讲解,如果有什么没有提到的HTML方面的常考面试题,欢迎大家补充,共同进步!

一、src 和 href 的区别
点开你的项目中的一个HTML文档,你很可能发现下面的两段代码
<link href="styles.css" rel="stylesheet">
<script src="app.js"></script>
两段代码分别是对外部css和js资源的引用,但是引用的方式却不相同
一个引用时使用href,而另一个则是使用src,那么这是为何呢,明明都是加载外部文件不是吗?
带着这个疑问,我们开启下面的讲解——src与href的区别...
1.下面的这句话是我们讲解的基础
最核心区别:
src
直接嵌入并替换当前元素内容(如JS执行、图片显示),而 href
建立与外部资源的关联关系(如CSS应用、链接跳转)。
本质差异:
src
是 "把资源拿过来用" ,href
是 "告诉浏览器这个资源和我有关" 。
我们提取关键词,src是‘嵌入’,href是‘关联’
2.那么何为嵌入?何为关联?
看下面的例子
<img src="http://gips3.baidu.com/it/u=1022347589,1106887837&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280" alt="" width="100px" height="100px">
<a href="http://gips3.baidu.com/it/u=1022347589,1106887837&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280">点击下载图片</a>

这里的图片直接显示在页面上,这就是‘嵌入’
这里的一个超链接,不会将图片直接显示在页面上,这就叫‘关联’
这里只是举个例子方便大家理解,实际上‘嵌入’和‘关联’不只是展示和不展示的关系,还有更深层的关系
我们再次回到在文章开篇给大家的例子,css和js的引用
3.为什么css就是关联,而js就得嵌入?
我们来研究一下css,css只是修饰 HTML,不改变文档结构,只影响渲染样式。
而js呢,动态修改 DOM、执行逻辑,可能改变文档结构或行为。
一个不会影响HTML的文档结构,而另一个会影响,这就是为什么css是关联,而js是嵌入,不嵌入如何影响文档结构呢?不影响文档结构为什么要嵌入呢
4.性能上的区别
当然上述只是较为浅显的讲解了src和href的直观的区别,其实src与href还有诸如性能上的区别
下面我们基于下面的表来讲解
对比项 |
src |
href |
加载方式 |
同步加载(默认阻塞渲染) |
异步加载(不阻塞 DOM 解析) |
执行/渲染 |
立即生效(如执行 JS、显示图片) |
按需生效(如点击链接、应用 CSS) |
缓存策略 |
强缓存优先(如 Cache-Control ) |
协商缓存优先(如 ETag ) |
错误影响 |
可能导致元素失效(如图片裂图) |
通常降级处理(如 CSS 加载失败) |
(1)加载方式的区别
src 的加载特点
src
属性用于嵌入式资源,浏览器会同步加载这些资源。这意味着:
<script src="app.js"></script>
<img src="photo.jpg">
当浏览器解析到这些标签时:
- 暂停 HTML 解析
-
立即下载
app.js
或 photo.jpg
-
执行/渲染资源内容
- 完成后才继续解析后续 HTML
这种同步加载机制可能导致页面渲染延迟(特别是当脚本很大时)。
href 的加载特点
href
属性用于关联性资源,浏览器会异步加载这些资源:
<link href="styles.css" rel="stylesheet">
<a href="about.html">关于我们</a>
加载过程:
-
继续解析 HTML(不阻塞)
-
后台并行下载
styles.css
-
按需应用(CSS 下载完成后才渲染样式)
例外情况:CSS 会阻塞渲染(避免"无样式内容闪烁"),但仍异步加载。
(2)执行/渲染时机的区别
src 资源的执行
src
资源的生效是立即且强制性的:
<!-- 图片会立即加载并显示 -->
<img src="banner.jpg" alt="广告横幅">
<!-- JS 会立即下载并执行 -->
<script src="analytics.js"></script>
如果资源加载失败:
href 资源的应用
href
资源的生效是按需或延迟的:
<!-- CSS 下载完成后才会应用样式 -->
<link href="theme.css" rel="stylesheet">
<!-- 只有点击链接才会加载页面 -->
<a href="contact.html">联系我们</a>
如果资源加载失败:
- CSS 会降级使用浏览器默认样式
- 链接点击会跳转到错误页面
(33)缓存策略的区别
src 资源的缓存
浏览器对 src
资源倾向于使用强缓存:
<!-- 图片可能被长期缓存 -->
<img src="logo.png" alt="公司标志">
缓存表现:
- 优先使用
Cache-Control: max-age
- 适合不变资源(如图片、静态JS)
href 资源的缓存
href
资源更多使用协商缓存:
<!-- CSS 经常使用ETag验证 -->
<link href="styles.css" rel="stylesheet">
缓存表现:
- 优先使用
ETag
/Last-Modified
- 适合频繁更新的资源(如CSS)
(4)错误处理的区别
src 资源错误
加载失败会直接影响功能:
<!-- 图片加载失败会显示alt文本 -->
<img src="missing.jpg" alt="图片缺失提示">
<!-- JS加载失败会中断后续脚本 -->
<script src="missing.js"></script>
href 资源错误
加载失败通常有优雅降级:
<!-- CSS加载失败会使用浏览器默认样式 -->
<link href="missing.css" rel="stylesheet">
<!-- 链接失效会显示404页面 -->
<a href="deleted.html">已删除的页面</a>
二、对HTML语义化标签的理解
对于这个问题,确实是面试官经常问到的,而且回答比较固定,就按照下面的解读顺序来解答
1. 定义语义化标签
"语义化标签是指HTML中那些具有明确含义和用途的标签,它们不仅能告诉浏览器如何显示内容,更重要的是能清晰地表达内容的含义和结构。"
2. 语义化标签的优势
"使用语义化标签主要有以下几个好处:
-
更好的可读性:代码更易于理解和维护
-
更佳的SEO:搜索引擎能更好地理解页面内容
-
更强的可访问性:辅助技术(如屏幕阅读器)能更准确地解读页面
-
更清晰的文档结构:使页面层次更加分明"
3. 常见语义化标签举例
"HTML5引入了一些重要的语义化标签,比如:
-
<header>
表示页眉或内容区块的头部
-
<nav>
定义导航链接
-
<main>
表示文档的主要内容
-
<article>
表示独立的内容区块
-
<section>
定义文档中的节或段
-
<aside>
表示与周围内容相关但不直接相关的内容
-
<footer>
表示页脚或内容区块的底部"
4. 与传统div布局的对比
"相比传统的div+class命名方式,语义化标签:
- 使HTML结构更直观
- 减少了不必要的class命名
- 提供了更丰富的文档结构信息"
5. 实际应用建议
"在实际开发中,我通常会:
- 优先使用合适的语义化标签
- 只在没有合适语义标签时使用div
- 结合ARIA属性进一步增强可访问性
- 确保标签的嵌套关系合理"
如果面试官表现出兴趣,可以进一步深入展示自己的知识面:

(1)历史背景
"在HTML5之前,开发者主要依赖div和span配合class来构建页面,这导致了所谓的'div汤'问题。HTML5引入语义化标签正是为了解决这个问题。"
(2)技术细节
"语义化标签不仅影响文档结构,还与DOM API和CSS选择器有很好的配合。例如,我们可以直接使用document.querySelector('main')
来获取主要内容区域。"
(3)性能考量
"虽然语义化标签本身对性能影响不大,但它们可以带来更好的代码组织和维护性,间接影响开发效率和长期项目性能。"
(4)实际案例
"在我之前参与的项目中,我们通过重构使用语义化标签,使得页面在搜索引擎中的排名提升了约15%,同时屏幕阅读器用户的满意度也有显著提高。"
三、<script>
标签中的Async 与Defer 的区别
script 标签的 defer 和 async 属性,是为解决传统脚本加载阻塞 HTML 解析的问题而生。传统方式中,脚本加载执行会暂停 HTML 解析,易致白屏或 DOM 操作错误。 defer 让脚本并行加载,等 HTML 解析完按顺序执行,适合需操作 DOM 或有依赖的脚本;async 使脚本并行加载,完成后立即执行,顺序不定,适合独立脚本。二者提升了加载效率,优化了用户体验。
HTML 中,<script>
标签的defer
和async
属性都用于控制脚本的加载和执行时机,但它们有以下区别:
-
加载方式:
-
defer
:脚本会与 HTML 并行加载,但会等到 HTML 解析完成后(DOMContentLoaded 事件触发前)才执行。
-
async
:脚本会与 HTML 并行加载,加载完成后立即执行,可能会打断 HTML 的解析。
-
执行顺序:
-
defer
:多个带defer
的脚本会按照它们在 HTML 中出现的顺序执行。
-
async
:多个带async
的脚本执行顺序不确定,先加载完成的先执行。
-
适用场景:
下面是一个简单的示例,展示它们的区别:
<!DOCTYPE html>
<html>
<head>
<!-- 1. 正常脚本:立即加载并执行,阻塞HTML解析 -->
<script src="script1.js"></script>
<!-- 2. defer脚本:并行加载,按顺序执行,HTML解析完成后 -->
<script defer src="script2.js"></script>
<!-- 3. async脚本:并行加载,加载完成立即执行,顺序不确定 -->
<script async src="script3.js"></script>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
执行流程大致为:
script1.js 会阻塞 HTML 解析
script2.js 和 script3.js 会并行加载
script3.js 可能在 HTML 解析完成前执行(如果加载快)
script2.js 会在 HTML 解析完成后,按顺序执行(无论何时加载完成)

四、谈谈web worker
给大家推荐一篇关于web worker的文章www.ruanyifeng.com/blog/2018/0…
Web Worker 是 HTML5 引入的一项浏览器 API,它允许 JavaScript 在后台线程中运行复杂计算,避免阻塞主线程(UI 渲染线程),从而显著提升页面响应速度和用户体验。
我们通过一个最简单的Web Worker案例,去体验一下Web Worker是如何运行的
下面是一个最简单的 Web Worker 示例,包括主脚本和 worker 脚本两部分。
主脚本 (main.js)
首先,在你的 HTML 文件中引入主脚本:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Web Worker Demo</title>
</head>
<body>
<h1>Web Worker Example</h1>
<script src="main.js"></script>
</body>
</html>
然后,创建 main.js
文件,并添加以下代码:
// 这段代码首先检查当前浏览器是否支持 Web Workers。`Worker` 是创建 Web Worker 的构造函数。
// 如果浏览器不支持 Web Workers,则会显示一条消息给用户。
if (typeof(Worker) !== "undefined") {
//通过 `new Worker("worker.js")` 创建一个新的 Web Worker 实例,
//这里 `"worker.js"` 是指向 Worker 脚本的路径。
//这意味着将要运行的后台脚本位于名为 `worker.js` 的文件中。
var worker = new Worker("worker.js");
// 当接收到消息时触发
worker.onmessage = function(event) {
console.log("从 Worker 接收到的消息: " + event.data);
};
// 向 Worker 发送消息
worker.postMessage("Hello Worker!");
} else {
console.log("抱歉,你的浏览器不支持 Web Workers...");
}
Worker 脚本 (worker.js)
接着,创建一个名为 worker.js
的文件,并添加以下代码:
// 当接收到消息时触发
onmessage = function(event) {
console.log("从主线程接收到的消息: " + event.data);
// 处理完数据后,发送消息回主线程
postMessage("你好,主线程!已收到你的消息: " + event.data);
};
具体的代码解释,我以注释的方式放在了代码之中,值得注意的一点是接收消息是onmessage
、发送消息是postMessage
这是内置的函数,不要随意修改
上述的代码就完成了worker.js中的内容会在独立的线程中运行,不会影响主线程,而且可以和主线程进行通讯
当然,我们也可以和面试官聊一聊web worker的缺点
-
性能开销:创建新线程需要额外资源,初始化成本较高,对于轻量级任务反而可能降低效率。
-
通信瓶颈:线程间数据传递需通过序列化 / 反序列化(深拷贝)实现,频繁通信会导致显著延迟。
-
功能受限:无法直接操作 DOM 或访问主线程的
window
、document
对象,应用场景受限。
-
调试复杂:多线程环境下的调试难度较大,错误堆栈追踪和问题定位更具挑战性。
-
内存管理:Worker 线程不会自动销毁,需手动调用
terminate()
,否则可能导致内存泄漏。
如果想深入了解web worker在项目中的使用,可以看我之前的一篇文章从零带你解构GitHub爆火项目——前端实现类谷歌翻译功能<( ̄︶ ̄)↗[GO!]

五、HTML5的离线储存如何使用?
再推荐一篇文章 HTML5-离线缓存(Application Cache)
这个已经被弃用了,不知道会不会有面试官问
六、iframe 的优缺点
<iframe>
是 HTML 中用于在当前页面嵌入另一个网页的标签,它创建了一个独立的浏览上下文(browsing context),允许在父页面中显示外部资源。
该标签有广泛的应用场景
下面讲解三个<iframe>
最主要的特点
1. 内容隔离性
iframe 创建了一个独立的浏览上下文,内部的 DOM、CSS 和 JavaScript 与父页面完全隔离,避免样式冲突和脚本干扰。
<iframe src="https://third-party.com/widget"></iframe>
无论第三方内容如何渲染,都不会影响父页面的布局或功能。
2. 跨域加载能力
iframe 可直接加载不同域名的资源,突破同源策略限制(需目标网站允许)。
<iframe src="https://maps.google.com/maps"></iframe> <!-- 加载Google地图 -->
无需复杂的 CORS 配置,即可嵌入第三方服务。
3. 独立生命周期
iframe 内的页面有自己的加载和渲染流程,不依赖父页面。
父页面加载完成后,iframe 仍可异步加载内容:
<body>
<iframe src="heavy-content.html"></iframe> <!-- 不阻塞父页面渲染 -->
</body>
iframe 的优点
1.iframe 的核心优势在于内容隔离和跨域集成。 通过创建独立的浏览上下文,它能将第三方内容(如地图、广告)与主页面完全隔离,避免样式冲突和脚本干扰。
例如,嵌入 Google 地图只需一行代码:<iframe src="https://maps.google.com"></iframe>
,无需复杂的 API 对接。
2.此外,iframe 支持加载不同域名的资源,突破同源策略限制,适合快速整合外部服务。其独立的生命周期也允许异步加载内容,不阻塞主页面渲染,提升用户体验。
iframe 的缺点
1.iframe 的主要代价在于性能开销和开发复杂性。 每个 iframe 都需独立加载资源并占用额外内存,多层嵌套会导致加载速度显著下降。
2.与主页面通信需通过 postMessage
,且需严格验证消息来源以防止 XSS 攻击。
3.响应式设计也颇具挑战,需手动计算高度或依赖 JavaScript 动态调整。
此外,搜索引擎通常不会索引 iframe 内容,影响 SEO。安全方面,若未正确配置 sandbox
属性,嵌入不可信来源可能引入安全风险。
因此,现代前端更倾向于使用组件化框架(如 React/Vue)替代 iframe 实现内部功能复用。
七、你认为label标签如何使用?
<label>
标签在 HTML 中用于为表单元素(如 input
、select
、textarea
)创建关联文本,主要作用是增强表单的可访问性和用户体验。
一、基础用法:显式关联
通过 for
属性与表单元素的 id
绑定,点击标签时会聚焦到对应元素。
<label for="username">用户名:</label>
<input type="text" id="username" name="username">
二、隐式关联:嵌套表单元素
将表单元素直接放在 <label>
内,无需 for
和 id
。
<label>
记住我
<input type="checkbox" name="remember">
</label>
三、增强交互体验
-
扩大点击区域:用户点击标签文本时,也能触发表单元素。
<label for="subscribe">
<input type="checkbox" id="subscribe">
订阅 newsletter
</label>
-
提升无障碍性:屏幕阅读器会朗读标签文本,帮助视力障碍用户理解表单用途。
其实面试官最想听到的就是第三点,增强交互体验,这是label区别于div,span等标签的重要一点

八、Canvas和SVG的区别
Canvas 和 SVG 都是 HTML5 中用于绘制图形的技术,但核心逻辑和适用场景差异很大。
Canvas 是基于像素的位图绘制技术,通过 JavaScript 动态操作像素,优势在于处理高频更新的动态场景,比如游戏动画、实时数据可视化(像股票 K 线的实时刷新),因为它直接操作像素,绘制大量元素时性能更优;但缺点是放大后可能模糊,且需要手动计算点击区域来实现交互。
SVG 则是基于 XML 的矢量图形,用标签描述图形的几何信息,优势是缩放时不会失真,适合静态或交互简单的场景,比如图标、流程图、地图(像点击某个区域高亮),而且原生支持 DOM 事件,交互实现更简单;但如果图形复杂(比如包含上万节点),会因为 DOM 节点过多影响性能。
实际开发中会根据场景选择:需要高性能动态效果选 Canvas,需要无损缩放或简单交互选 SVG,有时也会结合使用,比如用 Canvas 做底层渲染、SVG 做上层交互层。
九、介绍一下img的srcset属性
img
标签的srcset
属性主要用于解决不同设备(如手机、平板、桌面端)在屏幕尺寸、分辨率上的差异,实现图片的自适应加载,提升页面性能和用户体验。
它的核心作用是让浏览器根据当前设备的条件(比如屏幕宽度、像素密度),从开发者提供的多个图片版本中自动选择最合适的一张加载。使用时需要指定多个图片资源及其对应的适配条件,格式是 “图片路径 + 空格 + 条件描述”,多个资源用逗号分隔。
下面举一个例子方便大家理解
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>srcset 属性示例</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.image-container {
margin: 20px 0;
text-align: center;
}
img {
max-width: 100%;
height: auto;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.info {
margin-top: 10px;
color: #666;
font-size: 14px;
}
</style>
</head>
<body>
<h1>img srcset 属性示例</h1>
<div class="image-container">
<!-- srcset + sizes 组合使用 -->
<img
src="https://picsum.photos/800/400" <!-- 兼容不支持srcset的浏览器 -->
srcset="
https://picsum.photos/400/200 400w,
https://picsum.photos/800/400 800w,
https://picsum.photos/1200/600 1200w,
https://picsum.photos/1600/800 1600w
"
sizes="
(max-width: 600px) 100vw, <!-- 屏幕宽度≤600px时,图片宽度为视口宽度 -->
(max-width: 1000px) 50vw, <!-- 屏幕宽度≤1000px时,图片宽度为视口宽度的50% -->
800px <!-- 其他情况,图片宽度为800px -->
"
alt="风景图示例"
>
<div class="info">
此图片会根据设备屏幕尺寸和像素密度自动选择最合适的版本加载。
<br>
当前加载的是:<span id="loadedImage"></span>
</div>
</div>
<script>
// 显示当前加载的图片信息(仅用于演示)
document.addEventListener('DOMContentLoaded', () => {
const img = document.querySelector('img');
const info = document.getElementById('loadedImage');
// 图片加载完成后
img.onload = () => {
info.textContent = `${img.naturalWidth}×${img.naturalHeight}px`;
};
// 窗口大小变化时重新检查
window.addEventListener('resize', () => {
setTimeout(() => {
info.textContent = `${img.naturalWidth}×${img.naturalHeight}px`;
}, 300);
});
});
</script>
</body>
</html>
这个属性的优势在于避免了 “一刀切” 加载同一张图(比如在小屏幕加载过大图片浪费带宽,或在高清屏加载低清图导致模糊),既优化了加载速度,又保证了显示效果。

十、介绍一下HTML5 drag API
HTML5 Drag and Drop API 提供了一套原生的拖放功能,允许用户在网页中拖动元素并将其放置到指定区域。
先给大家一个例子,大家可以先玩一玩
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f5f7fa;
padding: 20px;
}
.board {
display: flex;
gap: 15px;
margin-top: 20px;
}
.column {
background-color: #ebecf0;
border-radius: 8px;
padding: 12px;
width: 250px;
min-height: 400px;
}
.column-title {
font-weight: bold;
padding: 8px;
margin-bottom: 10px;
color: #172b4d;
}
.task {
background-color: white;
border-radius: 6px;
padding: 12px;
margin-bottom: 10px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
cursor: grab;
transition: transform 0.1s, box-shadow 0.2s;
}
.task:active {
cursor: grabbing;
}
.task.dragging {
opacity: 0.5;
transform: scale(1.02);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
.column.drop-zone {
background-color: #e1e4e8;
}
</style>
</head>
<body>
<h2>任务看板</h2>
<div class="board">
<div class="column" id="todo">
<div class="column-title">待处理</div>
<div class="task" draggable="true" data-task-id="1">设计登录页面</div>
<div class="task" draggable="true" data-task-id="2">编写API文档</div>
</div>
<div class="column" id="progress">
<div class="column-title">进行中</div>
<div class="task" draggable="true" data-task-id="3">用户注册功能开发</div>
</div>
<div class="column" id="done">
<div class="column-title">已完成</div>
<div class="task" draggable="true" data-task-id="4">首页UI设计</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// 获取所有可拖动任务和列
const tasks = document.querySelectorAll('.task');
const columns = document.querySelectorAll('.column');
// 当前被拖动的任务
let draggedTask = null;
// 为每个任务添加拖动事件
tasks.forEach(task => {
task.addEventListener('dragstart', () => {
draggedTask = task;
setTimeout(() => {
task.classList.add('dragging');
}, 0);
});
task.addEventListener('dragend', () => {
task.classList.remove('dragging');
});
});
// 为每个列添加放置事件
columns.forEach(column => {
column.addEventListener('dragover', e => {
e.preventDefault();
column.classList.add('drop-zone');
});
column.addEventListener('dragleave', () => {
column.classList.remove('drop-zone');
});
column.addEventListener('drop', e => {
e.preventDefault();
column.classList.remove('drop-zone');
// 如果目标列中有其他任务,可以插入到特定位置
// 这里简单追加到列末尾
if (draggedTask) {
column.appendChild(draggedTask);
// 在实际应用中,这里可以发送AJAX请求更新服务器状态
console.log(`任务 ${draggedTask.dataset.taskId} 移动到 ${column.id} 列`);
}
});
});
});
</script>
</body>
</html>

下面给大家简单的讲解一下这些API的使用
1. 让元素可以拖动
首先,告诉浏览器哪些东西能拖动:
<div draggable="true">把我拖走</div>
加上 draggable="true"
这个元素就能被拖动了
2. 设置拖放区域
然后,指定哪些地方能接收被拖动的元素:
<div id="drop-area">拖到这里放下</div>
3. 添加4个关键事件
(1) 拖动开始时(dragstart)
document.querySelector('[draggable]').addEventListener('dragstart', function(e) {
e.dataTransfer.setData('text/plain', '随便带点数据'); // 像快递一样带上数据
this.style.opacity = '0.5'; // 拖动时变半透明
});
(2) 拖到目标上方时(dragover)
document.getElementById('drop-area').addEventListener('dragover', function(e) {
e.preventDefault(); // 必须写这句才能放下
this.style.background = 'lightblue'; // 高亮显示
});
(3) 离开目标区域时(dragleave)
document.getElementById('drop-area').addEventListener('dragleave', function() {
this.style.background = ''; // 取消高亮
});
(4) 放下时(drop)
document.getElementById('drop-area').addEventListener('drop', function(e) {
e.preventDefault();
const data = e.dataTransfer.getData('text/plain'); // 取出之前带的数据
this.innerHTML = `收到了:${data}`; // 显示收到的内容
this.style.background = ''; // 取消高亮
});
十一、<!Doctype html>
有何作用?
<!DOCTYPE html>
是 HTML5 文档的文档类型声明(Document Type Declaration),它是 HTML 文档的第一行代码,用于告诉浏览器当前文档使用的是 HTML5 标准。
面试过程中,你可能会遇到如下的问题
1. 基本作用
-
声明文档类型:明确告诉浏览器这是一个 HTML5 文档,使用最新的 HTML 规范解析。
-
触发标准模式(Standards Mode):确保浏览器按照现代 Web 标准渲染页面,避免旧浏览器的兼容性问题。
2. 为什么必须放在第一行?
-
避免浏览器进入混杂模式(Quirks Mode):
如果 <!DOCTYPE html>
缺失或不在文档开头,浏览器可能会以“混杂模式”渲染页面,导致样式和布局表现异常(如盒模型计算错误)。
-
确保文档解析正确:
HTML 解析器需要先读取 DOCTYPE
来决定如何解析后续内容。
4. 对浏览器渲染模式的影响
-
标准模式(Standards Mode):
- 启用条件:存在正确的
<!DOCTYPE html>
。
- 特性:严格遵循 W3C 标准,正确解析 CSS 和 JavaScript。
- 示例:
width: 100px
仅包含内容宽度(不包含 padding
和 border
)。
-
混杂模式|怪异模式(Quirks Mode):
- 启用条件:缺失或错误的 DOCTYPE。
- 特性:模拟旧浏览器(如 IE5)的渲染行为,可能导致布局错乱。
- 示例:
width: 100px
包含内容 + padding
+ border
(类似 box-sizing: border-box
)。
5. 实际开发中的意义
-
确保跨浏览器一致性:
现代框架(如 React/Vue)的模板默认包含 <!DOCTYPE html>
,避免因浏览器差异导致布局问题。
-
避免兼容性问题:
例如,在混杂模式下:
-
margin
和 padding
的计算可能异常。
- 某些 CSS3 属性(如
flexbox
)可能失效。
-
验证工具依赖:
W3C 验证器等工具需要 DOCTYPE 来判断文档是否符合标准。
6. 如何验证当前模式?
通过 JavaScript 检测:
if (document.compatMode === "CSS1Compat") {
console.log("标准模式");
} else {
console.log("混杂模式");
}
十二、meta viewport 有什么作用,怎么写?
<meta name="viewport">
是移动端网页开发的核心标签,用于控制网页在移动设备上的显示方式和缩放行为。
注意:如果只写 <meta name="viewport">
而不指定 content
属性,该标签将完全无效,浏览器会直接忽略它。
一般的写法如下
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
具体的参数意义如下——
参数 |
值 |
作用 |
示例 |
width |
device-width |
视口宽度=设备宽度 |
width=375 (iPhone6/7/8) |
initial-scale |
数字 |
初始缩放比例 |
1.0 (不缩放) |
minimum-scale |
数字 |
最小缩放比例 |
0.5 (可缩小至50%) |
maximum-scale |
数字 |
最大缩放比例 |
2.0 (可放大至200%) |
user-scalable |
yes/no |
是否允许用户缩放 |
no (禁止缩放) |
十三、浏览器乱码的原因是什么?如何解决?
乱码的主要原因
-
字符编码声明错误或缺失
- 网页未指定编码或指定了错误的编码
- 服务器发送的HTTP头与页面声明的编码不一致
-
文件实际编码与声明编码不匹配
- 文件保存的编码(如UTF-8)与HTML中声明的编码(如GBK)不同
-
浏览器自动检测编码失败
-
字体支持问题
解决方案
1. 正确声明HTML文档编码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> <!-- 推荐使用UTF-8编码 -->
<!-- 或者传统的声明方式 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
2. 确保文件实际编码与声明一致
- 使用代码编辑器(如VS Code)检查并转换文件编码
- 保存文件时选择正确的编码格式(推荐UTF-8)
3. 配置服务器HTTP头
确保服务器发送正确的Content-Type头:
Content-Type: text/html; charset=utf-8
4. 检查字体支持
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
}
十四、介绍一下渐进增强与优雅降级
渐进增强:先保证所有设备能看(基础HTML),再给新设备加特效(CSS/JS)
优雅降级:先做出最酷效果(最新技术),再让旧设备凑合能用
下面举例子让大家了解一下两者的开发流程
1. 渐进增强(Progressive Enhancement)
核心思想:先保证基础功能可用(HTML),再逐步增强(CSS → JS)。
适用场景:内容型网站(博客、新闻站)、对可访问性要求高的项目。
① HTML 基础结构(所有设备都能访问)
<!-- 基础链接 - 即使没有JS也能跳转 -->
<a href="/details.html" class="enhanced-link">查看详情</a>
② 添加 CSS 增强(提升视觉体验)
/* 基础样式(所有浏览器) */
.enhanced-link {
color: blue;
text-decoration: underline;
}
/* 增强样式(支持CSS3的浏览器) */
@supports (display: flex) {
.enhanced-link {
padding: 8px 12px;
background: #f0f0f0;
}
}
③ 用 JavaScript 增强交互(现代浏览器才生效)
// 检测浏览器是否支持JS和Fetch API
if ('fetch' in window) {
const link = document.querySelector('.enhanced-link');
link.addEventListener('click', (e) => {
e.preventDefault(); // 阻止默认跳转
fetch('/api/details').then(...); // AJAX加载内容
});
}
✅ 优点:
- 低端设备(如旧手机、屏幕阅读器)至少能看内容
- 代码更健壮,不容易完全崩溃
2. 优雅降级(Graceful Degradation)
核心思想:先按最新技术开发完整功能,再兼容旧浏览器。
适用场景:Web 应用(如在线工具)、内部系统(可控浏览器环境)。
实现方法
① 默认使用最新技术(如 CSS Grid、AJAX)
<button id="ajax-button">加载数据</button>
<div id="content"></div>
// 默认用Fetch API
document.getElementById('ajax-button').addEventListener('click', () => {
fetch('/api/data').then(response => response.json()).then(updateUI);
});
② 检测兼容性并降级
// 如果不支持Fetch,改用XMLHttpRequest或直接跳转
if (!('fetch' in window)) {
document.getElementById('ajax-button').onclick = () => {
window.location.href = '/legacy-data.html'; // 降级方案
};
}
CSS 降级示例(用 @supports
检测)
/* 现代浏览器:用CSS Grid */
.container {
display: grid;
grid-template-columns: 1fr 1fr;
}
/* 旧浏览器降级为Flexbox */
@supports not (display: grid) {
.container {
display: flex;
flex-wrap: wrap;
}
.container > * {
width: 50%;
}
}
✅ 优点:
- 现代用户获得最佳体验
- 开发效率高(先实现理想效果,再处理兼容)
十五、介绍一下HTML5的新特性
这是一个很宽泛的问题,面试官只是想考察我们对HTML发展的掌握,我认为应该挑其中的重点来回答,比较重要的包括下面的五部分
大部分前文都有介绍,部分没介绍的会放到之后的文章介绍,比如存储API会放在面试浏览器篇介绍
1.语义化标签
<header> <nav> <article> <section> <footer> <aside> <main>
2.媒体支持
- 原生音视频:
<audio>
<video>
(不再依赖Flash)
- 画布绘图:
<canvas>
+ JavaScript API
3.表单增强
- 新输入类型:
email
url
date
range
color
- 属性:
placeholder
required
pattern
autofocus
4.存储API
-
localStorage
/sessionStorage
(替代Cookie)
-
IndexedDB
(结构化数据存储)
5.Web Workers
十六、b与strong的区别
我们可以从以下的几个角度回答
1.视觉表现:
两者默认都显示为加粗文本
2.语义差异:
<b>
:仅表示视觉上的加粗,没有语义含义;<strong>
:表示内容具有重要性或紧急性,带有语义强调
3.使用场景:
用<b>
:当只需要视觉上加粗,不需要特别强调内容重要性时;用<strong>
:当内容确实重要,需要特别强调时(如警告、关键信息)
4.对辅助设备的影响:
屏幕阅读器会以不同语调朗读<strong>
的内容;<b>
对辅助设备没有特殊处理
★★★但是,我们的回答不要止步于此,碰到了自己擅长的领域必须好好的‘秀秀肌肉’

1.<i>
vs <em>
<i>
:仅表示视觉斜体(如图标、术语);<em>
:表示需要强调的文本(语义斜体)
2.<s>
vs <del>
<s>
:仅表示视觉删除线(如促销价);<del>
:表示文档中被删除的内容(有语义)
3.<u>
vs <ins>
<u>
:仅表示视觉下划线;<ins>
:表示文档中新增的内容
结语
HTML 面试题看似基础,但往往藏着不少细节,掌握它们不仅能让你在面试中游刃有余,还能在日常开发中写出更优雅的代码。希望这篇整理能帮你查漏补缺,信心满满地迎接面试挑战!
记住,面试官也是从新手过来的,放轻松,展现你的实力就好!
祝你面试顺利,offer 拿到手软! 如果有其他问题,欢迎在评论区交流~
