PostCSS深入学习: 跨浏览器兼容性

在前面一系列的PostCSS教程中我们学习了PostCSS一些基础知识。接下来准备继续使用PostCSS生成样式表,而且采用不同类型的插件用于不同的目的。

在这篇教程中我们使用PostCSS创建一个跨浏览器兼容性的样式表。我们将要做的:

  • 有前缀的自动添加前缀

  • 添加一系列的IE版本,回退到IE8、IE9和IE10

  • 为没有支持的属性添加will-change属性

那我们开始吧。

设置您的项目

你需要做的第一件事情就是使用GulpGrunt设置您的项目。如果你没有一个完美的项目模板,我建议你使用Gulp,可以使用较少的代码来达到相同的目的。

你可以阅读前面有关于Gulp或Grunt创建PostCSS项目的教程:

如果你不想从头开始手动设置您的项目,你可以下载本教程中提供的源码附件,提取Gulp或Grunt项目到一个空的文件夹中。

然后在命令终端运行:npm install

安装插件

现在你已经准备好了一个空的Gulp(或Grunt)+PostCSS的项目,我们需要安装本教程中需要使用到的插件。

我们要安装一些插件,所以在这里不会像在《PostCSS深入学习:Gulp设置》和《PostCSS深入学习:Grunt配置》中介绍的那样,一个一个安装。而是使用一个命令一次性安装本教程中需要用到的插件。

不管你是使用Gulp还是Grunt,在你项目的目录下运行下面的命令:

npm install autoprefixer postcss-color-rgba-fallback postcss-opacity postcss-pseudoelements postcss-vmin pixrem postcss-will-change --save-dev

现在已经安装好插件了,下面我们继续将这些插件加载到您的项目中。

通过Gulp加载插件

如果你使用的是Gulp,在你的gulpfile.js加载这些变量:

var autoprefixer = require('autoprefixer');var color_rgba_fallback = require('postcss-color-rgba-fallback');var opacity = require('postcss-opacity');var pseudoelements = require('postcss-pseudoelements');var vmin = require('postcss-vmin');var pixrem = require('pixrem');var will_change = require('postcss-will-change');

并且将这些变量的名称添加到你的processors数组中:

var processors = [
    will_change,
    autoprefixer,
    color_rgba_fallback,
    opacity,
    pseudoelements,
    vmin,
    pixrem
];

做一个快速测试,在命令终端运行gulp css,检查style.css文件有没有放到dest文件夹中。

通过Grunt加载插件

如果你使用Grunt,更新你的processors对象,并且给对象嵌套options,如下所示:

processors: [  require('postcss-will-change')(),  require('autoprefixer')(),  require('postcss-color-rgba-fallback')(),  require('postcss-opacity')(),  require('postcss-pseudoelements')(),  require('postcss-vmin')(),  require('pixrem')()
]

在命令终端运行grunt postcss命令,做一个快速的检测,并且检查你项目中的dest文件夹中有没有一个新的style.css文件。

到这里的话,你已经安装好了本教程中所需要的PostCSS插件。接你来继续看如何使用这些插件来解决你的样式表实现跨浏览器的兼容性。

自动添加浏览器前缀

介绍跨浏览器兼容的一些措施,我们为此指定一些特殊的用例是很有必要的。自动化需要的属性添加浏览器厂商的私有前缀,我建议应该在每个完成的项目之后,通过@Andrey Sitnik的Autoprefixer插件来处理。

自己很难监测哪些属性需要添加浏览器厂商的私有前缀。在你的项目中使用Autoprefixer作为其中的一部分,它会要看CanIUse.com数据去检测你的代码,然后根据需要添加浏览器的前缀。这样你就无需思考那些事情,可以专心的写自己代码。

让我们来做一个Autoprefixer的测试示例。将下面的动画和flexbox代码添加到你项目的src/style.css文件中:

@keyframes animationExample {    from {        width: 0;
    }
    to {        width: 100%;
    }}.animateThis {    animation: animationExample 2s;
    display: flex;}

运行gulp css或者grunt postcss编译你的文件,接下来你会发现在你项目中dest/style.css文件已添加了浏览器的前缀:

@-webkit-keyframes animationExample {    from {        width: 0;
    }
    to {        width: 100%;
    }}@keyframes animationExample {    from {        width: 0;
    }
    to {        width: 100%;
    }}.animateThis {    -webkit-animation: animationExample 2s;
            animation: animationExample 2s;
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;}

正如你所看到的一样,根据CanIUse.comanimationflexbox提供的数据,自动添加了前缀。

指定支持的浏览器版本

Autoprefixer使用Browserlist来确定哪些浏览器版本将得到支持。默认情况下根据需要提供前缀的支持:

  • **> 1%**: 全球有超过1%的人使用的浏览器

  • last 2 versions: 根据CanIUse.com追踪的最后两个版本的所有浏览器

  • Firefox ESR: 最新的Firefox版本

  • Opera 12.1: Opera 12.1版本

上面的示例中,我们通过Autoprefixer的默认设置进行的编译,也就是说支持IE10和Safari8,所以animation前面需要添加-webkit-前缀,而flexbox需要-ms--webkit-前缀。

如果你设置Browserlist配置只支持IE11+和Safari9,那么IE11和Safari9不需要这些前缀。

试试在你的gulpfile.jsgruntfile.js文件中通过browsers设置Autoprefixer的Browserlsit:

// In the Gulpfile 'processors' array:autoprefixer({browsers:'safari >= 9, ie >= 11'}),// In the Gruntfile 'processors' array:require('autoprefixer')({ browsers: ['safari >= 9, ie >= 11'] }),

如果你看到编译后的CSS和编译前的CSS没有区别。这是因为没有支持Safari8或IE10浏览请求,所以没有前缀。

扩展阅读

will-change属性添加回退

will-change属性用于提前让浏览器知道某些元素设计的动画。这允许浏览器优化呈现动画渲染过程,防止延误和闪烁。然而,目前IE/Edge,Safari和Opera Mini还不支持这个属性。

@Andrey Sitnik开发的postcss-will-change插件,添加一个回退,这将有助于这些浏览器渲染做得更好,即使浏览器不支持will-change属性,也不会影响效率。它通过添加backface-visibility属性,触发GPU处理器。

例如,在你项目的src/style.css文件中加入下面的代码:

.thisWillChange {    will-change: transform;}

编译之后,在你项目的dest/style.css文件中可以看到下面的代码:

.thisWillChange {    backface-visibility: hidden;
    will-change: transform;}

注意:这个插件在gulpfile.js(或grunfile.js)文件中应该在Autoprefixer之前加载。这是允许Autoprefixer插件给backface-visibility添加浏览器前缀。如下所示:

/* Fallback with vendor prefixes */.thisWillChange {    -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
    will-change: transform;}

扩展阅读

给IE老版本添加降级属性

我们应该感谢微软公司提高浏览器版本,更主要的是公司领导支持放弃IE老版本,我们也可以逐渐不必考虑IE老版本,以及降级的解决方案。微软公司本身在2016年也不再对IE8进行支持。Bootstrap4最近也不支持IE8。Google在2012年停止了对IE8的支持,而且在2013年对IE9的支持也慢慢降在降低。

话说,结束不结束对IE老版本的支持必须根据项目评估的基础上,如果您的目标用户使用IE老版本占较高比率,你可能别无选择,只能尽力支持他们。如果是这种情况之下,以下插件可以帮助你在处理IE老版本兼容性上减少一些痛苦。

rgba()颜色创建降级方案

IE8不支持rgba()颜色,所以@Guillaume Demesy的postcss-color-rgba-fallback插件添加了一个十六进制颜色作为降级处理。

例如,在你项目的src/style.css文件中添加下面的代码:

.rgbaFallback {    background: rgba(0,0,0,0.5);}

编译之后,在你项目的dest/style.css文件中可以看到下面的代码:

.rgbaFallback {    background: #000000;
    background: rgba(0,0,0,0.5);}

扩展阅读

opacity提供降级方案

IE8也不支持opacity属性,所以@Vincent De Oliveira提供了postcss-opacity插件,给IE浏览器添加滤镜属性,作为降级处理。

在你的样式源码中添加:

.opacityFallback {    opacity: 0.5;}

编辑出来的样式文件,会添加一个-ms-filter属性作为opacity的降级处理:

.opacityFallback {    opacity: 0.5;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";}

扩展阅读

将伪元素的::转换为:

例如.element::before使用两个冒号::表示为伪元素,而.element:hover使用一个冒号:表示为伪类。实践中表明使用::主要是用来区分伪类。

然而,在IE8中仅支持一个冒号:,并不支持::的伪元素。通过@Sven Tschui的postcss-pseudoelements插件,可以得到最好的实践,插件能自将的将::转换为:

在你的代码中添加包含::的代码:

.pseudo-element::before {    content: '';}

编译出来的代码中你看到的只有::

.pseudo-element:before {    content: '';}

通过实践,使用这个插件是最佳编码实践,当然也可以不使用插件,使用CSS也有适当的语法降级处理IE8。

扩展阅读

使用vmvmin做降级处理

IE9中并不支持viewport相对单位vmin,但可以使用vm作为等效的单位。如果你为了让IE9支持vmin,可以使用@Vincent De Oliveira的postcss-vmin插件,对IE9做降级处理。

在你项目的src/style.css文件中添加下面的代码:

.vmFallback {    width: 50vmin;}

编译出来的代码,会添加vm单位作为降级处理:

.vmFallback {    width: 50vm;
    width: 50vmin;}

扩展阅读

rem添加px作为降级处理

IE8一直都不支持rem单位,而且在IE9和IE10中他们都不支持伪元素和font的缩写。使用@Vincent De Oliveira和@Rob Wierzbowski的node-pixrem插件,可以自动为rem添加px单位作为降级处理。

在你的样式表中添加下面的代码:

.remFallback {    height: 10rem;
    font: 2rem Arial;}.remFallback::before {    content: '';
    line-height: 1rem;}

重新编译你的样式,你在样式文件中会看到添加px作为降级处理: