陪读蛙

自定义字幕样式

用自己的 CSS 定制视频字幕:模糊译文、弱化原文,或者重新设计字幕框。

字幕样式页面能调字体、缩放、粗细、颜色和背景透明度。自定义 CSS 负责这些控件够不到的部分:用模糊把译文盖住、真正需要时才看,给译文加下划线,把原文推到次要位置,或者重新设计字幕框的形状。

它只作用于陪读蛙的字幕覆盖层。网页翻译有一份独立的样式表,见自定义翻译样式

打开编辑器

  1. 打开 设置 → 视频字幕
  2. 点击自定义样式进入字幕样式
  3. 滚动到自定义 CSS 并点击进入。
  4. 写你的 CSS。编辑器上方的预览会随着输入实时更新。
  5. 点击保存

保存会同步到已经打开的播放器,所以你可以在另一个标签页留一个视频,边保存边看效果。清空编辑器再保存就会移除这段 CSS,字幕交还给上面的控件。

从预设模板开始

预设模板下拉框里有三段现成的样式。选中一个是追加到编辑器末尾,而不是覆盖已有内容,所以模板可以叠加:选两次就能同时模糊译文并且弱化原文。

模糊译文

先靠听,实在听不出来再看。鼠标移到那一行时模糊会消失。

.subtitles-translation {
  filter: blur(6px);
  transition: filter 0.15s ease;
}

.subtitles-translation:hover {
  filter: none;
}

虚线译文

把译文标记成辅助信息,而不是正文。

.subtitles-translation {
  text-decoration: underline dashed;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
}

弱化原文

原文仍然在,但不会第一时间抢走视线。

.subtitles-main {
  opacity: 0.6;
}

可以使用的选择器

覆盖层刻意做得很小。以下三个类名属于对外约定,不会被重命名:

<div class="read-frog-subtitles-box">
  <div class="subtitles-main">Mr. Kamiya isn't confronting the world…</div>
  <div class="subtitles-translation" lang="zh" dir="ltr">神谷先生…</div>
</div>
选择器匹配的元素
.read-frog-subtitles-box装着两行字幕的框——背景、内边距、圆角、宽度、对齐
.subtitles-main原文那一行
.subtitles-translation译文那一行

译文那一行还带两个额外的钩子:

  • langdir 跟随你的目标语言,所以 .subtitles-translation[lang='ja'].subtitles-translation[dir='rtl'] 都能用。
  • 译文还在返回途中时会带上 data-pending="true"
.subtitles-translation[data-pending='true'] {
  opacity: 0.35;
}

DOM 里永远是原文在前;译文位置只是用 order 在视觉上调换两行。请按类名匹配,不要用 :first-child

与样式控件配合

你在界面里选的字体、缩放、粗细和颜色,是以 CSS 变量的形式送到每一行上的,再由一条样式规则转换成真正的声明。你的 CSS 注入在那条规则之后,所以一条普通声明就能覆盖它——不需要 !important

.subtitles-translation {
  color: #ffd479;
  font-weight: 600;
}

有两个例外,值得在动手之前先知道。

改属性,别改 --rf-subtitle-* 变量

那四个控件背后的变量是以行内样式写在每一行上的,而行内声明的优先级高于任何样式表规则。在自定义 CSS 里写 --rf-subtitle-color 不会有任何效果:

/* 无效——该变量是行内设置的。 */
.subtitles-main { --rf-subtitle-color: #7cf; }

/* 有效。 */
.subtitles-main { color: #7cf; }

字幕框背景需要 !important

背景透明度出于同样的原因也是行内写在框上的,这是自定义 CSS 唯一需要强硬一点的地方:

.read-frog-subtitles-box {
  background-color: rgba(24, 20, 48, 0.85) !important;
  border-radius: 10px;
  padding: 8px 14px;
}

框上的其他属性——内边距、圆角、宽度、对齐——普通声明就够了。

字号用 em,别用 px

覆盖层的根字号是按视频高度算出来的,字幕在全屏或缩成小窗时能保持比例靠的就是这一点。一行上的 1em 意味着“播放器本来会用的字号”;写成 px 就固定了,不再跟随视频。

.subtitles-translation {
  font-size: 1.15em;
}

更多示例

去掉底框,给文字描边

适合画面偏亮的视频——这时候深色底框比字幕本身还碍眼。

.read-frog-subtitles-box {
  background-color: transparent !important;
}

.subtitles-main,
.subtitles-translation {
  text-shadow:
    0 0 4px rgba(0, 0, 0, 0.95),
    0 1px 3px rgba(0, 0, 0, 0.9);
}

让译文当主角

把原文缩小成参考,把分量交给译文。

.subtitles-main {
  font-size: 0.75em;
  opacity: 0.65;
}

.subtitles-translation {
  font-size: 1.1em;
  font-weight: 600;
}

长句左对齐

字幕一旦换行到三行,居中就很难读了。

.read-frog-subtitles-box {
  max-width: 70%;
  text-align: left;
}

按语言设置字体

如果你会用多个目标语言阅读,又希望每种语言都好看,这个很有用。

.subtitles-translation[lang='ja'] {
  font-family: "Hiragino Mincho ProN", "Yu Mincho", serif;
}

.subtitles-translation[dir='rtl'] {
  font-size: 1.05em;
}

作用范围与限制

覆盖层渲染在播放器内部的一个 shadow root 里。这个边界既保证你的 CSS 不会泄漏到页面上,也决定了哪些写法会悄无声息地失效:

  • 有效,且只作用于覆盖层内: @keyframes@media@supports、过渡、伪类,以及你自己定义的 CSS 变量。
  • 会被忽略: @font-face@property。shadow root 无法注册这两者,所以请使用系统里已有的字体,而不是自己加载。
  • 匹配不到任何东西: :rootbody。覆盖层里没有页面级元素——请使用上面那三个类。
  • 够不到: YouTube 播放器自己的控件、它背后的页面,以及原生字幕。自定义 CSS 无法给字幕覆盖层之外的任何东西设置样式。
  • 体积上限: 8 KB。编辑器会随输入检查语法,CSS 不合法或过长时会禁用保存
/* 动画没问题,而且不会跑到覆盖层外面。 */
@keyframes rf-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.subtitles-translation {
  animation: rf-fade-in 0.2s ease-out;
}

排查问题

  • 保存之后没有变化: 先确认状态显示 CSS 有效、按钮显示已保存,再检查规则是否命中了那三个类名之一。
  • 给框设置的背景色无效: 加上 !important。透明度控件是把这个属性行内写上去的。
  • 覆盖 --rf-subtitle-* 没有效果: 改成直接设置 colorfont-sizefont-familyfont-weight
  • 全屏时字号突变: 把那条 font-sizepx 换成 em
  • 字体始终不生效: @font-face 在覆盖层里不起作用,请使用系统里已安装的字体。
  • 保存按钮是灰的: 编辑器发现了语法错误,或者样式表超过了 8 KB。
  • 覆盖层看起来坏掉了: 清空编辑器并保存。CSS 会立刻被移除,样式控件重新接管。

自定义 CSS 和其他设置存在一起,会随配置导出一并带走,见配置、同步与备份。覆盖层的其余内容见视频字幕

On this page