面试题-浏览器/网络/性能优化
浏览器
三种浏览器缓存
localStorage和sessionStorage
浏览器存储localStorage和sessionStorage,用于在客户端持久化存储数据
特性 | localStorage | sessionStorage |
---|---|---|
存储时间 | 永久存储,除非手动删除 | 会话期间存储,关闭页面/浏览器后清除 |
存储大小 | 通常为 5MB 左右(不同浏览器可能不同) | 同上 |
作用域 | 同一域名下所有页面共享 | 同一页面/标签页的会话内有效 |
localStorage只能存储字符串,存取对象需要JSON方法进行转换,否则是[object Objet]
loacl/sssionStorage不同域的数据不共享
sessionStorage同一浏览器窗口的不同标签页可共享数据,新开的窗口不共享
cookie
cookie像超市会员卡 ,容量小,每次都会携带。
在服务器第一次返回响应时候,会在响应头添加cookie信息,浏览器自动保存到本地,下次访问同一域名时会在请求头中自动带上cookie,服务器根据cookie识别用户身份
关于token–我的疑惑+详解
因为我只是用过localStorage存储+axios拦截器从里面获取token,没有使用过cookie,所以问了大模型老师:
1.携带token的方法有哪些,如何给后端token,有什么区别?
2.我不理解既然cookie会自动保存token,那么为什么还要通过localStorage保存token呢,这两个token有什么区别吗
详解如下:
Cookie与LocalStorage存储Token的核心区别表格
区别 | Cookie存储 | LocalStorage存储Token |
---|---|---|
携带方式 | 浏览器自动随请求发送,无需前端额外代码。 | 需前端手动从本地取出并添加到请求头。 |
安全性 | - 可设置HttpOnly防止XSS,但存在CSRF风险(需配合SameSite)。 - 跨域时受同源策略限制。 |
- 不自动发送,需前端严格控制token使用,避免XSS攻击(如避免在前端JS中直接操作token)。 |
存储时效 | 可设置过期时间(如max-age ),或随浏览器关闭过期(会话cookie)。 |
永久存储,需前端手动删除(如用户登出时)。 |
跨域共享 | 同域名下共享,跨域需后端配置Access-Control-Allow-Credentials 。 |
同域名下共享,不同域名不互通(受同源策略限制)。 |
容量限制 | 约4KB,不适合存储大token。 | 约5-10MB,适合存储JWT等较长字符串。 |
Token 的携带方法及给后端的方式
Token本质是客户端向服务器证明身份的凭证,常见携带方式如下:
请求头(Header)携带:最主流的方式
实现:在HTTP请求头中添加Authorization
字段,格式通常为Bearer <token>
(如 JWT 场景)JWT(JSON Web Token)是一种轻量级的开放标准(RFC 7519),常用于身份验证和信息安全传输
1
2
3
4
5
6
7axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});优势:
跨域请求时可通过设置withCredentials: true
携带(需后端配合)。
与前端框架(如 Vue/React)集成方便,可统一拦截处理Cookie 存储并自动携带
实现:服务器返回token时通过Set-Cookie响应头写入浏览器cookie,后续请求自动携带。
注意事项:
需设置HttpOnly: true
(防止 XSS 攻击)和SameSite: Strict/Lax
(防止 CSRF 攻击)。
跨域场景下需后端配置 Access-Control-Allow-Credentials: true。
缺点:
cookie大小限制(通常 4KB),不适合存储大token。
域名共享问题(不同子域名需配置SameSite为None并配合HTTPS)。LocalStorage/SessionStorage存储,手动携带
实现:前端将 token 存入本地存储,发送请求时从本地取出并添加到请求头1
2
3
4
5
6
7
8// 存储
localStorage.setItem('token', response.data.token);
// 携带
fetch('api/resource', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});优势:
存储容量大(一般 5MB+),适合存储 JWT 等较长的 token。
不依赖域名,可在同一浏览器的不同标签页共享(localStorage)
为什么同时用 localStorage 和 cookie 存 token?
其实这两种方式各有优缺点。比如 cookie 的好处是自动携带,不用前端写额外代码,但安全性较弱,容易被 XSS 攻击(所以一般会加 HttpOnly)。而 localStorage 需要手动管理,但容量大,适合存 JWT 这样的长 token。实际项目中可能会结合用,比如用 localStorage 存 token,用 cookie 存一些非敏感信息,同时通过前端拦截器统一在请求头里携带 token,这样既能保证安全,又方便管理。
Token 是怎么生成的?存在哪里
Token是服务器生成的一串加密字符串,用于标识用户身份,类似 “电子钥匙”
存储位置:
客户端:存储在 cookie、localStorage 等位置。
服务器:不强制存储(如 JWT 无需存储,服务器通过密钥验证签名),或存储在数据库(如 Session Token 需记录会话状态)
Token 一般是服务器生成的。比如JWT的话,服务器会用密钥把用户信息(像 ID、权限)加密成一个字符串,直接返回给前端,服务器自己不用存这个 token,下次用户带 token 来的时候,服务器用同样的密钥验证签名对不对就行。
如果是 Session Token,服务器会生成一个随机字符串,存在数据库里,然后把 token 给前端,后续前端带 token 来,服务器就查数据库确认是不是有效。
根据场景选择存储方式
优先用请求头 + localStorage:适合大多数前后端分离项目,前端手动管理 token,配合拦截器统一携带,安全性和灵活性较高。
配合 cookie 使用:需开启 HttpOnly 和 SameSite,适合对兼容性要求高或需要跨域携带 token 的场景(如 SSR 项目)。
核心原则:token 的存储和携带方式需平衡安全性、开发效率和项目需求,避免单一方案的缺陷(如 cookie 的 CSRF 风险、localStorage 的 XSS 风险)
浏览器缓存策略
浏览器缓存的工作流程
首次请求:服务器返回资源及缓存策略(强缓存 / 协商缓存参数)
再次请求:
先检查强缓存是否有效,若有效则直接使用缓存(状态码200 (from cache))
若强缓存失效,发送协商缓存请求头(If-Modified-Since/If-None-Match)到服务器。
服务器验证后,若资源未更新,返回304,浏览器使用缓存;若更新,协商缓存失效,返回新资源
强缓存和协商缓存
强缓存(本地缓存)
浏览器直接读取本地缓存,不与服务器交互,状态码为200关键响应头:
Expires:资源过期时间(绝对时间戳),若未过期则直接读取缓存
Cache-Control(优先级高于Expires):
max-age=秒数:资源在多少秒内有效,如max-age=3600表示 小时内缓存有效。
public:资源可被客户端和代理服务器缓存
private:资源仅可被客户端缓存
no-cache:并非不缓存,而是需要经过协商缓存验证
no-store:禁止任何形式的缓存,每次请求都从服务器获取协商缓存(服务器验证)
浏览器向服务器发送验证请求,验证资源是否更新,状态码为304,若未更新则使用缓存关键响应头:
第一次请求时服务器返回:
Last-Modified:资源最后修改时间。
ETag:资源的唯一标识(如文件哈希值)。
后续请求时浏览器发送:
If-Modified-Since:携带Last-Modified的值,询问服务器资源是否修改。
If-None-Match:携带ETag的值,询问服务器资源是否变更
服务器响应:
若资源未更新,返回304 Not Modified,浏览器使用本地缓存
若资源更新,返回200 OK及新资源内容
缓存策略的选择场景
强缓存适合:
静态资源(如图片、CSS、JS),版本稳定,更新频率低。
可设置max-age为较长时间(如 1 周),并通过 URL 版本号控制更新。
协商缓存适合:
动态数据(如用户信息页面),或更新频率较高但需缓存的资源。
避免强缓存导致数据过期,通过协商缓存确保数据时效性。
Cache-Control有哪些常用值
max-age=N:资源在 N 秒内有效,过期后需重新验证。
public:资源可被客户端和代理服务器缓存(如 CDN)。
private:资源仅客户端可缓存,代理服务器不可缓存(如用户登录信息)。
no-cache:强制浏览器发送协商请求到服务器,验证资源是否更新。
no-store:禁止任何缓存,每次请求都从服务器获取(如敏感数据)。
ETag相比Last-Modified有什么优势?
Last-Modified:资源最后修改时间。
ETag:资源的唯一标识(如文件哈希值
- Last-Modified有局限性:
只能精确到秒级,若资源在 1 秒内多次修改,无法识别
服务器时间同步问题可能导致判断不准 - ETag的优势:
基于文件内容生成哈希值,更精准判断资源是否变更
可解决Last-Modified的时间精度问题和服务器时间不一致问题
如何强制更新浏览器缓存?
- 修改资源 URL(最常用):
如将index.js改为index.v2.js,浏览器会视为新资源,跳过缓存。 - 利用Cache-Control: no-cache:
每次请求强制走协商缓存,由服务器验证是否更新。 - 修改响应头ETag或Last-Modified:
服务器主动变更标识,使协商缓存失效。
如何强制更新浏览器缓存?
- 修改资源 URL(最常用):
如将index.js改为index.v2.js,浏览器会视为新资源,跳过缓存。 - 利用Cache-Control: no-cache:
每次请求强制走协商缓存,由服务器验证是否更新。 - 修改响应头ETag或Last-Modified:
服务器主动变更标识,使协商缓存失效。
缓存策略进阶问题:缓存与性能优化的结合
如何利用缓存提升首屏加载速度?
对静态资源启用强缓存,减少重复请求。
对 HTML 文件使用协商缓存(因 HTML 更新频率高,避免强缓存导致页面不更新)。
利用Service Worker实现 PWA 缓存,进一步提升离线加载能力。
缓存可能带来的问题及解决方案?
问题:资源更新后,旧缓存未失效,导致用户看到旧内容。
解决方案:
对静态资源使用Contenthash命名(如index.abc123.js),内容变更时 URL 自动更新。
对 HTML 文件设置Cache-Control: no-cache,确保每次请求验证最新内容。
场景:用户反馈页面更新后,部分图片 / JS 未刷新,如何排查?
检查服务器响应头是否正确设置了缓存策略(如Cache-Control的max-age是否过长)。
查看浏览器DevTools的Network面板,确认资源是否走了强缓存(200 from cache)或协商缓存(304)。
若资源应更新但未更新,可手动清除浏览器缓存,或强制刷新页面(Ctrl+Shift+R,跳过强缓存)。
- 长期解决方案:对静态资源添加版本号后缀(如img?v=2.0),强制浏览器加载新资源。
网络
跨域问题如何解决
是否跨域首先要看两个资源是否同源,如果两个资源的协议协议、域名、端口号有不一样的,就会触发跨域限制。
- 跨域限制目的:保护数据安全,浏览器要限制跨域为了防止恶意网站读取或修改用户数据。
- 哪些操作会触发跨域限制:
前端AJAX请求跨域接口浏览器会报错
cookie、session、loaclStorage共享时,跨域无法自动携带
DOM操作:iframe产生的页面如果跨域,只能显示页面,无法进行js操作
本地存储,跨域无法读取localStorage - 例外情况:浏览器允许静态资源跨域加载
跨域解决方案
- CORS(最常用,生产环境也能用):是一种后端配置规则,允许特定源的请求访问数据。适用于前后端分离的项目,安全性高
- Nginx的代理:是生产环境正式解决方案,需要服务器配置
- 反向代理(开发用):在前后端之间添加“中间层”,把跨域请求变成同源请求。只在本地有效,是开发环境的临时解决方案
- JSONP(旧项目用):利用
<script>
标签可以跨域加载JS脚本的特性间接获取数据。仅适用GET请求,安全性低
Nginx
是一款轻量级的高性能 Web 服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器
作用
- 反向代理与负载均衡
Nginx可作为反向代理服务器
可以将客户端请求均匀分配到多个后端服务器上,使各服务器负载均衡,避免单点服务器压力过大,提高系统整体处理能力和可靠性 - 静态资源服务器
对静态资源(如 HTML、CSS、JavaScript、图片等)的处理效率极高
Nginx 可配置缓存,将经常访问的静态资源缓存到内存或磁盘中,当有相同请求再次到来时,直接从缓存中读取并响应,减少后端服务器的负载和响应时间,进一步提高网站性能和用户体验 - HTTP 请求处理与优化
Nginx 支持 HTTP/2 协议
能对 HTTP 请求进行过滤和处理,如检查请求头、URL 等信息,根据规则拒绝非法请求或进行相应的处理,防止恶意攻击,如 SQL 注入、XSS 攻击等,增强系统安全性
HTTP的多个版本
HTTP 协议有多个版本,常见的有 HTTP/1.0、HTTP/1.1 和 HTTP/2
兼容性:
HTTP/1.0 和 HTTP/1.1 兼容性较好,被大多数浏览器和服务器支持
HTTP/2 虽然越来越普及,但仍有一些旧设备或环境可能对其支持不完全,不过随着技术发展,兼容性问题在逐渐改善
HTTP/1.0
每个请求都需要建立一个新的 TCP 连接,请求完成后连接即被关闭,意味着每次请求和响应都有较高的延迟,因为建立和拆除连接需要消耗时间和资源
适用于一些简单的、对性能要求不高的小型网站或应用,不过现在已较少单独使用
HTTP/1.1
1.0 基础上进行了改进。支持持久连接,即多个请求可以复用同一个 TCP 连接,减少了连接建立和关闭的开销,提高了性能
还支持请求管道化,允许客户端在一个连接上连续发送多个请求,而无需等待前一个请求的响应,但服务器仍需按顺序响应请求
广泛应用于各种类型的网站和应用,能较好地满足大多数常规网络应用的需求
HTTP/2
采用了二进制分帧层,将数据分割成更小的帧,并以二进制格式传输,提高了传输效率
多路复用,多个请求和响应可以在同一个连接上同时进行,且相互不干扰
它支持服务器推送,服务器可以主动向客户端推送资源,提前将客户端可能需要的资源发送给客户端,减少客户端的请求次数
特别适合高并发、对性能要求极高的场景,如大型电商网站、在线视频平台等,能显著提高页面加载速度和用户体验
HTTP 状态码分类
HTTP 状态码是服务器对请求的响应结果标识,用 3 位数字表示,首位数字定义类别:
- 1xx(信息响应):请求已被接收,需要继续处理(临时状态)。
- 例如:
101 Switching Protocols
(协议切换,如 WebSocket 握手)。
- 例如:
- 2xx(成功):请求已成功处理。
- 例如:
200 OK
(标准成功响应)、201 Created
(资源创建成功)。
- 例如:
- 3xx(重定向):需要客户端进一步操作以完成请求。
- 例如:
301 Moved Permanently
(永久重定向)、302 Found
(临时重定向)、304协商缓存
- 例如:
- 4xx(客户端错误):请求包含错误或无法完成。
- 例如:
400 Bad Request
(请求语法错误)、404 Not Found
(资源不存在)。
- 例如:
- 5xx(服务器错误):服务器处理请求时发生错误。
- 例如:
500 Internal Server Error
(服务器内部错误)、503 Service Unavailable
(服务不可用)。
- 例如:
高频状态码详解
- 200 OK:
- 场景:GET 请求成功获取资源,或 POST 请求提交数据成功(后端可能返回 200 或 201)。
- 前端关注:正确处理响应数据(如 JSON 解析、渲染页面)。
- 301 vs 302:
301:永久重定向(浏览器缓存跳转,后续直接访问新 URL)。
302:临时重定向(每次需向原 URL 发起请求)。
- 304 Not Modified:
- 场景:协商缓存生效,资源未修改,直接使用本地缓存。
- 前端关联:通过
Cache-Control
和ETag
控制缓存策略。
- 401 Unauthorized:
- 含义:请求未携带有效身份凭证(如 Token 过期)。
- 前端处理:跳转登录页或自动刷新 Token(通过 Axios 拦截器)。
- 403 Forbidden:
- 含义:服务器理解请求,但拒绝执行(如无权限访问接口)。
- 与 401 区别:401 是未认证,403 是已认证但无权访问。
- 404 Not Found:
- 场景:请求资源不存在(如 URL 错误、未部署静态文件)。
- 前端优化:自定义 404 页面,提升用户体验。
- 500 Internal Server Error:
- 含义:服务器处理请求时发生未知错误(如代码异常)。
- 前端处理:提示用户“服务异常,请稍后重试”,并上报日志。
JWT
JWT(JSON Web Token)是一种用于网络间安全传输声明的标准,它通过数字签名确保传输信息的完整性和真实性,常用于身份验证和授权场景。
如何防止 CSRF 攻击
CSRF(跨站请求伪造):攻击者诱导用户向已认证的网站发送恶意请求
防御 CSRF 攻击的核心是验证请求来源。常用方法包括添加 Anti-CSRF Token、设置 SameSite Cookie,以及验证 Referer 头。例如,Spring Security 默认使用 CSRF Token 防御攻击
get post put PATCH
GET:请求数据,不会修改服务器数据
POST:提交数据,修改服务器数据
PUT:更新数据,完整替换现有资源
PATCH: 部分更新现有资源
POST 用于创建新资源(URI 由服务器分配)
PUT 用于更新已有资源(URI 由客户端指定)
get
幂等:多次相同请求结果相同(如刷新页面不会重复创建数据)。
参数暴露:数据通过 URL 参数(?key=value)传递,有长度限制(约 2KB)。
可缓存:浏览器默认缓存 GET 请求(如图片、CSS 文件)
POST
非幂等:重复提交可能创建多条相同数据(如多次提交表单)。
参数隐蔽:数据放在请求体(Body)中,适合传输大量或敏感数据。
不可缓存:浏览器默认不缓存 POST 请求
PUT 请求
幂等:多次相同请求结果相同(如多次修改同一数据)
完整替换:需提供资源的全部字段,缺失字段会被删除
避免大量小 PUT 请求,可合并为一次 POST 批量更新
工程化能力
前端工程化包含:1)构建(Webpack/Vite),2)编译(Babel/PostCSS),3)优化(代码分割、Tree Shaking),4)性能监控(Lighthouse)。通过这些环节,实现代码模块化、自动化构建和性能调优。
Webpack/Vite 构建工具
模块打包:将 JS、CSS、图片等资源打包成少量文件,减少HTTP请求
资源处理:通过Loader(Webpack)或原生ESM(Vite)处理非JS资源(如SASS转CSS、图片压缩)
Vite利用浏览器原生ESM,开发环境无需打包,启动极快。生产环境用Rollup打包,适合现代框架
示例配置项:
entry
:起点文件output.path
:输出目录module.rules
:配置Loaderplugins
:扩展功能”
Babel、PostCSS 等编译工具
两者都是构建流程中的‘翻译官’
Babel:将新版JS(ES6+)转译为旧版(ES5)以兼容老浏览器。支持JSX等语法扩展
PostCSS:用JS插件转换CSS(如自动加前缀、用CSS变量、嵌套写法等)
PostCSS 本身不处理样式,通过插件(如autoprefixer
)实现功能
代码分割、Tree Shaking 等优化手段
代码分割(Code Splitting):将代码拆分成多个文件,按需加载(如路由懒加载)
Tree Shaking:删除未使用的代码(依赖ESM静态结构)
前端性能优化意识
加载阶段:减小资源体积(压缩、懒加载)、加快首屏(SSR、预渲染)
运行时性能:减少重绘重排、防抖节流、Web Worker长任务拆分
缓存策略:CDN加速静态资源、Service Worker实现离线可用
Lighthouse 评测工具
- 核心指标
FCP(First Contentful Paint):首次内容绘制时间。
LCP(Largest Contentful Paint):最大内容绘制时间。
TTI(Time to Interactive):页面可交互时间。
CLS(Cumulative Layout Shift):累积布局偏移(避免内容跳动) - 优化建议
Performance:减少阻塞渲染的资源。
Accessibility:添加 ARIA 标签、合理的颜色对比度。
Best Practices:使用 HTTPS、避免弃用 API。
SEO:确保标题、元描述有效。
web标准,可用性,可访问性:
web标准
web标准是网页开发的规范合集,想要网页在不同设备、浏览器中具有一致的表现和功能,就要遵守web标准进行开发
常见的标准规范有html5的语义化标签、css3的flex布局、grid布局、javascript的标准规范。
遵循web标准能提高网页的兼容性、可维护性、优先被搜索引擎发现、提高无障碍访问能力。
可用性(用户体验)
用户要使用网页,作为开发人员,肯定希望网页能让用户高效、清晰地完成任务,侧重用户体验,这就是可用性。
核心内容有:
课件原则:当前状态和操作的可见:比如点击按钮后有明确反馈;
匹配原则:符合大部分用户的认知和习惯,比如购物车通常放在右上角或者右下方,就不能放在左上角。
容错原则:允许用户撤销,提供清晰的错误提示。
效率原则:提供快捷方式减少用户操作步骤,比如搜索框支持回车键查询,比如设计面包屑导航。
可访问性(包容性):
像无障碍坡道,让残障人士也能平等使用功能的能力。
图片添加alt文本、使用语义化标签、ARIA属性为非语义化元素添加额外语义信息;颜色对比度:文本与背景对比度至少达到4.5:1;按钮可以通过tab键聚焦。
其他问题:
为什么移动优先设计符合可用性原则?
移动优先设计从手机端开始规划,逐步适配大屏幕,这符合可用性的“效率原则”:
- 手机屏幕小,必须精简内容,反而促使设计师提炼核心功能(如电商APP优先展示“搜索”和“购物车”);
- 移动设备网络环境更复杂,优化加载性能(如图片懒加载、资源压缩)后,桌面端体验也会提升;
- 触摸操作需要更大的点击区域(如按钮至少44px×44px),这让鼠标操作也更轻松。
公司项目中如何落实Web标准?
1. 技术选型:使用HTML5语义化标签、CSS3新特性,避免过时语法(如表格布局);
2. 代码规范:
- 结构、样式、脚本分离(HTML中不写内联样式和JS);
- 命名语义化(如 nav-menu 比 div1 更易理解);
3. 构建工具: - 使用ESLint校验JS代码,Stylelint规范CSS格式;
- 自动转换语法(如Babel将ES6转为ES5,PostCSS添加浏览器前缀);
4. 测试流程: - 用W3C validator校验HTML是否符合标准;
- 在不同浏览器(Chrome、Firefox、Edge)中测试显示一致性。
性能优化
如何优化 CSS 性能?
减少选择器复杂度:避免深层嵌套(如 body div ul li a)
避免行内样式:影响缓存和维护性
减少重排(reflow)和重绘(repaint):
批量修改样式(先修改再应用)
使用 transform 和 opacity 进行动画(触发合成层)
压缩和分割 CSS:减小文件体积,利用浏览器并行加载
如何优化首次加载渲染速度?
压缩资源(CSS/JS 最小化)
懒加载非首屏图片
使用CDN加速
内联关键CSS(Critical CSS)
相关知识
less和sass
都css的预处理器,允许用更强大的语法编写css,然后编译成浏览器 能够识别的普通css
允许变量复用、函数计算、可以嵌套(比如多层选择器时)、代码组织。
- less: @,客户端编译,轻量级,不可以嵌套属性,不可以@extend,能Mixin,社区生态小,已停止更新
- sass:&,服务器编译,功能强大,可以嵌套属性,可以@extend集成,有很多第三方库,持续更新中
<script>
标签放在页面底部的原因?
解析阻塞:浏览器遇到 <script>
会暂停 HTML 解析,先下载执行 JS
解决方案:
使用 async(下载异步,执行仍阻塞)
使用 defer(延迟到 HTML 解析完执行)
CSS 为什么要放在 <head>
中?
渲染阻塞:浏览器需先构建 CSSOM 才能渲染页面
避免 FOUC(Flash of Unstyled Content):防止先显示无样式内容再突然变化
DOMContentLoaded和load事件区别?
DOMContentLoaded:HTML 解析完成 + DOM 树构建完毕(此时图片可能未加载)
load:所有资源(图片、样式表)加载完成
为什么修改大量 DOM 会导致页面卡顿?
原因:多次重排:每次 DOM 修改都触发重排(如循环中逐条改样式)
优化方案:
使用 document.createDocumentFragment() 批量操作
先 display: none 修改完再显示
使用虚拟 DOM(如 Vue/React)
重排和重绘
重排:当元素位置/尺寸变化(如改宽度、窗口缩放),浏览器重新计算布局
重绘:当元素外观变化但不影响布局(如改颜色),浏览器重新绘制
性能影响:重排 > 重绘 > 合成
优化方法:
批量 DOM 操作(使用 documentFragment)
使用 position: absolute 脱离文档流
移动端适配方案
移动端适配的核心是让网页在不同设备上显示正常、布局合理、交互流畅
常用方法
有响应式布局,通过媒体查询(@media)设置不同屏幕尺寸的样式,比如小屏时让内容撑满,大屏时居中显示。然后会用相对单位配合工具动态调整根字体大小,这样页面元素能根据设备宽度自动缩放。
对于复杂的布局,会用Flexbox或Grid来保证元素对齐和分布。图片适配会用srcset根据分辨率加载合适的资源
基础适配:rem + amfe-flexible + postcss-pxtorem
布局优化:Flexbox/Grid + 媒体查询。
资源适配:srcset + picture。
动态调整:JavaScript 动态计算字体大小或布局参数
amfe-flexible + postcss-pxtorem通过包管理器安装+配置即可
响应式布局
通过媒体查询(@media)设置不同屏幕尺寸的样式,比如小屏时让内容撑满,大屏时居中显示。会用相对单位比如%,em,rem
配合工具动态调整根字体大小,这样页面元素能根据设备宽度自动缩放
- 好处:
- 代码复用率高,一套代码适配多种设备
- 适合内容动态变化的场景(如新闻、电商页面)
- 缺点:
- 复杂布局需要编写大量媒体查询规则
- 对图片资源适配需额外处理(如srcset)
1
2
3
4
5@media screen and (max-width: 600px) {
.container {
width: 100%;
}
}
rem单位适配:
- 原理:通过 JavaScript 动态计算根元素()的 font-size,再结合 rem 单位实现缩放。
- 工具:常用 amfe-flexible + postcss-pxtorem 自动将 px 转换为 rem
- 需要手动配置或依赖工具链,对旧版浏览器兼容性要求较高
vw/vh单位适配:
- 原理:vw(视口宽度的 1%)、vh(视口高度的 1%)直接基于视口大小计算。
- 优点:
无需 JavaScript,纯 CSS 实现。
适合现代项目,布局简洁。 - 缺点:
- 对字体大小的适配需额外处理(如 clamp() 函数)。
- 部分设备可能存在兼容性问题(如 iOS 13 以下)
1
2
3.container {
width: 50vw; /* 占屏幕宽度的 50% */
}
flex和grid布局
复杂的布局,会用Flexbox或Grid来保证元素对齐和分布。最后,图片适配会用 srcset
根据分辨率加载合适的资源
Flexbox快速实现一维布局(如导航栏、卡片列表),兼容性较好
Grid更复杂的布局更灵活,兼容性较差
自适应设计
- 原理:通过服务器或前端检测设备类型,加载不同的布局文件,如 PC、移动端分开开发
优点:
可针对特定设备优化性能(如移动端加载更轻量的资源)。
缺点:
维护成本高(需维护多套代码)。
不适合内容动态变化的场景
如何选择适配方案
选择适配方案需要看项目需求。如果是传统项目,我会优先用 媒体查询 + rem,因为它的兼容性好,适配精度高。
如果是现代项目,可能会用 vw/vh 或 CSS Grid,因为它们更简洁。
对于图片资源,会用srcset和picture 标签。
如果项目需要极致性能,可能会考虑自适应设计,但维护成本会更高。总之,我会根据团队技术栈、项目复杂度和目标用户群体选择最适合的方案
rem 和 vw 的区别
- rem 是基于根元素()的字体大小计算的,通过 JavaScript 动态调整根字体大小,适合传统的渐进式适配。- - vw 是直接基于视口宽度的百分比单位,比如 1vw 等于屏幕宽度的 1%,完全不需要 JavaScript。
- rem 更适合需要精确控制字体大小的场景,
- vw 更适合现代布局,尤其是动态内容较多的页面。
- 但是vw 在处理字体时可能会导致过小或过大的问题,需要结合
clamp()函数
优化