@supports 指令在 Safari iOS 中的工作原理

Posted

技术标签:

【中文标题】@supports 指令在 Safari iOS 中的工作原理【英文标题】:How @supports directive works in Safari iOS 【发布时间】:2019-08-08 18:02:51 【问题描述】:

我的 Web 应用程序是响应式的,我必须支持 ios 10 及更高版本。 我有一个高度是动态的容器。为了处理 iPhone X 布局,我使用@supports 指令,如下所述:iPhone X layout features with CSS Environment variables。

这是我迄今为止实现的代码(不要考虑90px,因为这只是一个示例):

const wrapperWhenCollapsed = 
  height: 'calc(100% - 90px)',
  '@supports (padding-top: constant(safe-area-inset-top))': 
    height: 'calc(100% - 90px - constant(safe-area-inset-bottom))',
  ,
  '@supports (padding-top: env(safe-area-inset-top))': 
    height: 'calc(100% - 90px - env(safe-area-inset-bottom))',
  ,
;

const wrapperWhenExpanded = 
  height: '100%',
  '@supports (padding-top: constant(safe-area-inset-top))': 
    height: 'calc(100% - constant(safe-area-inset-bottom))',
  ,
  '@supports (padding-top: env(safe-area-inset-top))': 
    height: 'calc(100% - env(safe-area-inset-bottom))',
  ,
;

基于此,我有几个问题:

padding-top@supports 指令中的用途是什么? 有没有办法在不使用padding-top的情况下使用@supports指令?

我的目标是验证浏览器是否支持constantenv。如果不是,则应用后备值。

谢谢,洛伦佐

【问题讨论】:

【参考方案1】:

发生了什么事。

认为@supports@media 相同,它基本上是浏览器理解的if/else 检查。

在@supports的情况下,你需要提供一个有效的CSS规则来解析。问题是 CSS env() 是 CSS 中值声明的一部分。因此,要正确匹配为“有效”@supports 需要一个匹配的属性名称来检查整个规则是否有效。

因为env() 作为布局声明的一部分是有效的,所以选择了padding-top。您可能会改用paddingmargin 等。 它必须是一个有效的可解析规则。


设备测试

如果您的目标是针对特定设备,我会非常小心地使用@supports,因为它旨在告诉您浏览器可以做什么而不是具体使用什么设备。 Chrome、Firefox、Safari 等都会告诉你env()is valid。虽然只有 Safari(旧版本)支持 constant() 代替 env()现在它已被弃用。

在这种情况下,您真正​​要测试的是 safe-area-inset-* 存在并且其值不是 CSS 渲染引擎支持特定属性。


由于您使用 javascript 来设置它,您应该能够避免所有 @supports 的东西,只需使用 JS 测试变量。 (我没有测试过这个,因为我无权访问设备)

var safe = getComputedStyle(document.body).getPropertyValue('safe-area-inset-top');
if(safe && safe != null) 
  // is iPhoneX so do your thing
  // or maybe another phone with a notch...

注意,如果它有效,我不知道你应该期待什么。但我假设你会得到一个像素尺寸,所以测试它是否存在并获得一个值。


话虽如此,您确实不应该测试特定的设备/浏览器组合。相反,您应该构建能够适应不同设备的代码。这意味着任何有缺口的手机与 iPhone X 相比。

【讨论】:

您好,感谢您的回复。这是申请用 Cordova 编写的应用程序吗?我认为在这种情况下@supports 可能是一个很好的解决方案,因为 'safe-area-inset-top' 仅适用于 iOS WebKit,不适用于 android 那么 js 应该可以与 Cordova 一起使用,但是我不知道您需要使用哪个生命周期挂钩。我相信 getComputedStyle() 需要等到 DOM 完全呈现,我也不知道 env() 变量何时真正可用。【参考方案2】:

对于您的height 属性,您不需要使用@supports,因为任何无法识别env()constant() 的浏览器都会退回到您的默认值(calc(100% - 90px) 或@ 987654326@).

至于如何使用@supports,您可以将其与任何CSS 属性/值组合一起使用。它检测用户的浏览器是否支持特定的 CSS 功能。一些例子:

@supports (display: grid)  /* Browser supports grid layout */ 
@supports (color: #ffff)  /* Browser supports RGBA hex colors */ 
@supports (--foo: 123)  /* Browser supports CSS variables */ 

【讨论】:

以上是关于@supports 指令在 Safari iOS 中的工作原理的主要内容,如果未能解决你的问题,请参考以下文章

CSS 文本动画不会在 Safari 中显示,我无法让 @supports 查询作为备份

macOS+iOS:Safari和Webkit停止支持SHA-1证书了

webkit-backface-visibility 崩溃 safari 和 chrome (IOS)

如何打开mac application support路径

Apple 最新(2015 年)“链接到应用商店”指令导致 Safari 出现不必要的行为

详解Vue中的自定义指令