β

【译】浏览器原生modernizr: CSS @support

携程UED 95 阅读

原文:http://demosthenes.info/blog/964/A-Browser-Native-Modernizr-Using-supports-in-CSS
翻译:叮当当咚当当小胖妞呀

前端开发工程师的心中一直萦绕着这样一个问题:这么写可以吗。判断CSS支持哪些浏览器,在不支持的浏览器中优雅降级,这些工作几乎占用了开发的大部分时间。像Modernizr这样的特性检测工具很大程度上帮助解决了这样的问题,但是不是所有的情况都适用,而且会加载很多我们不需要的Javascript。

理想状态下,我们需要一个原生方法帮助我们检测浏览器中支持的CSS,并让我们直接找到这些特性,其实我们可以通过@supports和Javascript的CSS.support()方法来实现这个目标。在本文中,我会说明一下这个属性的CSS规范,包括不支持浏览器中的Javascript方案。

特性检测语句

作为@规则,@supports的书写方式跟@mediaqueries一样,可以把它想成是一种CSS形式的if声明。例如,我们要检测浏览器是否支持vw单位

@supports ( width: 75vw ) {
/* 支持vw单位浏览器的CSS规则 */
}

注意圆括号中的条件必须以有效CSSproperty: value的形式书写,@supports (vw) { }这样写是无效的。你也可以使用or语句,在检测带有浏览器前缀属性的时候会很有帮助:

@supports ( display: -webkit-flex ) or ( display: -ms-flex ) or ( display: flex )
{
/* 支持flexbox浏览器的代码 */
}

你也可以使用and来添加条件,例如,可以使用以下语句来检测浏览器是否同时支持CSS的currentColorHSL color属性:

@supports ( color: currentColor ) and ( color: hsl(0,50%,30%) {
/* 支持currentColor和HSL浏览器的代码 */
}

再次重申,书写什么CSS代码并不重要,只要代码有效就行。最后——也可能是最没用的——条件:not语句:

@supports not (display: inline-grid) {
/* 不支持CSS grid浏览器的代码 */
}

andornot可以混合使用以应对复杂情况。

支持情况

现在Firefox、Chrome、Android(4.4+)和Opera支持@supports,Safari和IE还不支持,这样会导致一个矛盾:@supports仅在支持的浏览器中才会有效,其他的无效。这句话其实不完全对,我们一会儿会说到。

在不支持的浏览器中使用@supports

我们其实可以在不支持CSS规则或Javascript方法的浏览器中间接使用@supports,我写过一篇关于使用Open Type实现真正的小型大写的文章,其中一条评论提出了使用@supports解决问题的例子:我们不能同时使用font-variant: small-cap和OpenType,这意味着那些不支持OpenType的浏览器会显示小写的文本,这个问题可以使用@supports方法解决,这种解决方案让我想起了我最近写的一篇文章用CSS媒体查询触发Javascript

@font-face {
font-family: Questa Grande;
src: url(Questa_Grande_Regular.otf) ;
}
p { font-family: Questa Grande, sans-serif; font-size: 2rem; }
@supports ( -moz-font-feature-settings: "smcp=1" )
or ( -moz-font-feature-settings: "smcp" )
or ( -ms-font-feature-settings: "smcp" )
or ( -o-font-feature-settings: "smcp" )
or ( -webkit-font-feature-settings: "smcp" )
or ( font-feature-settings:"smcp") {
p:first-of-type:first-line {
-moz-font-feature-settings: "smcp=1";
-moz-font-feature-settings: "smcp";
-ms-font-feature-settings: "smcp";
-o-font-feature-settings: "smcp";
-webkit-font-feature-settings: "smcp";
font-feature-settings:"smcp";
}
body:before { content: 'small-caps'; display: none; }
}

这段代码的意思是:如果浏览器支持OpenType,那么在第一个段落的第一行执行小型大写样式,然后为<body>的伪元素添加small-caps的文本并隐藏。这其实是我们给Javascript的一个“信息”:

var smallcaps = window.getComputedStyle(document.body, ':before' ).content;
if (smallcaps!== "small-caps") {
var css = document.createElement('style');
var styles = 'p:first-of-type:first-line { font-variant: small-caps }';
if (css.styleSheet)
{ css.styleSheet.cssText = styles; }
else {
css.appendChild(document.createTextNode(styles))
}
document.getElementsByTagName("head")[0].appendChild(css);
}

这段脚本会查找隐藏的文本:如果没有找到,脚本会为段落创建一个回退,并应用在<head>标签中,这样在不支持OpenType的浏览器中也能实现首行小型大写了。

效果如下:

small cap

总结

虽然使用@supports还有争议,但在这篇文章中,我展示了让每个浏览器都能使用的方法:你可以在<body>的伪元素里面添加文本让Javascript检测,或者运用多重样式名代表你想要测试的特性,就像Modernizr这样,不过我们使用的是原生Javascript和CSS。

作者:携程UED
携程旅行前端开发团队
原文地址:【译】浏览器原生modernizr: CSS @support, 感谢原作者分享。

发表评论