使用 CSS 播放声音

Avatar of Alvaro Montoro
Alvaro Montoro

DigitalOcean 提供适用于您旅程各个阶段的云产品。立即开始使用 $200 免费积分!

CSS 是样式、布局和展示的领域。它充满了颜色、尺寸和动画。但您知道它还可以控制网页上何时播放声音吗?

本文介绍了一种实现该功能的小技巧。它实际上是对 HTML 和 CSS 的严格实现,因此并非真正意义上的黑客手段。但…… 坦白地说,这仍然算得上是一种黑客行为。我并不建议在生产环境中使用它,因为在生产环境中,音频应该由原生 <audio> 元素和/或 JavaScript 进行控制。

技巧

使用 CSS 播放声音有几种方法,但基本原理相同:将音频文件作为隐藏对象/文档插入网页,并在发生操作时显示它。例如以下代码

<style>
  embed { display: none; }
  button:active + embed { display: block; }
</style>

<button>Play Sound</button>
<embed src="path-to-audio-file.mp3" />

查看演示

此代码使用 <embed> 标签,但我们也可以使用 <object> 标签,效果类似

<object data="path-to-audio-file.mp3"></object>

关于演示和该方法,需要说明一点。大约一年前,我在 CodePen 上用 HTML 和 CSS 制作了一个 小型钢琴,使用了这种方法。效果很好,但此后,一些内容发生了变化,该演示在 CodePen 上不再可用。

最大的变化与安全性有关。由于它使用 embedobject 而不是 audio,因此导入的文件将受到更严格的安全检查。跨域访问控制策略 (CORS) 强制音频文件与导入它的页面使用相同的协议和域。即使将声音以 base64 格式存储也不再有效。此外,您(和用户)可能需要在浏览器设置中启用自动播放,才能使该技巧起作用。它通常在标志后面启用。

另一个变化是,浏览器现在只播放声音一次。我曾经发誓,过去的浏览器每次显示声音时都会播放它。但事实似乎不再如此,这极大地限制了该技巧的适用范围(并且使钢琴演示几乎毫无用处)。

如果您控制着服务器和文件,可以解决 CORS 问题,但禁用自动播放是针对每个用户的,我们无法控制。

查看演示

工作原理

这种行为背后的理论可以在 embed 标签的定义 中找到,隐藏在其中

每当一个未 处于潜在活动状态embed 元素变为 潜在活动状态,以及每当一个 潜在活动状态的 embed 元素保持 潜在活动状态 且其 src 属性被设置、更改或删除,或者其 type 属性被设置、更改或删除时,用户代理必须 排队执行一个任务,使用嵌入式任务源来运行该元素的 embed 元素设置步骤

object 标签的 定义 也是如此

每当以下情况之一发生时

[…]

  • 元素从 正在渲染 状态变为未渲染状态,或反之,

[…] 用户代理必须 排队执行一个任务,以运行以下步骤来(重新)确定 object 元素所代表的内容。[并最终处理和运行它]

虽然 object 的情况更清晰(文件在渲染时被处理和运行),但 embed 具有“潜在活动”的概念,可能显得更加复杂。虽然还有一些其他条件,但它会在初始渲染时运行,与 object 的运行方式类似。

如您所见,从技术上讲,这根本不是什么技巧,而是所有浏览器都应该执行的操作…… 尽管它们并没有这么做。

浏览器支持

与许多此类黑客手段和技巧一样,该功能的浏览器支持情况并不理想,而且在不同浏览器之间差异很大。

在 Opera 和 Chrome 上效果很好,这意味着它在浏览器市场中占很大比例。但是,在其他基于 Chromium 的浏览器中的支持情况参差不齐。例如,Mac 上的 Edge 会正确播放音频,而 Brave 浏览器则不会,除非您使用的是最新版本。

Safari 无法使用,Internet Explorer 或 Windows 上的 Edge 也是如此。在这些浏览器中,没有任何类似于工作的东西。

Firefox 会在页面加载时一次播放所有声音,但之后,在声音被隐藏后再显示时,它不会再播放。它会在控制台中触发安全警告,因为声音尝试在“没有用户交互”的情况下播放,因此除非用户先批准网站,否则会被阻止。

总的来说,这是一个有趣的 CSS 技巧,但属于“不要在家尝试”的那种…… 在软件开发中,这意味着这是在家中尝试的完美选择。🙂