HTML5 相比 HTML4 有哪些重大改进?列举至少5个新特性。
-
标签上的改动
- 新增了一些语义化标签,比如像: nav、footer、header、ssection之类的
- 提供了一些新功能的标签:video、audio
- 删除了一些标记表现,比如font
-
API新增
- Canvas、Svg
- 媒体播放器(video、audio)
- 拖拽
- indexedDB
- 新增了一些表单元素:progress
什么是语义化标签?列举常见的语义化标签并说明其用途。
语义化标签,可以让开发者构建清晰的页面结构,同时也更有利于爬虫对网站内容的解析。
- html文档结构清晰,比如header、section、footer的经典布局
- 更好的用户体验,像img标签的alt属性,即使在图片未加载的情况下,可以显示图片信息。
- 更有利于网站的SEO优化,爬虫解析依赖标签来决定上下文关键字的权重。
<!DOCTYPE html> 的作用是什么?如果不写会发生什么?
<!DOCTYPE html> 是HTML文档类型声明,它的作用是告诉浏览器按照最新的标准模式来保证 HTML文档。
如果不声明,可能会触发怪异模式。
- CSS布局错乱(width和 padding的计算方式不同)
- javascript行为错误
HTML 中的 data-* 属性有什么作用?如何通过 JavaScript 访问?
data-* 其实就是一个自定义的attribute,开发者用来存储html标签对应的数据,基本上只能存储字符串类型(当然序列化后的js对象也可以存)。也可以当成一个自定义属性来设置css内容(其实就是一个自定义的属性选择器)
js通过获取data-*
// 通过getAttribute 访问
let btn = document.querySelector('#btn')
let size = btn.getAttribute('data-size')
// 通过dataset访问
size = btn.dataset.size
css访问:
btn[data-size="sm"] {
width:100px;
height:32px;
font-size:14px;
}
参考链接:
<meta> 标签有哪些常见用法?(如 viewport、charset、SEO 相关)
<meta> 标签用于定义 HTML 文档的元数据(metadata),用来表示HTML文件的解析、SEO、移动端适配等内容。
- 字符编码声明
<meta charset="UTF-8">
2. 控制浏览器的布局和缩放
<meta name="viewport" content="width=device-width, initial-scale=1.0">
3. SEO相关
关键词(keywords):
<meta name="keywords" content="HTML, meta标签, SEO, 前端">
页面描述(Description)
<meta name="description" content="这是一个关于HTML元标签用法的详细介绍页面">
控制搜索引起的行为
<meta name="robots" content="noindex, nofollow">
#noindex:禁止搜索引擎索引本页。
#nofollow:禁止跟踪本页的链接。
4. 社交媒体卡片(open graph)
<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">
<script> 标签中 defer 和 async 的区别是什么?
<script> 标签中的 defer 和 async 都是用来控制脚本加载和执行行为的属性
没有src属性的脚本 defer和async 会被忽略
- 默认行为:
<script src="script.js"></script>
- 加载:立即下载脚本,会阻塞html解析
- 执行:脚本下载完后会立即执行,执行也会阻塞 html解析
- 影响:可能会导致页面渲染延迟
- async(异步):
<script async src="script.js"></script>
-
加载:异步下载脚本,不阻塞HTML解析
-
执行:脚本下载完成后立即执行(无论HTML是否解析完成)
-
特点:
- 多个
async脚本的执行顺序不确定(先下载完的先执行)。 - 适合独立脚本,不依赖dom或其他脚本,若脚本操作DOM,可能会因为DOM未就绪报错
- 多个
-
影响
- defer(延迟)
- 加载:异步下载脚本,不阻塞HTML解析
- 执行: 脚本延迟到 html解析完成后,DOMContentLoaded 事件前按顺序执行
<img> 的 srcset 和 sizes 属性如何实现响应式图片?
- Srcset: 图片候选集,提供多个图片源,并指定每个源的宽度描述符(w)或像素密度描述符(x)
- sizes:自定义渲染条件,告诉浏览器图片在不同视口下的渲染宽度(CSS像素)
<img src="default.jpg"
srcset="small.jpg 480w, medium.jpg 1024w, large.jpg 1600w"
sizes="(max-width: 600px) 480px, 1024px">
为什么用 srcset 而不是 CSS 或 JavaScript?
- 原生支持:浏览器可提前解析,避免布局抖动和额外请求。
- 性能优化:减少高分辨率设备下载不必要的超大图片。
- SEO 友好:图片内容能被搜索引擎正确抓取。
HTML 中如何实现懒加载(Lazy Loading)?原生支持的方式是什么?
html实现懒加载的方式有三种:
- 原生方式:
优点:不用写javascript代码,理论上性能最优
缺点: 无法设置自定义触发距离或者加载回调
<img src='image.jpg' loading="lazy" alt='...'/>
优点:异步监听,比监听滚动事件更高效,可以自定义触发距离,不仅针对图片,任何广告、图片都可以作为懒加载的元素
缺点:首屏内容默认不会触发观察,就浏览器需要通过polyfill兼容
<html>
<body>
<img data-src="image.jpg" class="lazy" alt="...">
</body>
</html>
<script>
const lazyImages = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 替换 data-src 为实际 src
observer.unobserve(img); // 停止观察已加载的图片
}
});
});
lazyImages.forEach(img => observer.observe(img));
</script>
- 滚动视口方案:
优点 :兼容性最佳
缺点:性能较差,频繁触发滚动事件,肯能会造成布局抖动
window.addEventListener('scroll', throttle(() => {
const lazyImages = document.querySelectorAll('.lazy');
lazyImages.forEach(img => {
if (isInViewport(img)) { // 判断元素是否进入视口
img.src = img.dataset.src;
img.classList.remove('lazy');
}
});
}, 200));
<canvas> 和 <svg> 的区别及适用场景。
canvas和svg的使用场景其实截然不同。
| 特性 | | |
|---|---|---|
| 类型 | 位图(像素级) | 矢量图(基于 XML) |
| 渲染方式 | 通过 JavaScript 动态绘制(即时渲染) | 声明式 XML 描述,由浏览器解析渲染 |
| DOM 支持 | 无(绘制后无法单独操作图形元素) | 是(每个图形是 DOM 节点,可绑定事件) |
| 分辨率适应性 | 依赖分辨率(放大变模糊) | 分辨率无关(无限缩放不失真) |
| 性能 | 适合高频更新(如游戏、动画) | 复杂静态图形性能更好 |
| SEO/可访问性 | 差(内容无法被搜索引擎或屏幕阅读器识别) | 好(文本和结构可被索引) |
<iframe> 的优缺点是什么?哪些场景下会用到它?
iframe可以在一个页面中嵌入一个新的独立网页,比如一个网站中可以嵌入youtube、bilibili等外部视频,或者是嵌入一些广告。
优点:
- 内容隔离,可以将第三方网站内容嵌入,不会影响原网站的内容,由于父页面和嵌入页面的js和 css隔离,也不会因嵌入页面被恶意攻击
- 兼容性好,基本上所有现代浏览器都支持
缺点:
- Seo: 搜索引擎会忽略掉ifream中的内容
- 未设置
loading="lazy"时会阻塞父页面onload事件。 - 同源策略限制了不同域的的内容交互
HTML5 表单新增了哪些输入类型?
- 基础输入类型
| 类型 | 用途 | 示例 |
|---|---|---|
| type="email" | 输入电子邮件地址(自动验证格式) | |
| type="url" | 输入 URL(自动验证格式) | |
| type="tel" | 输入电话号码(移动端弹出数字键盘) | |
| type="search" | 搜索框(样式可能与普通文本不同) | |
| type="color" | 颜色选择器 |
- 数字与范围输入
| 类型 | 用途 | 属性 |
|---|---|---|
| type="number" | 输入数字(支持步进增减) | min, max, step(如 step="0.1") |
| type="range" | 滑块控件(选择数值范围) | min, max, value(默认值) |
如何通过 HTML 实现表单验证(无需 JavaScript)?
- 必填字段,使用
required属性强制用户填写字段
<input type="text" name="username" required>
<textarea name="feedback" required></textarea>
2. 使用 html5新增的输入类型自带格式验证:
<input type="email" name="email" required>
<input type="url" name="website">
3. 通过pattern 属性自定义规则
<input
type="password"
name="password"
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$"
title="密码需至少8位,包含大小写字母和数字"
>
<label> 标签的 for 属性和包裹输入框的区别?
两者在功能上其实是等效的,作用都是关联表单控件
- for属性(通过id关联)
<label for="username">用户名:</label>
<input type="text" id="username">
2. label标签包裹
<label>
用户名:
<input type="text">
</label>
整体看下来其实,for的功能和灵活性更高,开发复杂表单时,更推荐使用for + id的形式开发,但同时也要注意id冲突。
<datalist> 和 <select> 的区别是什么?
<datalist> 和 <select> 都用于提供输入选项,但它们在交互方式、灵活性和使用场景上有显著区别。以下是详细对比:
| 特性 | | |
|---|---|---|
| 交互方式 | 输入+下拉建议(类似搜索框自动补全) | 纯下拉选择(只能选择预设选项) |
| 输入自由度 | 允许用户输入自定义值 | 仅限选择列表中的选项 |
| 多选支持 | 不支持 | 可通过 实现 |
| 数据结构 | 通过 关联 | 直接包裹 子元素 |
| 浏览器支持 | IE10+ 和现代浏览器 | 所有浏览器(包括旧版) |
<label>输入城市:</label>
<input type="text" list="city-list">
<datalist id="city-list">
<option value="北京">
<option value="上海">
<option value="广州">
<option value="深圳">
</datalist>
<label>选择城市:</label>
<select>
<option value="">--请选择--</option>
<option value="bj">北京</option>
<option value="sh">上海</option>
<option value="gz">广州</option>
</select>
如何禁用表单的自动填充(autocomplete)?
设置 autocomplete="off" ,可以对整个表单(form)设置,也可以给输入框设置(input)
HTML 中哪些操作会导致重绘(Repaint)或回流(Reflow)?
在html和css中,某些操作会触发重绘或者回流,影响页面性能。
回流:浏览器重新计算元素的机和属性(尺寸、位置等),导致重新布局
重绘:浏览器重新绘制元素的可见样式(颜色、背景等),不影响布局
回流一定触发重绘,重绘不一定触发回流
触发回流的操作:
- 改变元素的尺寸、位置或布局
- 获取某些布局属性,如offsetWidth(强制触发回流)
- 文本或者图片的内容发生变化
- 删除/新增dom元素
- 窗口的缩放
触发重绘的操作:
- 修改不影响布局的视觉样式
优化建议 :
-
减少回流的次数
- 批量修改dom操作
- 将布局属性缓存起来,避免频繁操作读取
-
使用css优化
- 使用不会触发回流的元素代替(如: 使用 translateX 代替 left属性)
-
脱离文档流
- 对于有复杂动画的元素使用绝对定位,将动画元素脱离完当流,减少回流对其他元素的影响。
可以使用开发者工具检测
- Chrome DevTools → Performance 面板记录回流/重绘事件。
- 启用 Rendering → Layout Shift Regions 可视化回流区域。
预加载(Prefetch/Preload)如何通过 HTML 实现?
在 HTML 中,可以通过<link rel="preload">和 <link rel="prefetch">实现资源的预加载,优化页面性能。
- Preload(关键资源预加载)
- as 指定资源类型,可选值包括
script、style、font、image等。 - type指定 MIME 类型(如
font/woff2)。 - crossorigin 跨域资源必须添加
特点:
- 浏览器会立即加载资源,优先级高于普通请求。
- 适合渲染阻塞资源(如首屏 CSS)。
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="app.js" as="script">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
2. prefetch(非关键资源预加载)
<link rel="prefetch" href="next-page.html" as="document">
<link rel="prefetch" href="image.png" as="image">
特点:
- 浏览器在空闲时加载资源,优先级较低。
- 适合预加载 下一页内容或用户可能访问的资源。
什么是 HTML 的 contenteditable 属性?它有什么潜在问题?
contenteditable 是一个html属性,可以用于指定元素内容是否可以被用户所编辑。一般用于富文本编辑器。
<div contenteditable="true">可编辑的内容</div>
潜在问题:
- 可能会被粘贴恶意代码,造成xss攻击
- 内容的频繁编辑会触发回流和重绘,影响性能
localStorage、sessionStorage 和 Cookie 的区别?
| 特性 | localStorage | sessionStorage | Cookie |
|---|---|---|---|
| 存储位置 | 浏览器本地存储 | 浏览器会话存储 | 浏览器和服务器(通过 HTTP 头传输) |
| 生命周期 | 永久存储,除非手动删除或清除浏览器数据 | 仅限当前会话(关闭标签页/浏览器后清除) | 可设置过期时间(默认会话级) |
| 存储大小 | 通常 5~10MB(不同浏览器可能不同) | 同 localStorage | 约 4KB(单个域名下总数有限制) |
| 数据共享范围 | 同源的所有标签页和窗口共享 | 仅限当前标签页(同源也不共享) | 同源共享(可通过 domain 和 path 控制) |
| 是否自动发送到服务器 | 否 | 否 | 是(通过 HTTP 请求头自动发送) |
| API 易用性 | 简单的键值对接口(setItem/getItem) | 同 localStorage | 需手动解析字符串(或依赖库) |
| 安全性 | 仅限客户端,无 HTTPS 自动保护 | 同 localStorage | 可设置 Secure(仅 HTTPS)、HttpOnly(防 XSS) |
| 主要用途 | 长期存储客户端数据(如用户偏好) | 临时会话数据(如表单草稿) | 身份验证(如 Session ID)、跟踪用户行为 |
HTML5 提供了哪些离线存储方案?
-
Web storage(详细内容参照上题)
- Session storage
- Local storage
-
Index DB
Index DB用来存储结构化数据,适合较大规模、复杂的数据,也可以存文件,同时支持事务、索引和一部的操作。存储容量也比较大,约为浏览器空间的 50%-80%
- Service Worker
缓存网络请求(如 HTML、CSS、JS、图片等),实现离线访问。
详细的service worker 可以参考下面这篇文章:
如何使用 Web Workers 在 HTML 中实现多线程?
Web Workers 是 HTML5 提供的 API,允许在后台线程中运行 JavaScript 代码,避免阻塞主线程。
基本用法:
- 先创建一个单独的worker脚本,用来执行复杂操作
// worker.js
self.onmessage = function(e) {
const data = e.data; // 接收主线程发送的数据
const result = heavyCalculation(data); // 执行耗时计算
self.postMessage(result); // 将结果发送回主线程
};
function heavyCalculation(data) {
// 模拟耗时计算(如大数据处理、复杂算法)
let sum = 0;
for (let i = 0; i < data; i++) {
sum += i;
}
return sum;
}
2. 在主js文件中初始化worker
// main.js
const worker = new Worker('worker.js'); // 加载 worker.js
// 向 Worker 发送数据
worker.postMessage(100000000); // 发送一个较大的数字
// 接收 Worker 返回的结果
worker.onmessage = function(e) {
console.log('计算结果:', e.data); // 输出 Worker 返回的结果
};
// 错误处理
worker.onerror = function(e) {
console.error('Worker 错误:', e.message);
};
worker.terminate();
web worker适用场景:
- CPU 密集型计算(如大数据分析、图像处理)。
- 长时间运行的任务(如实时数据解析、WebSocket 数据处理)。
- 避免 UI 卡顿(如复杂动画、图表渲染)。
target="_blank" 的安全风险是什么?如何避免?
会有反向标签劫持的风险,攻击原理如下:
-
用户点击带有
target="_blank"的链接时 -
恶意网站链接
window.openerAPI 获取对原页面的控制权- 可以将原页面重定向到钓鱼网站
- 执行恶意操作
防范措施:
- 跳转标签添加
rel="noopener"****
<a href="https://example.com" target="_blank" rel="noopener">安全链接</a>
2. 跳转标签添加 rel="noreferrer"
<a href="https://example.com" target="_blank" rel="noopener noreferrer">安全链接</a>
也可以同时添加**
noopener** 和noreferrer<a href="https://example.com" target="_blank" rel="noopener noreferrer">安全链接</a>