track 的 default 属性仅在首次加载且用户未操作时作为初始启用信号,需满足 kind="subtitles"、srclang 有效、src 可解析且未被手动关闭;它不自动匹配用户语言,多 default 行为不一致,JS 动态设置更可靠。

track 的 default 属性只在「首次加载且用户未操作」时生效
它不是“永久开启”,也不是“优先级最高”,而是一个初始开关信号。浏览器拿到 <track> 列表后,会扫描所有带 default 的轨道,从中选一个启用——但前提是:该轨道 kind="subtitles"、srclang 有效、src 可解析,且没有被用户手动关闭过。
常见错误现象包括:
- 加了
default却没显示字幕 → 检查srclang是否拼错(比如写成zh-CN但系统语言是zh) - 两个
<track>都写了default→ 浏览器可能忽略全部,或只启用第一个(行为不一致) - Safari 私密模式下完全不加载
<track>→ DOM 中甚至找不到该元素,default彻底无效
多个语言 track 并存时,default 不等于“自动匹配用户语言”
HTML 规范里 default 和 srclang 是解耦的:即使你写了 srclang="en" default,而用户系统语言是 ja,浏览器也不会自动 fallback 到 srclang="ja" 的那个 track;它只会启用那个标记了 default 的英文轨道(如果可用)。
真正起语言匹配作用的是 srclang + 用户操作系统/浏览器语言设置,但这个匹配仅影响「自动选择」逻辑,和 default 无关。如果你希望中英文按用户语言自动启用,就得:
立即学习“前端免费学习笔记(深入)”;
- 不设任何
default,靠浏览器原生语言协商 - 或用 JS 主动判断
navigator.language,再调用video.textTracks[i].mode = "showing" - 注意:Chrome 和 Firefox 对多
srclang的协商结果可能不同,测试时别只看一个浏览器
DOM 操作 default 属性比 HTML 写死更可控
直接在 HTML 里写 <track default> 看似简单,但容易被缓存、预加载顺序、或 polyfill 干扰。更稳妥的做法是等 <video> 加载完成后再用 JS 设置:
video.addEventListener('loadedmetadata', () => {
const tracks = video.textTracks;
for (let i = 0; i < tracks.length; i++) {
if (tracks[i].language === 'zh') {
tracks[i].mode = 'showing';
break;
}
}
});
这样能绕过以下问题:
- HTML 解析时
<track>还没挂到 video 上,default被忽略 - 某些安卓 WebView 对
default支持不全 - 服务端渲染时提前注入了错误的
default轨道
default 属性在 XHTML 或严格模式下必须写成 default="default"
虽然现代 HTML5 页面大多用 <track default> 就行,但如果你的项目跑在 XHTML MIME 类型(application/xhtml+xml)下,或者用了某些老旧校验工具,布尔属性必须显式赋值:
✅ 正确:<track kind="subtitles" src="cn.vtt" srclang="zh" label="Chinese" default="default">
❌ 错误:<track ... default>(XHTML 中会被视为无效属性)
这个细节极难排查,因为页面看起来完全正常,只有用 document.querySelector('track').hasAttribute('default') 才能确认是否被正确解析。
真正容易被忽略的是:即使所有条件都满足,Safari 在 iOS 17+ 的某些配置下仍会静默禁用字幕轨道——这时连 JS 设置 mode 都无效,只能换用 canvas 渲染字幕或改用 WebVTT 解析库手动绘制。



















