- 原文地址:Using Feature Queries in CSS
- 原文做者:Jen Simmons
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:Cherry
- 校对者:LeviDing、H2O-2
CSS 中有一个你可能尚未据说过的工具。它很强大。它已经存在一段时间了。而且它极可能会成为你最喜欢的 CSS 新功能之一。css
这就是 @supports
规则,也被称为 Feature Queries。前端
经过使用 @supports
,你能够在 CSS 中编写一个小测试,以查看是否支持某个“特性”(CSS 属性或值),并根据其返回的结果决定是否调用代码块。例如:react
@supports (display: grid) {
// 只有在浏览器支持 CSS 网格时才会运行代码
}复制代码
若是浏览器支持 display: grid
,那么括号内的全部样式都将被应用。不然将跳过全部样式。android
如今,对于特征查询的用途,彷佛还不是很清晰。这不是一种分析浏览器是否正确地实现了 CSS 属性的外部验证,若是你正在寻找这样的外部验证,参考这里。特征查询要求浏览器对是否支持某个 CSS 属性/值进行自我报告,并根据其返回的结果决定是否调用代码块。若是浏览器不正确或不完整地实现了一个特性,@supports
不会对你有帮助。若是浏览器误报了 CSS 支持的状况,@supports
不会对你有帮助。这不是一个能使浏览器漏洞消失的魔法。ios
即使如此,我仍然以为 @supports
很是有用。若是没有 @supports
规则的帮助,我对多个 CSS 新规则的使用就会被推迟不少。css3
多年来,开发者都用 Modernizr 作特征查询,可是 Modernizr 须要 JavaScript。即便脚本很小,Modernizr 的构建的CSS 须要 JavaScript 文件的下载、执行而且要在应用 CSS 以前完成。涉及 JavaScript 老是比只使用 CSS 慢。若是 JavaScript 打开失败也就是说若是 JavaScript 不执行会发生什么?另外,Modernizr 须要一个复杂而且许多项目没法处理的附加层。特征查询速度更快、更健壮、使用起来更加简单。git
你可能会注意到,特征查询的语法与媒体查询很是类似。我把他们看作堂兄弟。github
@supports (display: grid) {
main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
}复制代码
如今大多数状况下,CSS 中不须要这样的测试。例如,你在写下面代码的时候不用测试其支持状况:web
aside {
border: 1px solid black;
border-radius: 1em;
}复制代码
若是浏览器支持 border-radius
,那么它将在 aside
上设置圆角。若是没有,它将跳过代码行并继续前进,使框的边缘为正方形。这里没有理由运行测试或使用特征查询。CSS 就是这样工做的。这是 architecting solid, progressively-enhanced CSS 中的一个基本原则。浏览器只跳过不支持的代码,不抛出错误。后端
border-radius: 1em
如图片的右边所示。然而,Internet Explorer 六、7 和 8 不会设置圆角,显示效果如图片的左边所示。看看这个例子
codepen.io/jensimmons/…
那么,你想何时使用 @supports
?特征查询是一种将 CSS 声明捆绑在一块儿的工具,以便在必定条件下做为一个组运行。当你想在新的 CSS 功能被支持的时候,将新的和旧的 CSS 混合使用,那么请使用特征查询。
让咱们看一下使用 Initial Letter 属性的示例。这个新属性 initial-letter
告诉浏览器,使元素变得更大 —— 像段首大字。在这里,一个段落中第一个词的第一个字母被设置为四行文字的大小。很是好。但我仍是想把那字母加粗,在右边留一点空白,让它变成一个漂亮的橙色。酷。
p::first-letter {
-webkit-initial-letter: 4;
initial-letter: 4;
color: #FE742F;
font-weight: bold;
margin-right: 0.5em;
}复制代码
initial-letter
的例子在 Safari 9 下的显示。如今让咱们看看其余浏览器会发生什么…
initial-letter
属性被设置的更大了一些。咱们须要一种方法来测试浏览器是否支持
initial-letter
,而且只在颜色、粗细和空白处应用更改。进入特征查询。
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) {
p::first-letter {
-webkit-initial-letter: 4;
initial-letter: 4;
color: #FE742F;
font-weight: bold;
margin-right: 0.5em;
}
}复制代码
注意,您须要测试具备属性和值的完整字符串。最初这是令我困惑的。为何我要测试 initial-letter: 4
?值为 4 重要吗?若是我传入的值是 17 呢?它是否须要与后续代码中的值相匹配?
@supports
规则测试一个包含属性和值的字符串,由于有时候须要测试的是属性,有时须要测试的是值。对于 initial-letter
的例子,你传入的是什么值并不重要。可是考虑 @supports (display: grid)
,你会看到二者都是须要的。每一个浏览器都支持 display
。只有测试版浏览器支持 display: grid
(目前来讲)。
回到咱们的示例:目前 initial-letter
仅在 Safari 9 中获得支持,而且它须要前缀。因此我写了这个前缀,为了确保包含无前缀的版本我写了这个测试。是的,能够在特征查询中使用 or
、and
和 not
语句。
这是新的结果。浏览器支持 initial-letter
的话就会将其展示为字体更大、加粗而且是橘色的段首字母。其它浏览器表现的像段首字母不存在同样,但若是这些浏览器支持了这个规则,那么视觉效果将会是同样的。(顺便说一下,目前 Firefox 正在尝试实现段首字母特性。)
如今,您可能会尝试使用此工具将代码分红两个分支。“嘿,浏览器,若是你支持视口单位,执行这段代码,若是你不支持他们,执行另外一段代码。”这感受很好而且很整洁。
@supports (height: 100vh) {
// 使用 viewport height 的布局
}
@supports not (height: 100vh) {
// 老式浏览器另外一种布局
}
// 咱们但愿是这样,但这个代码不是很好复制代码
这不是一个好主意 —— 至少如今来讲。你发现是什么问题了吗?
然而,不是全部浏览器都支持特征查询。而且浏览器不支持 @supports
将会跳过这部分的所有代码。这不是很好。
这是否是意味着,除非 100% 的浏览器都支持,不然咱们就不能使用特征查询了?不是的,咱们能够,而且当今咱们应该使用特征查询。不要像最后一个例子那样编写代码。
那怎么作才是正确的呢?这和咱们在 100% 支持媒体查询前有相同的方法。事实上,在这个过渡时期使用特征查询比使用媒体查询更容易。你只要聪明点就好了。
你但愿构建你的代码,由于最古老的浏览器不支持特征查询或您正在测试的特性。我来教你怎么作。
(固然,在未来的某个时候,一旦 100% 的浏览器有特征查询,咱们就能够更大程度地使用 @supports not
,并以这种方式组织咱们的代码。但咱们还要等不少年。
那么特征查询的支持状况如何呢?
自从 2013 年年中以来,在 Firefox、Chrome、和 Opera 就已经支持 @supports
了。它也适用于 Edge 的每个版本。Safari 在 2015 年秋季将其在Safari 9 中支持。在任何版本的 Internet Explorer、Opera Mini、Blackberry Browser 或 UC 浏览器中都不支持特征查询。
您可能会认为 Internet Explore 不支持特征查询。实际是并非。我立刻告诉你缘由。我认为最大的障碍是 Safari 8。咱们须要密切关注这儿发生的事情。
让咱们来看另外一个例子。假设咱们有一些想要应用的布局代码,为了使操做更加合理须要使用 object-fit: cover
。对于不支持 object-fit
的浏览器,咱们但愿应用不一样的布局 CSS。
咱们开始来编写代码:
div {
width: 300px;
background: yellow;
// 老布局的一些复杂代码
}
@supports (object-fit: cover) {
img {
object-fit: cover;
}
div {
width: auto;
background: green;
// 新布局的一些其余复杂的代码
}
}复制代码
那么会发生什么呢?特征查询要么支持要么不支持,新的特性 object-fit: cover
要么支持要么不支持。结合这些,咱们有 4 种可能性:
支持特征查询吗? | 支持特性吗? | 会发生什么? | 这是咱们想要的吗? |
---|---|---|---|
支持特征查询 | 支持问题中的特性 | ||
支持特征查询 | 不支持问题中的特性 | ||
不支持特征查询 | 不支持问题中的特性 | ||
不支持特征查询 | 支持问题中的特性 |
Firefox、Chrome、Opera 和 Safari 9 都支持 object-fit
和 @supports
,因此这个测试将运行得很好,而且这个块内的代码将被应用。咱们的图像将经过 object-fit: cover
被裁剪,而且咱们 div
的背景将是绿色的。
Edge 不支持 object-fit
,但它支持 @supports
,所以该测试将运行并失败,防止代码块被应用。该图像将不会有 object-fit
应用,而且 div
有黄色的背景。
这是咱们想要的。
这就是咱们的经典克星 Internet Explorer 出现的地方。IE 不支持 @supports
,而且也不支持 object-fit
。你可能认为这意味着咱们不能使用特征查询 —— 并非。
想一下咱们想要的结果。咱们想要 IE 跳过整个代码块。而且确实是这样的结果。为何呢?由于当它执行到 @supports
时,它没法识别这个语法,而且会跳转到结尾。
它可能跳过代码“出于错误的缘由” —— 它跳过代码是由于它不支持 @supports
,而不是由于它不支持 object-fit
,可是谁在意呢?!咱们仍然获得咱们想要的结果。
一样的事情也发生在 Android 的黑莓浏览器和 UC 浏览器上。他们不支持 object-fit
和 @supports
,因此咱们都准备好了。很成功。
底线是 —— 当你在浏览器中使用一个不支的特征查询的特征查询时,只要让浏览器不支持你正在测试的功能就行了。
仔细思考代码的逻辑。问问本身,当浏览器跳过这个代码时会发生什么?若是那是你想要的,你都准备好了。
问题是这第 4 个组合 —— 虽然特征查询所包含的测试没有运行,可是浏览器确实支持该特性时,而且应该运行该代码。
例如,object-fit
由 Safari 7.1(Mac)和 8(Mac和iOS)支持,但这两个浏览器都不支持功能查询。这一样适用于 Opera Mini —— 它将支持 object-fit
,但不支持 @supports
。
会发生什么呢?这些浏览器进入这个代码块,但并未使用代码,在图片上应用 object-fit:cover
,并将这个 div
的背景设置为绿色,它跳过了整个代码块,留下黄色做为背景颜色。
而且这不是咱们真正想要的。
支持特征查询吗? | 支持特性吗? | 会发生什么? | 这是咱们想要的吗? |
---|---|---|---|
支持特征查询 | 支持问题中的特性 | CSS 被应用 | 是的 |
支持特征查询 | 不支持问题中的特性 | CSS 没有被应用 | 是的 |
不支持特征查询 | 不支持问题中的特性 | CSS 没有被应用 | 是的 |
不支持特征查询 | 支持问题中的特性 | CSS 没有被应用 | 不,可能不是 |
固然,这取决于特定的用例。也许这是咱们能够忍受的一个结果。较老的浏览器得到了较老浏览器的体验。网页仍在工做。
但在大多数状况下,咱们但愿浏览器可以使用它支持的任何特性。这就是为何在涉及特性查询时,Safari 8 多是最大的问题,而不是 Internet Explorer。Safari 8 支持许多新的特性 —— 好比 Flexbox。您可能不想阻止 Safari 8 上的这些属性。这就是为何我不多在 @supports
中使用 Flexbox,或者有时候,我在代码中至少写三个分支,一个使用 not
。(这很快就变得复杂了,因此不在这里解释了)。
若是您使用的功能在旧版浏览器中比功能查询支持的更好的话,那么在编写代码时要仔细考虑全部的组合。确保不要把你但愿这些浏览器实现的功能也排除在外了。
同时,能够很容易的在 @supports
中用最新的 CSS 特性 —— 例如 CSS Grid、首字母。没有哪一个浏览器会在不支持特征查询时就支持 CSS Grid 的。咱们没必要担忧那个包含新特性时问题多多的第四种组合,在之后这使得功能查询很是有用的。
全部这一切都意味着IE11 虽然仍会存在不少年,咱们仍是能够同时使用特征查询和 CSS 的最新特性。
如今咱们明白了为何咱们不能像这样编写代码:
@supports not (display: grid) {
// 较老浏览器的代码 // 不要模仿这个例子
}
@supports (display: grid) {
// 较新浏览器的代码 // 我说这真的很糟糕吗?
}复制代码
若是咱们这样作,咱们将阻止旧的浏览器获取他们须要的代码。
取而代之的是,像这样组织你的代码:
// 较老浏览器的回退代码
@supports (display: grid) {
// 较新浏览器的代码
// 在须要时覆盖上面的代码
}复制代码
这正是咱们在使用媒体查询的同时支持旧版本 IE 的策略。这个策略就是“移动优先”这个词的来源。
我预计 CSS Grid 将在 2017 在浏览器中被使用,我打赌在实现将来的布局时咱们将使用大量的特征查询。与 JavaScript 相比,它的麻烦要小得多,并且速度要快得多。而且 @supports
能使支持 CSS Grid 的浏览器作有趣的和复杂的东西,同时对不支持的浏览器提供布局选项。
自 2013 年年中以来,功能查询一直存在。随着 Safari 10 即将发布,我相信咱们已经到了将 @supports
添加到工具箱的时候了。
Jen Simmons 是在 Mozilla 的一个设计师,而且是 The Web Ahead 的主持人。她正在研究网络上平面设计的将来,并在全球会议上四处教授 CSS 布局。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、React、前端、后端、产品、设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划。