发现 CSS 中的 JavaScript 支持

原文信息: 查看原文查看原文

Detect JavaScript Support in CSS

- Ryan Mulligan

我一直知道有 scripting CSS 媒体特性,但我仍然以为它的跨浏览器支持不足。根据 caniuse.com 的信息,发现截至2023年12月,所有现代浏览器都已支持这一特性,这真是一个令人愉快的惊喜。有了这个特性,我们可以根据用户浏览器中是否可用 JavaScript 来提供替代的 CSS 规则。它还可以帮助减少未样式化内容的闪烁或不希望的布局偏移。

在我们深入之前: 尽管这个特性非常激动人心,我发现有一些不幸的陷阱。我在文章中增加了一个 问题 部分来说明。

使用方法

我们可以渐进式地增强我们的样式:

@media (scripting: enabled) {
  .my-element {
    /* 如果 JS 可用,则增强样式 */
  }
}

或者我们可以优雅地回退到一些替代样式:

@media (scripting: none) {
  .my-element {
    /* 如果 JS 不受支持,则使用回退样式 */
  }
}

还有一个 initial-only 值,适用于在页面加载期间启用但之后不启用的脚本。媒体查询第5级W3C工作草案 包括了几个它可能有用的案例。

例如,打印页面,或者在服务器上预渲染网络代理,并将几乎静态的页面版本发送给用户。

我个人不太想象会经常使用 initial-only,如果有的话。

特性出现之前的时间

在这项特性之前,检测 JavaScript 支持的一种方法是通过在开放的 html 标签上设置自定义选择器——在野外常见的一个是 no-js 类名。如果 JavaScript 被支持并启用,它会在渲染页面内容之前移除那个选择器。当 JavaScript 被禁用时,我们可以提供适应体验的替代样式。

<html class="no-js">
  <!-- 页面内容 -->
</html>
.no-js .my-element {
  /* 当 JS 被禁用时的样式 */
}

这是真实的生活吗?

想象一下,一个新的网络活动即将上线,是时候与所有关键利益相关者联系了。一切看起来都很好,大多数团队对结果感到满意,但突然间,会议上一些时髦的市场人员强烈要求在页面加载时在英雄组件上增加一个复杂的介绍动画。他们手势生动地要求主要标题淡入,像被弹弓拉回一样缩小,然后……这时他们用嘴发出爆炸声。“让它脱颖而出!”他们在发射前24小时下达命令。

汪。最好开始吧。

为了处理这项工作的复杂性,我们可能会求助于像 GSAP 这样的动画库。但如果 JavaScript 不可用,用户会看到什么,更不用说如果用户启用了 prefers reduced motion 设置?我们需要考虑一个没有所有那些摆动和缩放的英雄版本。

这个媒体查询解锁了提供更适合用户体验的 CSS 规则的能力。在下面的 CodePen 演示中,如果我们禁用 JavaScript,我们将发现动画被跳过,显示静态标题。

注意那个闪烁

要真正使页面加载时的介绍动画感觉平滑,演示依赖于 scripting 媒体查询来使用 CSS 隐藏标题。通过这样做,我们不会在 GSAP 动画加载之前捕捉到未样式化文本的闪烁。此外,我们只想在 JavaScript 可用 时隐藏标题,否则在禁用 JavaScript 的用户中它将被隐藏。

在下面的视频中,观察当页面加载时标题不被隐藏时会发生什么。当在较慢的网络上节流时,文本闪烁问题更加明显。

在视频中,为了分享那些烦人的未样式化文本的闪烁,标题在页面加载时不再被隐藏。当模拟较慢的网络速度时,问题变得更加严重。

结合查询

在演示的 CSS 标签中,注意媒体查询被结合起来同时检查脚本和减少运动的条件。

@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  /* JS 可用且运动 OK */
}

@media (scripting: none), (prefers-reduced-motion) {
  /* JS 被禁用或减少运动已启用 */
}

每个条件当然可以有专属的样式,如果期望的结果需要的话,但在规则集有重叠的地方结合它们也很好。

ISSUE

更新于2024年4月21日 - 在发布这篇文章后,一些反馈浮现出来,解释了这个媒体特性哪里意外地失败了。

  1. 当使用如 NoScript 或 uBlock Origin 这样的浏览器扩展来禁用页面脚本时,它的表现不符合预期。即使扩展关闭了 JavaScript,scripting: enabled 仍然匹配。
  2. 如果脚本被阻止或无法加载,需要通过 JavaScript 来处理回退。在上面的示例中,回退需要进入演示的 scripting: none 媒体查询规则集,以便显示英雄的静态版本。

非常感谢 SaraŠimeVadim 的分享!

分享于 2024-05-05

访问量 38

预览图片