postcss 插件开发:批量自动化移动端1px解决方案

前言

移动端web项目愈来愈多,设计师对于UI的要求也愈来愈高,好比1px 的边框。在高清屏下,移动端的1px 会很粗。现现在已经有许多优秀的1px解决方案css

这里总结几种较好用的解决方案html

  1. 伪元素

优势: 由于伪元素::after或::before是独立于当前元素,能够单独对其缩放而不影响元素自己的缩放前端

伪元素大多数浏览器默认单引号也可使用,
和伪类同样形式,并且单引号兼容性(ie)更好些
复制代码

缺点:须要额外编写伪元素样式。对于我这种懒癌往期用户来讲,真的头疼;vue

  1. less封装

优势:使用 less 对公共代码(方案一)封装,同时增长媒体查询分别对不一样 DPR 的设备,进行不一样的缩放node

缺点:须要调用封装好的less函数。对于不懂less的同窗们来讲,可能须要额外去学习下less,若是项目没使用预处理(less,sass,stylus),还须要额外引入。react

那么,有没有办法我既不额外引入第三方预处理器,也无需额外写一堆伪元素样式? ok,既然你看到这里了,那么就继续加油,立刻带你了解一下基于postcss的解决方案。git

目录

  1. 什么是postcss?
  2. 如何在项目中使用postcss和postcss相关插件?
  3. postcss插件开发流程和规范
  4. postcss-border-1px开发、npm包和github

若是你只是想直接使用该插件或者想看代码,你能够直接跳到4。github

什么是postcss?

多时候第一次在网上查询 PostCSS 概念的时候,你们都解释成一个后处理器的概念,其实我的以为这些概念不重要,更为重要的有如下几点:web

它本质上是一个什么东西vue-cli

PostCSS 能够直观的理解为:它就是一个平台、平台、平台,重要的事情来三遍比较爽,哈哈!

什么说它是一个平台呢?由于咱们直接用它,感受不能干什么事情,可是若是让一些插件在它上面跑,那么将会很强大。

PostCSS 提供了一个解析器,它可以将 CSS 解析成抽象语法树(AST)。

也就是说,postcss只是帮咱们把css解析成一个ast,除此以外,它什么都没作。因此说,PostCSS 它须要一个插件系统才可以发挥做用。咱们能够经过“插件”来传递AST,而后再把AST转换成一个串,最后再输出到目标文件中去。固然,这里是有API能够用,这里先不讲,省得晕了。

关于poscss详细的介绍,能够看这里。

如何在项目中使用postcss?和postcss相关插件

有如下几个步骤

  1. 在loader中配置postcss

前面说过了,postcss会将css文件转换成AST,因此咱们须要为css文件配置postcss-loader,vue-cli3及以上版本都默认配置了postcss,因此你无需再配置。若是你是react版本,请自行google如何配置。

这里有个注意的地方

若是你的项目配置的less sass之类的,须要将less-loader或者sass-loader配置在postcss下面。由于postcss只接受css,没法编译less和sass以及其余语法。 这里以less为例子

{
  test: /\.css$|\.less$/,
  use:
  [
    'style-loader',
    'css-loader',
    'postcss-loader',
    'less-loader'
  ]
}
复制代码
  1. 新增postcss.config.js文件
const border1px = require('postcss-botder-1px')
module.exports = {
plugin:[
  border1px({option}) // option是插件的参数
]
}
复制代码

自此,就完成了插件的使用。在项目中,你能够正常写border

border:1px solid red;
复制代码

postcss插件开发流程和规范

postcss开发规范
  1. 用postcss-前缀清除名称。
  2. 一个插件只作一件事情,也就是单一职责。
  3. 经过 postcss.plugin 来建立你的插件
 module.exports = postcss.plugin('plugin-name', opts => {
  return (root, result) => {
    // Plugin code
  }
})
复制代码
  1. 只使用postcss提供的公共的api来编写 PostCSS插件不得依赖未记录的属性或方法,postcss提供可不少很是好用的 api

想要了解更多的插件开发规范,点这里。

postcss开发流程
1. 了解postcss解析的ast。

例子:

要解析的css代码:

.demo{
  border:1px solid red;
}
复制代码

解析后的ast:

{
  "raws": {
    "semicolon": false,
    "after": ""
  },
  "type": "root",
  "nodes": [
    {
      "raws": {
        "before": "",
        "left": "",
        "right": "\n "
      },
      "type": "comment",
      "source": {
        "start": {
          "line": 1,
          "column": 1
        },
        "input": {
          "css": "/**\n * Paste or drop some CSS here and explore\n * the syntax tree created by chosen parser.\n * Enjoy!\n */\n\n.demo{\n  border:1px solid red;\n}",
          "hasBOM": false,
          "id": "<input css 31>"
        },
        "end": {
          "line": 5,
          "column": 3
        }
      },
      "text": "*\n * Paste or drop some CSS here and explore\n * the syntax tree created by chosen parser.\n * Enjoy!"
    },
    {
      "raws": {
        "before": "\n\n",
        "between": "",
        "semicolon": true,
        "after": "\n"
      },
      "type": "rule",
      "nodes": [
        {
          "raws": {
            "before": "\n  ",
            "between": ":"
          },
          "type": "decl",
          "source": {
            "start": {
              "line": 8,
              "column": 3
            },
            "input": {
              "css": "/**\n * Paste or drop some CSS here and explore\n * the syntax tree created by chosen parser.\n * Enjoy!\n */\n\n.demo{\n  border:1px solid red;\n}",
              "hasBOM": false,
              "id": "<input css 31>"
            },
            "end": {
              "line": 8,
              "column": 23
            }
          },
          "prop": "border",
          "value": "1px solid red"
        }
      ],
      "source": {
        "start": {
          "line": 7,
          "column": 1
        },
        "input": {
          "css": "/**\n * Paste or drop some CSS here and explore\n * the syntax tree created by chosen parser.\n * Enjoy!\n */\n\n.demo{\n  border:1px solid red;\n}",
          "hasBOM": false,
          "id": "<input css 31>"
        },
        "end": {
          "line": 9,
          "column": 1
        }
      },
      "selector": ".demo"
    }
  ],
  "source": {
    "input": {
      "css": "/**\n * Paste or drop some CSS here and explore\n * the syntax tree created by chosen parser.\n * Enjoy!\n */\n\n.demo{\n  border:1px solid red;\n}",
      "hasBOM": false,
      "id": "<input css 31>"
    },
    "start": {
      "line": 1,
      "column": 1
    }
  }
}
复制代码

是否是感受看的晕头转向?别怕!经过打印,你将会看到树型结构的Js对象是一个名为Root的构造函数,而起树型结构的nodes节点下还有Commont,AtRule,Rule构造函数。

  • Root: PostCss处理过的Css,整个处理过程基本上都在围绕着Root,Commont,AtRule,Rule都是它的子节点。
  • Commont: Css中的注释信息,注释的内容在Commont.text下。
  • AtRule: 为带@标识的部分,name为标识名称,params为标识参数。nodes为内部包含的其余子节点,能够是Commont,AtRule,Rule,这让咱们能够自定义更多的规则
  • Rule: 选择器样式部分,一个选择器表明一个Rule,选择器对应的样式列表nodes为Declaration构造函数
  • Declaration: 为Css样式属性,prop为样式属性,value为样式值。可给Rule手动添加样式属性,也能够修改prop,value。
2. 如何调试插件?

postcss插件也能够在node环境中单独运行。

其中,index.js文件就是你编写的插件入口

// 本地测试文件,若是要执行,须要手动建立  /demo/ccs.css
const postcss = require('postcss')
const process = require('process')
const fs = require('fs')
// index.js文件就是你编写的插件入口
const borderFill = require('./index.js')
fs.readFile('./demo/ccs.css', (err, css) => {
  postcss((borderFill)({ ratio: 100, replace: false }))
    .process(css, { from: './demo/css.css', to: './dist/css.css' })
    .then(result => {
      fs.writeFile('./dist/css.css', result.css, () => true)
      if (result.map) {
        fs.writeFile('./dist/css.map', result.map, () => true)
      }
    })
})
复制代码

这样,你就能够在一个本身搭建的简易的环境中测试你编写的postcss插件了。

3. 如何编写插件?

上文中,咱们对Css处理后生成的Root以及其节点下的Commont,AtRule,Rule, Declaration有了基本的认识,那么咱们是如何得到Root,又将拿这些构造函数作些什么呢。

carbon (1).png

总结以下:

  • 咱们要重点关注对象 Root,Commont,AtRule,Rule, Declaration,Result;

  • 遍历这些对象的方法,在上文提到的api文档中也有详细介绍。

walkCommonts,walkAtRules,walkRules,walkDels;

  • 遍历完后,咱们匹配到对应的节点后,就须要对节点进行操做,有如下api: append、clone、remove、after、before、insert

postcss-border-1px开发

npm包

npm i postcss-border-1px --s -d
复制代码

github:点这里。

1.目录。

建立postcss-border-1px 项目

插件思路: 主要是经过遍历css选择器,检测border属性,若是有,就为该选择器新增一个伪元素,并添加伪元素样式。

carbon.png

补充:

欢迎关注公众号:前端开发指南

本文使用 mdnice 排版

相关文章
相关标签/搜索