postcss插件的适配

在一个项目中,一个postcss的插件配置基本如下

module.exports = { 
"plugins": { 
    "postcss-import": {}, 
    "postcss-url": {}, 
    "postcss-aspect-ratio-mini": {}, 
    "postcss-write-svg": { utf8: false }, 
    "postcss-cssnext": {}, 
    "postcss-px-to-viewport": { 
        viewportWidth: 750, 
        viewportHeight: 1334, 
        unitPrecision: 3, 
        viewportUnit: 'vw', 
        selectorBlackList: ['.ignore', '.hairlines'],
        minPixelValue: 1, 
        mediaQuery: false 
        }, 
    "postcss-viewport-units":{}, 
    "cssnano": { 
        preset: "advanced", 
        autoprefixer: false, 
        "postcss-zindex": false 
        } 
    } 
}

接下来简单分析下各个配置文件的作用

postcss-import和postcss-url

postcss-import和postcss-url两个主要是用于处理引入的文件和资源路径的处理以及工作模式。

  • postcss-import就是在一个css中用来@import css文件的
  • postcss-url 是用于css的资源路径的 如果你的项目也使用的是Vue,并且配置了vue-loader,并且配置了相关的参数,那就就具有类似的功能。

autoprefixer

主要用来处理浏览器的私有前缀,这个已经是大家经常使用的一个PostCSS插件了。这里需要提出的是,如果你的项目中使用了postcss-next和cssnano,那么autoprefixer插件可以不引入,而且在postcss-next和cssnano两者中选择其一关闭autoprefixer,因为这两个插件都集成了autoprefixer插件的特性。

postcss-aspect-ratio-mini

主要用来处理元素容器宽高比。在项目当中很多地方会使用img、object或者video,那么这个插件能更好的帮助我们完美处理宽高比的缩放。在实际使用的时候,具有一个默认的结构:

<div aspectratio>
    <div aspectratio-content></div>
</div>

在实际使用的时候,你可以把自定义属性aspectratio和aspectratio-content换成相应的类名,比如:

<div class="aspectratio">
    <div class="aspectratio-content"></div>
</div>

我个人比较喜欢用自定义属性,它和类名所起的作用是同等的。结构定义之后,需要在你的样式文件中添加一个统一的宽度比默认属性:

[aspectratio] {
    position: relative;
}
[aspectratio]::before {
    content: '';
    display: block;
    width: 1px;
    margin-left: -1px;
    height: 0;
}

[aspectratio-content] {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
}

如果我们想要做一个188:246(188是容器宽度,246是容器高度)这样的比例容器,只需要这样使用:

[w-188-246] {
    aspect-ratio: '188:246';
}

有一点需要特别注意:aspect-ratio属性不能和其他属性写在一起,否则编译出来的属性只会留下aspect-ratio的值,比如:

<div aspectratio w-188-246 class="color"></div>

编译前的CSS如下:

[w-188-246] {
    width: 188px;
    background-color: red;
    aspect-ratio: '188:246';
}

编译之后:

[w-188-246]:before {
    padding-top: 130.85106382978725%;
}

主要是因为在插件中做了相应的处理,不在每次调用aspect-ratio时,生成前面指定的默认样式代码,这样代码没那么冗余。所以在使用的时候,需要把width和background-color分开来写:

[w-188-246] {
    width: 188px;
    background-color: red;
}
[w-188-246] {
    aspect-ratio: '188:246';
}

这个时候,编译出来的CSS就正常了:

[w-188-246] {
    width: 25.067vw;
    background-color: red;
}
[w-188-246]:before {
    padding-top: 130.85106382978725%;
}

postcss-write-svg

主要用来处理移动端1px的解决方案。该插件主要使用的是border-image和background配合SVG绘制的矢量图来做1px的相关处理。

postcss-cssnext

其实就是cssnext。该插件可以让我们使用CSS未来的特性,其会对这些特性做相关的兼容性处理。著作权归作者所有。

cssnano

主要用来压缩和清理CSS代码。在Webpack中,cssnano和css-loader捆绑在一起,所以不需要自己加载它。不过你也可以使用postcss-loader显式的使用cssnano。

  • 删除空格和最后一个分号
  • 删除注释
  • 优化字体权重
  • 丢弃重复的样式规则
  • 优化calc()
  • 压缩选择器
  • 减少手写属性
  • 合并规则

postcss-px-to-viewport

两个PostCSS插件主要是用于vw适配方案,算是这次项目中必不可少的PostCSS插件。其中,postcss-px-to-viewport插件主要用来把px单位转换为vw、vh、vmin或者vmax这样的视窗单位,也是vw适配方案的核心插件之一。

在配置中需要配置相关的几个关键参数:

"postcss-px-to-viewport": 
    { 
    viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 
    viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置 
    unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) 
    viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw 
    selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 
    minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值 
    mediaQuery: false // 允许在媒体查询中转换`px` 
    }

postcss-viewport-units

由于浏览器对vw还具有一定的兼容性,其在Android 4.4之下和iOS8以下的版本都存有一定的问题。为了让vw、vh、vmin和vmax这些viewport单位能更好的使用。其兼容方案就是使用viewport的polyfill:Viewport Units Buggyfill。

而在采用Viewport Units Buggyfill的时候,需要手动给使用viewport单位的样式中添加其对应的Hack代码,比如:

.box {
    top: 2vw;
    left: 1vw;

    content: 'viewport-units-buggyfill;top: 2vw;left: 1vw;';
}

如果每一个都这样来做,那么将是灾难性的。幸运的是,可以使用postcss-viewport-units。其主要是给CSS的属性添加content的属性,配合viewport-units-buggyfill库给vw、vh、vmin和vmax做适配的操作。

另一个坑,使用postcss-viewport-units将会给具有content属性的元素造成一定的影响,比如你的项目中使用伪元素::before、::after或者伪类:before、:after之类。那么使用该插件,会自动替换你原来的content内容,为了避免该现象,需要在content的属性值末尾添加!important。

results matching ""

    No results matching ""