用disabled比改href更稳,因disabled是原子性开关,不触发重载、无fouc;而改href会引发样式空档期导致白屏或错位,前提是目标css须预加载完成。

为什么用 disabled 比直接改 href 更稳
直接改 href 会触发浏览器重新请求、解析、注入样式表,中间存在空档期——旧样式已卸载、新样式未就绪,页面可能白屏或错位(FOUC)。而 disabled 是原子性开关:浏览器不中断加载,只控制是否应用,切换瞬间完成,无重排、无重载、无竞态。前提是目标 CSS 文件必须**已预加载完成**,否则禁用再启用也无效。
两个 link 标签 + disabled 的最小可行写法
HTML 中预置两套主题的 link,都设为 rel="stylesheet",仅一个启用:
<link id="theme-light" rel="stylesheet" href="/css/light.css"><link id="theme-dark" rel="stylesheet" href="/css/dark.css" disabled>
切换时只需 JS 控制属性:
document.getElementById('theme-light').disabled = truedocument.getElementById('theme-dark').disabled = false
注意:disabled 对 rel="preload" 无效,所以两个 link 都不能用 preload;若需预加载,得用 fetch() 或 rel="prefetch" 单独拉取资源,但不挂载到 DOM。
如何避免 iOS Safari 下 disabled 失效
iOS Safari(尤其是旧版)对 disabled 切换响应不稳定,常见表现是样式没变、disabled 属性已更新但浏览器没重绘。应对方式:
- 切换后强制触发一次微任务重排:
getComputedStyle(document.body).color - 确保两个
link的href路径可访问且非 404,否则 Safari 可能静默忽略整个link - 不要在
DOMContentLoaded前执行切换逻辑,否则部分 WebKit 内核可能尚未完成样式表注册 - 如果必须兼容极旧 iOS,降级为
href切换 +onload监听 +setTimeoutfallback
配合 localStorage 和 prefers-color-scheme 的初始化顺序
用户偏好优先级应是:localStorage > system preference > fallback light。但初始化时容易出错:
- 先读
localStorage.getItem('preferred-theme'),有值则立即设对应disabled状态 - 无值时调用
window.matchMedia('(prefers-color-scheme: dark)')判断系统倾向,再设状态 - 必须在所有
link标签已解析进 DOM 后再执行初始化(推荐放在DOMContentLoaded回调里) - 监听系统变化时,只更新
localStorage和 UI 状态,**不自动切主题**——除非用户明确关闭了“跟随系统”开关
真正麻烦的不是切换动作本身,而是初始化那一帧:DOM 尚未就绪就操作 disabled,或 localStorage 读取晚于样式应用,都会导致首屏闪一下旧主题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











