“你写一个基础 HTML 页面结构吧。”——这句话我在这几年校招面试里说过很多次。大多数同学都能刷刷刷写出<!DOCTYPE html>、<html>、<head>、<body>这套标准模板,但当我紧接着问“第一行为什么要写 DOCTYPE”“lang 属性里的 zh-CN 到底是什么意思”“meta charset 不写会怎么样”时,对面就会陷入沉默。HTML 简单到没人认真复习,但它恰恰是校招面试里最容易被“试水”、也最容易拉开差距的一块。这篇文章我就以面经整理的形式,把那些“你以为你知道,但真问起来会卡壳”的 HTML 考点挨个过一遍,给准备校招的同学一份能直接照着补的清单。
1. 一张HTML模板就是一道综合题:DOCTYPE、lang、charset、viewport 逐行拆
先回到那个最常见的标准模板本身。面试官让写基本页面结构,不是真的要看你会不会写,而是想顺着模板里的每一行往下追问。四行代码,四个考点,谁基本功扎实,几句话就能试探出来。
1.1 第一行DOCTYPE:为什么面试官总从这里开始“设套”
<!DOCTYPE html>这一行在 HTML5 里看起来非常短,短到很多人以为它就是个形式。它不是 HTML 标签,而是文档类型声明,核心作用是告诉浏览器:用标准模式还是怪癖模式来渲染这个页面。
浏览器在解析页面时有两套规则。标准模式下,CSS 布局按照 W3C 规范来,比如width的默认计算就是 content 的宽度;一旦不写 DOCTYPE,浏览器会进入 quirks mode,也就是怪癖模式。这个模式是为了兼容 IE5 时代的老页面而保留的,里面充满了各种“历史遗留行为”,最典型的就是盒模型。在怪癖模式下,width: 100px的div会把padding和border也算进这 100px 里,导致同样一套样式在标准模式和怪癖模式下渲染结果完全不同。
面试官追问到这一层,还会顺便考一个进阶点:除了 standards mode 和 quirks mode,还有一个 almost standards mode。它主要处理表格单元格里图片垂直对齐的老问题,<!DOCTYPE html>在部分老版本浏览器里就会触发这个模式。现在主流浏览器基本已经没有感知上的差异,但能说出这个概念,说明你真的去了解过浏览器渲染机制,而不是只背了模板。
实操建议就一句话:新建页面直接复制标准模板,别手敲。<!doctype html>和<!DOCTYPE html>大小写不敏感都能识别,但漏掉任何一个字符,整个页面就可能掉进怪癖模式,这种问题排查起来特别隐蔽。
1.2 lang 属性:zh-CN、zh-Hans、hreflang 都是什么意思
<html lang="zh-CN">里的lang属性,是给浏览器、搜索引擎、屏幕阅读器看的语言声明,不是给人看的装饰。
面试官经常拿一个词来考人:zh-CN和zh-Hans有什么区别。很多同学会愣住,因为平时根本没人区分。zh-CN是语言加地区,zh 表示中文,CN 表示中国地区;zh-Hans是语言加文字系统,Hans 表示简体中文。一个新加坡的中文页面可能写zh-SG或者更精确地写zh-Hans-SG。这个区别在 HTML 规范里属于 bcp47 语言标签体系,面试能答出这层,是很明显的加分项。
lang的实际影响也很具体:浏览器翻译插件需要靠它判断当前页面是什么语言,要不要弹出翻译提示;屏幕阅读器会根据lang选择合适的发音规则,中英文混排的页面如果标签标错,朗读器会用错误的语言读出来;搜索引擎也会参考lang来识别页面内容语言。
另外还有一个容易混淆的点:hreflang。它写在<link>或<a>标签上,用于告诉搜索引擎当前页面和其他语言版本页面的对应关系,比如<link rel="alternate" hreflang="en" href="/en/">。lang是声明当前页面语言,hreflang是声明链接目标页面的语言,方向完全不同。面试里能主动把这个区分讲清楚,面试官会记住你的。
1.3 meta charset 与 viewport:基础模板里的“连带考点”
<meta charset="utf-8">声明的是文档字符编码。浏览器解析 HTML 时,第一步是解码字节流,而解码用什么字符集就取决于这个声明。如果不写,浏览器会自己猜编码,一旦猜错,页面就是一堆乱码,中文字符会出现经典的“锟斤拷”“烫烫烫”。
这里有个细节值得记住:W3C 建议 charset 声明必须出现在 head 的前 1024 字节内。原因是浏览器解析 HTML 时会边下载边解析,HEAD 区域的字节已经足够用来做编码决策。所以实际项目里的规范就是把 charset 放在 head 的第一行,紧跟其后才是 title 和 viewport。
<meta name="viewport" content="width=device-width, initial-scale=1.0">则是移动端适配的第一道题。老式智能手机浏览器的默认布局视口宽度是 980px,如果不设置 viewport,页面会先在 980px 宽度下布局,再整体缩小到手机屏幕显示。结果就是页面能看,但字小得没法点。width=device-width把布局视口设成设备宽度,initial-scale=1.0确保初始缩放比例是 1:1。
面试官喜欢追问的是:maximum-scale=1和user-scalable=no为什么不推荐?因为这俩属性会禁用用户缩放页面的能力,对视力不好的用户非常不友好,属于可访问性上的坑。而且 iOS 10 开始 Safari 直接忽略这两个属性,写了也没用。如果能顺势把 layout viewport、visual viewport、ideal viewport 这三个概念讲出来,移动端适配这一块基本就过关了。
2. 语义化标签:从背概念到现场手写
语义化是 HTML 面试绝对绕不开的考点。这个知识点问得浅,答案就是“用合适的标签表达合适的内容”;问得深,能一路问到无障碍、SEO、文档大纲。我通常建议应届生从三个维度来组织答案。
2.1 面试官问“语义化是什么”时,他到底想听什么
只回答“语义化就是不要全部用 div”是远远不够的。一个完整的回答应该覆盖三个受益方。
第一是开发者自己。语义化标签让页面结构更清晰,别人接手代码时,不用看 CSS 就能从标签猜出内容性质,比如header是页头、nav是导航、aside是侧边栏。类名可以少写一大半,维护成本明显降下来。
第二是浏览器和搜索引擎。爬虫需要理解页面结构才能正确建立索引。一个文章页面里,<article>包裹正文、<h1>放标题、<time>标记发布时间,这些信息对搜索引擎判断内容质量很有帮助,也是 SEO 的基础。
第三是辅助技术和无障碍用户。屏幕阅读器会朗读标签的语义信息,比如“这是一个按钮”“这是一个导航区域”。用<div>模拟按钮,屏幕阅读器只会告诉用户“这是一个分组”,键盘用户也无法正常操作。反过来说,<button>天然支持 Tab 聚焦、Enter 和 Space 触发、屏幕阅读器朗读,这些能力不需要任何额外代码。
我面过不少同学,能答出这三个维度的人不足三成,大多数人都卡在“为了让搜索引擎看得懂”这一层。如果能主动把“开发者、浏览器、用户”三个视角都覆盖,这道题的分数直接拉满。
2.2 面经里很少提的“加分标签”:address、time、details、dialog
header、footer、nav、main、article、section、aside这七个是基础,大家在简历上都写过。但面试官想判断一个候选人的知识广度,往往喜欢挑一些不那么常用的标签来问。
<address>是表示联系信息的标签,不是给网页底部放公司地址那么简单。它应该包裹具体的联系方式,比如邮箱、电话、物理地址。放在<article>里时,它表示文章作者的联系方式,这是一个很语义化的细节。
<time>配合datetime属性可以让时间变得机器可读。<time datetime="2026-06-01T10:00:00+08:00">2026年6月1日</time>这种写法,搜索引擎能直接提取事件时间,格式可以精确到秒甚至带时区。
<details>和<summary>是原生折叠面板,不需要任何 JS。<details open>控制默认展开状态,它还会触发toggle事件。面试官问“原生折叠和 div+JS 实现的折叠有什么区别”时,核心答案是:原生实现自带键盘操作和可访问性支持,浏览器还能记住展开状态,交互成本几乎为零。
<dialog>是原生弹窗,支持showModal()方法,配合::backdrop可以做遮罩层。它天然支持Esc关闭、焦点锁定在弹窗内,这些都是自定义弹窗需要手动实现的。
还有<mark>表示高亮文本、<meter>表示度量值、<progress>表示任务进度。能准确说出这些标签的适用场景,比背十个八股题都管用。
2.3 h1-h6 的层级纪律:一个页面到底该有几个 h1
“一个页面有几个 h1”是语义化里的经典追问。我的建议是:一个页面只放一个 h1,一般用于站点主标题或页面核心标题。HTML5 的文档大纲理论上允许每个 section 有自己的 h1,但实际场景里搜索引擎对多 h1 的页面往往视为结构不清晰,而且主流工具对 sectioning 内容的支持也参差不齐,所以保守做法就是“一页一 h1”。
h1 到 h6 不能跳级,也是容易被忽略的点。h1 后面直接跟 h3,文档大纲就缺了一级,屏幕阅读器用户按标题跳转导航时,会突然找不到 h2 层级的内容,体验很差。我在面试里会让候选人现场给一篇博客文章写标题结构,很多人会写成“h1 是 logo,h2 是文章标题”,这是错的。logo 应该用<div>包裹图片,h1 应该是文章真正的标题,或者是站点名,不能把装饰性 logo 当作 h1。
2.4 现场手写:文章列表页“标准答案”长什么样
面试手写题最常见的场景之一,是写一个博客文章列表。很多同学会写出一堆 div + class,样式看起来没问题,但结构没有任何语义。参考实现可以是这样:
<main> <h1>最新文章</h1> <article> <h2><a href="/post/1">前端校招面经:HTML 到底要怎么复习</a></h2> <p>面经整理:从基础模板到语义化,从表单细节到资源加载……</p> <p> <time datetime="2026-05-20">2026-05-20</time> </p> </article> </main>每个标签的选择都有理由:<main>标记页面主内容区域,一个页面只有一个;<article>表示每条文章是独立、自包含的内容;<h2>作为 h1 下的直接子级;<a>包裹标题是文章链接的标准写法;<time>标记发布时间。面试官看的是结构思维能力,而不是代码量。
3. 表单与交互:HTML 里细节最多的一章
表单是 HTML 里细节密度最高的部分,也是校招面试经常会出场景题的地方。一个搜索框、一个注册表单,都能问出很多花样。
3.1 input 的 type 属性:一个属性值能问出多少东西
type最基础的是 text 和 password,但面试官真正关心的往往是移动端输入体验相关的细节。比如“移动端让用户输入手机号,用 type='number' 还是 type='tel'?”
很多同学直接答 number。面试官想听到的答案是:要看场景。type="number"会调起带小数点和正负号的数字键盘,更侧重数值输入;type="tel"调起的是纯数字键盘,适合手机号这种“本质上是数字串但不参与数学运算”的输入。如果只是要一个数字软键盘但不想改变数据的语义类型,可以用inputmode="numeric",它只控制软键盘样式,不改变输入值类型。
type="email"在移动端会调出带 @ 和 .com 的键盘;type="search"在 WebKit 内核浏览器里会自带一个清除按钮;type="date"在 Chrome 是日历控件,在 iOS Safari 是滚轮选择,不同浏览器表现差异很大,实际项目要提前评估 UI 统一性。
3.2 HTML5 原生校验:required、pattern 与 setCustomValidity
表单校验是前端必考题。现代浏览器支持的原生校验属性包括required、minlength、maxlength、min、max、step、pattern,加上type="email"这类自动约束。
校验触发时机是表单 submit 时,浏览器会阻止不合法的表单提交,并弹出气泡提示。如果项目想用异步校验拦截提交、同时不触发浏览器自带气泡,可以在<form>上加novalidate属性,自己做校验逻辑。
面试高频题:“原生实现一个手机号校验的输入框”。参考写法:
<input type="tel" name="phone" pattern="1[3-9][0-9]{9}" inputmode="numeric" required >如果想自定义错误提示文字,用 JavaScript 的setCustomValidity(),设置后元素会进入:invalid状态,提交时显示自定义文案。注意用完后要重置为空字符串,否则元素会一直处于校验失败状态,这是实际开发里很容易踩的坑。
3.3 label 的两种绑定方式和“点击命中面积”
label看似简单,实际是表单可访问性的关键。两种绑定方式:一种是用for属性指向输入框的id,另一种是直接包裹输入框。
<label for="username">用户名</label> <input id="username" name="username" type="text"> <!-- 另一种写法 --> <label> 用户名 <input name="username" type="text"> </label>label的价值在于扩大点击命中面积。对复选框和单选框来说尤其重要,一个手指头在移动端很难精准点中一个小圆圈,但包了 label 之后,点击文字也能触发选中。屏幕阅读器朗读时,label 的内容会成为控件的可访问名称,没有 label 的输入框,辅助技术只会念“编辑框”,用户根本不知道要输入什么。
面试里有个经典错误:用placeholder当标签。placeholder 在用户输入后就消失了,而且它不构成合法的可访问名。视觉设计上确实有人不爱显示 label,但正确的做法是视觉上隐藏 label,而不是删掉它,或者用aria-label提供名称。
3.4 场景题:搜索表单如何写出“加分项”
让候选人写一个搜索表单,是我个人很喜欢的考察方式。高效能完成的人会写出类似这样的结构:
<form role="search" action="/search"> <label for="q">搜索内容</label> <input id="q" name="q" type="search" autocomplete="off" enterkeyhint="search" required > <button type="submit">搜索</button> </form>role="search"告诉辅助技术这是一个搜索区域;name="q"决定提交后 URL 的查询参数名;type="search"在部分浏览器自带清除按钮;autocomplete="off"避免浏览器历史记录干扰搜索词联想;enterkeyhint="search"会让移动端键盘的回车键变成“搜索”样式。这些细节任何一个被面试官看到,都是“基本功扎实”的直接证据。
4. 资源加载的“性能题”:script 和 link 标签比你想的复杂
HTML 不只是结构和语义,资源加载相关的标签属性也是校招面试的高频考点。尤其是性能优化方向的候选,这一章几乎是必问。
4.1 defer 与 async:脚本加载面试题的“标准图解”
这是经典中的经典。面试官会问:“默认情况下,浏览器解析到 script 标签时会发生什么?”答案是在下载并执行脚本时暂停 HTML 解析,等脚本跑完再继续解析后面的 DOM。页面越复杂、脚本越多、体积越大,阻塞就越明显,这就是脚本阻塞渲染的机制。
defer和async都是为了让脚本下载不阻塞解析。区别在于执行时机:
defer:下载不阻塞解析,等整个 DOM 解析完成后、DOMContentLoaded 事件触发前,按文档顺序执行。async:下载不阻塞解析,但下载完成后立刻执行,执行时依然会阻塞解析。多个 async 脚本执行顺序不保证,谁先下载完谁先执行。
代码示例:
<script src="a.js" defer></script> <script src="b.js" defer></script> <script src="c.js" async></script>a 和 b 一定会按顺序在 DOMContentLoaded 之前执行;c 可能在下载完成后随时插入执行,甚至会跑在 a 前面。
工程上的建议是:业务代码依赖 DOM 和依赖执行顺序,用 defer;独立统计脚本、广告脚本、第三方埋点,用 async,因为它们不依赖页面其它部分。把这两条使用原则说清楚,比单纯背定义更有说服力。
4.2 preload、prefetch、preconnect:link 标签里的性能三件套
这三兄弟在性能优化题里出镜率很高,功能也容易混淆。
preload是提前加载当前页面马上要用的资源,典型场景是首屏字体。自定义字体文件如果不提前加载,浏览器要等用到字体的文本渲染时才去下载,会出现 FOIT(不可见文本闪烁)。用<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>可以让字体下载提前开始。
这里有个坑:preload 字体资源必须带上crossorigin属性,否则浏览器会下载两次。原因是字体请求默认以 CORS 模式发出,不带 crossorigin 的 preload 请求模式不匹配,就会造成重复下载。这个细节我在面试里问过很多次,很少有人能答上来。
prefetch是提前加载用户未来可能访问的页面资源,比如下一页、弹窗里的内容,浏览器会在空闲时下载。preconnect是在页面加载早期提前完成 DNS 解析、TCP 握手、TLS 协商。如果网站用了第三方字体 CDN、图片 CDN,提前preconnect可以明显减少后续请求的建立时间。
实际场景题:“网站用了一款自定义字体,怎么优化首次加载?”可以组合答:font-display: swap显示降级字体,preload提前下载字体文件,preconnect提前连接字体服务器,三管齐下。
4.3 img 的 loading、decoding、fetchpriority:一张图片的完整加载链路
图片加载优化是性能题的重灾区。新时代的 img 标签有一组属性值得熟记:
loading="lazy"是懒加载,浏览器会在图片进入视口附近时才加载。注意首屏图片不要加 lazy,否则首屏内容会延迟加载,反而拖慢 LCP。decoding="async"让图片解码异步进行,不阻塞主线程上的渲染工作,但它不会让加载变快,只是让解码过程不卡渲染。fetchpriority="high"是告诉浏览器这张图片的加载优先级高,适合首屏 LCP 图片。
还有一个老生常谈但重要的事:img 要写width和height属性。这不是为了限制图片显示大小,而是让浏览器在图片未加载完时就能预留出正确的占位空间。不写的话,图片加载完成后布局会突然跳动,也就是 CLS(布局偏移)问题,这在性能评分里是一个重要指标。
4.4 SRI 与 crossorigin:script 标签上的安全题
integrity属性是 Subresource Integrity 的缩写,给外部脚本或样式加上哈希值,浏览器下载文件后会用哈希校验,不匹配就拒绝执行。这个机制主要用来防御 CDN 被篡改。如果资源是在第三方 CDN 上,需要同时设置crossorigin="anonymous",否则浏览器在同源策略下无法拿到原始响应做哈希比对。
面试官喜欢变体追问:“为什么有些跨域脚本报错时只能看到 Script error,拿不到详细信息?”原因是浏览器默认不向跨域脚本暴露错误信息。在 script 标签上加crossorigin="anonymous",并且服务器返回对应的 CORS 头,window.onerror 才能拿到具体的错误堆栈。这个点把跨域、CORS、错误监控串在了一起,能答好说明知识体系是连通的。
5. 可访问性与 SEO:面试官眼中的“非功能需求”
可访问性在大部分前端简历里都是“熟悉”,但真能被问出东西来的很少。校招面试里不太会要求你背 WCAG 条款,但 alt、aria、SEO 这几个基础点是绕不开的。
5.1 alt 的正确姿势:不是所有图片都需要“描述”
alt 的第一个作用是图片加载失败时显示替代文本,第二个作用是屏幕阅读器朗读图片内容,第三个作用是在弱网环境下提供内容降级。
但很多人不知道,不是所有图片都该写描述性 alt。纯装饰性图片(比如一条分割线、一个背景图里的元素)应该写alt="",空 alt 会让屏幕阅读器直接跳过图片;如果不写 alt 属性,屏幕阅读器会去念文件名,比如 “logo-final-v2.png”,这才是灾难。所以“装饰性图片用空 alt,有信息量的图片用描述性 alt”是一条重要规则。
图片包含文字时,alt 应该写文字本身,除非这些文字已经在旁边 HTML 里出现。图片作为链接内容时,alt 会成为链接文本的一部分,要写清楚“点了之后会去哪里”,而不是描述图片长什么样。title属性只是悬停提示,不能替代 alt,这条也是容易踩的坑。
5.2 aria-*:什么时候该用,什么时候是画蛇添足
aria 属性是让 HTML 元素能被辅助技术正确理解的关键。面试最常见的题是给一个自定义控件补无障碍属性,比如自定义 checkbox:
<span role="checkbox" aria-checked="true" tabindex="0" aria-label="同意用户协议" ></span>role="checkbox"告诉屏幕阅读器这是一个复选框;aria-checked表达当前选中状态;tabindex="0"让它可以被键盘聚焦;aria-label提供控件名称。这四个属性缺一不可。
但 aria 不是越多越好。如果元素已经有可见文本,就不要再加aria-label,否则辅助技术会忽略可见文本,只念 aria-label 的内容。aria-hidden="true"是给装饰性元素用的,但如果这个元素内部有可聚焦的链接或按钮,加上 aria-hidden 会造成键盘用户“聚焦到看不见的元素上”,这是严重的可访问性事故。
我的建议是:能用原生元素就用原生元素。<button>自带所有按键交互和可访问性;<dialog>自带焦点锁定和关闭逻辑。自定义交互组件才需要 aria 来补全语义。
5.3 SEO 方向的 meta 与结构化数据:两道不算偏的加分题
HTML 里和 SEO 直接相关的,一是 title 和 meta description,二是 Open Graph,三是结构化数据。
<title>是搜索结果里的大标题,<meta name="description">是摘要描述。这两个是搜索引擎最基础的理解入口。
Open Graph 协议控制的是链接分享到社交平台时的预览卡片。og:title、og:description、og:image是最常用的三个属性。很多业务方要求在分享到微信/掘金/知乎时展示好看的卡片,前端要做的就是正确输出这些 meta 标签。
结构化数据的现代实现是 JSON-LD,比如给一篇文章加 Article 类型的结构化数据:
{ "@context": "https://schema.org", "@type": "Article", "headline": "前端校招面经分享:这些 HTML 你知道吗?", "datePublished": "2026-05-20" }搜索引擎会基于这些数据生成富摘要,比如搜索结果里直接展示发布时间、作者、评分。面试不需要背 schema 全量字段,但要知道 JSON-LD 是什么、和 microdata 相比为什么更推荐——JSON-LD 写在 script 标签里,不影响 HTML 结构,更干净。
6. 冷门但能拉开差距的 HTML 细节
最后这一章,是我从历年校招面试和开发实战里挑出来的“偏门但确实会考”的点。它们不常见,但一旦出现,就能明显区分“背过八股”和“真的研究过”。
6.1 浏览器最小字号 12px,但页面里为什么能做 8px
这是一个很经典的奇怪问题。Chrome 浏览器对中文页面默认设置了一个最小字号限制,通常是 12px