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 上不再可用。
最大的变化与安全性有关。由于它使用 embed
或 object
而不是 audio
,因此导入的文件将受到更严格的安全检查。跨域访问控制策略 (CORS) 强制音频文件与导入它的页面使用相同的协议和域。即使将声音以 base64 格式存储也不再有效。此外,您(和用户)可能需要在浏览器设置中启用自动播放,才能使该技巧起作用。它通常在标志后面启用。
另一个变化是,浏览器现在只播放声音一次。我曾经发誓,过去的浏览器每次显示声音时都会播放它。但事实似乎不再如此,这极大地限制了该技巧的适用范围(并且使钢琴演示几乎毫无用处)。
如果您控制着服务器和文件,可以解决 CORS 问题,但禁用自动播放是针对每个用户的,我们无法控制。
工作原理
这种行为背后的理论可以在 embed
标签的定义 中找到,隐藏在其中
每当一个未 处于潜在活动状态 的
embed
元素变为 潜在活动状态,以及每当一个 潜在活动状态的embed
元素保持 潜在活动状态 且其src
属性被设置、更改或删除,或者其type
属性被设置、更改或删除时,用户代理必须 排队执行一个任务,使用嵌入式任务源来运行该元素的embed
元素设置步骤。
每当以下情况之一发生时
[…]
- 元素从 正在渲染 状态变为未渲染状态,或反之,
[…] 用户代理必须 排队执行一个任务,以运行以下步骤来(重新)确定
object
元素所代表的内容。[并最终处理和运行它]
虽然 object
的情况更清晰(文件在渲染时被处理和运行),但 embed
具有“潜在活动”的概念,可能显得更加复杂。虽然还有一些其他条件,但它会在初始渲染时运行,与 object
的运行方式类似。
如您所见,从技术上讲,这根本不是什么技巧,而是所有浏览器都应该执行的操作…… 尽管它们并没有这么做。
浏览器支持
与许多此类黑客手段和技巧一样,该功能的浏览器支持情况并不理想,而且在不同浏览器之间差异很大。
在 Opera 和 Chrome 上效果很好,这意味着它在浏览器市场中占很大比例。但是,在其他基于 Chromium 的浏览器中的支持情况参差不齐。例如,Mac 上的 Edge 会正确播放音频,而 Brave 浏览器则不会,除非您使用的是最新版本。
Safari 无法使用,Internet Explorer 或 Windows 上的 Edge 也是如此。在这些浏览器中,没有任何类似于工作的东西。
Firefox 会在页面加载时一次播放所有声音,但之后,在声音被隐藏后再显示时,它不会再播放。它会在控制台中触发安全警告,因为声音尝试在“没有用户交互”的情况下播放,因此除非用户先批准网站,否则会被阻止。
总的来说,这是一个有趣的 CSS 技巧,但属于“不要在家尝试”的那种…… 在软件开发中,这意味着这是在家中尝试的完美选择。🙂
我在 HTML 中添加了“tabindex”属性,并在 CSS 中添加了 :focus …… 现在,按下“Tab”键可以依次播放声音 :)
这真的很酷 :)