必须遵循.plyr__*结构,因为Plyr的JS和CSS均依赖该BEM约定定位真实DOM节点;自定义class会导致控制失效、样式不生效及状态不同步。

直接用 .plyr__control 命名按钮、进度条等交互元素,配合 .plyr--fullscreen 这类修饰符表达状态,就能让结构一目了然,避免样式污染和命名冲突。
为什么不用自定义 class 名,而必须遵循 .plyr__* 结构
BEM 在 Plyr 中不是可选项,而是其 CSS 架构的底层约定。所有内置控制组件(如播放按钮、音量滑块、全屏开关)都通过 Shadow DOM 或 JS 动态注入,并绑定到固定 class 名上。如果你写 .my-play-btn 并试图覆盖 ::-webkit-media-controls-play-button,会失败——因为那个伪元素根本不在你写的 HTML 里;而 Plyr 的 DOM 是真实存在的,且只响应它自己定义的 BEM class。
常见错误现象:
- 手动给
<button>加class="play",却发现点击无反应 → Plyr 的 JS 只监听.plyr__control[data-plyr="play"] - 用
.video-player__progress覆盖进度条样式,但实际生效的是.plyr__progress→ 类名不匹配,CSS 规则被忽略
.plyr__control 和 .plyr__progress 的语义分工
.plyr__control 是所有可交互控件的通用容器级 class,它本身不决定外观,只表示“这是一个用户能点/拖/切换的东西”。真正区分功能的是它的 data-plyr 属性值:
立即学习“前端免费学习笔记(深入)”;
-
<button class="plyr__control" data-plyr="play">→ 播放/暂停主控 -
<input type="range" class="plyr__control" data-plyr="volume">→ 音量调节器 -
<div class="plyr__progress">→ 进度条容器(非控件,不可交互,仅展示)
注意:.plyr__progress 不是 .plyr__control 的子类,它是独立 Element,用于包裹内部的 .plyr__progress__buffer 和 .plyr__progress__played。混用会导致样式错位或 JS 行为异常。
状态类必须用 .plyr--* 修饰符,不能硬写 is-playing
Plyr 通过 JS 动态在根容器(.plyr)上添加/移除状态类,比如播放时加 .plyr--playing,静音时加 .plyr--muted。这些类是全局开关,影响整套 UI 的视觉反馈:
-
.plyr--playing .plyr__control[data-plyr="play"]::before→ 显示暂停图标 -
.plyr--paused .plyr__control[data-plyr="play"]::before→ 显示播放图标 -
.plyr--fullscreen .plyr__controls→ 控制栏占满全屏高度
如果你自己写 .is-playing 并试图控制图标切换,Plyr 的 JS 不会同步这个 class,导致图标状态与实际播放逻辑脱节。
自定义扩展控件必须挂载到 .plyr__controls 内部,且 class 名保持 BEM 一致性
想加一个“倍速选择”下拉菜单?不能丢在 <body> 里,也不能用 .custom-speed-select 这种孤立名:
<div class="plyr__controls">
<!-- 原有控件 -->
<button class="plyr__control" data-plyr="play"></button>
<!-- 自定义控件:必须用 plyr__ 前缀 + 合理 element 名 -->
<div class="plyr__speed-control">
<select class="plyr__speed-select">
<option value="1">1x</option>
<option value="1.5">1.5x</option>
</select>
</div>
</div>这样做的关键原因:Plyr 的 CSS 特异性基于 .plyr__controls > *,你的新控件只有在相同层级、同前缀下,才能继承基础间距、对齐、禁用态等默认样式。否则就得重写一整套 reset 规则。
最易被忽略的一点:BEM 不是命名游戏,而是约束 DOM 与 CSS 的契约。Plyr 的 class 名一旦改错,JS 就找不到目标节点,CSS 就无法命中,连基本的点击反馈都会消失——这不是样式没生效,是整个控制链断了。



















