CSS 中的前端工程化:预编译器与后处理器

23 篇文章 1 订阅
文章介绍了CSS预编译器如Less的功能,包括变量、嵌套、mixin和函数,提高CSS代码的复用性和组织性。同时,讲解了PostCSS如何通过插件转换CSS,增强代码可读性,处理浏览器前缀,以及实现CSS模块化和错误检查。
摘要由CSDN通过智能技术生成

1 CSS 预编译器

Less

:将类 CSS 语言(Less(.less)、Sass(.scss)、Stylus 等)编译处理成浏览器可解析的真正 CSS。增强了 CSS 代码的复用性,还有嵌套、变量、循环、函数、mixin 等,具有很方便的 UI 组件模块化开发能力。

在 Node.js 环境中使用 Less:

// 比如全局安装 less:
npm install -g less;
// 转换编写好的 less 文件为 CSS
lessc styles.less styles.css

在浏览器环境中使用 Less :

<link rel="stylesheet/less" type="text/css" href="styles.less" />

<script src=​"https://cdn.jsdelivr.net/npm/less@4"​></script>

采用变量定义属性值让属性值更具语义化,@定义变量@{}变量插值,其中选择器中、属性名中、部分片段中:必须使用变量插值。

/* @定义变量 */
@width: 10px;
@height: @width + 10px;
@color: blue;
.heading {
  width: @width;
  height: @height;
  margin: 5px;
  padding: $margin; // 属性可直接作为变量使用
  a {
    color: @color; // white 变量支持提升和作用域嵌套
  }
  @color: white;
}
// 编译后
.heading {
  width: 10px;
  height: 20px;
  margin: 5px;
  padding: 5px;
}
.heading a {
  color: white;
}

/* 选择器中使用变量插值 */
@banner: banner;
.@{banner} {
  font-weight: bold;
}
/* 属性名中使用 */
@color: color;
.widget {
  @{color}: #ffffff;
}
/* 属性值中的部分片段中使用 */
@images: '../images';
.bg-img {
  background: url('@{images}/bg.png');
}
// 编译后
@banner: banner;
.banner {
  font-weight: bold;
}
.widget {
  color: #ffffff;
}
.bg-img {
  background: url('../images/bg.png');
}

混合 mixin,可理解为可复用的样式片段。编译后,mixin 本身是否在 CSS 中输出取决于定义是否带括号。

/* 定义 mixin */
/* 不带括号,该 mixin 定义会输出在编译结果中 */
.my-mixin {
  color: black;
}
/* 带括号,该 mixin 定义不会输出在编译结果中 */
.my-other-mixin() {
  background-color: white;
}
/* 带选择器的 mixin 定义 */
.my-hover-mixin() {
  &:hover {  /* & 符号表示父选择器 */
    border: 1px solid red;
  }
}
/* 命名空间 mixin, 允许堆叠多个 id 或 class 可以减少和其他库 mixin 或用户 mixin 的冲突 */
#bundle {
  .button() {
    display: block;
    &:hover {
      background-color: white;
    }
  }
  /* 允许添加条件形成受保护的命名空间,条件为 true 时才会使用 */
  .minxin() when (@mode=huge) { /* */ }
}
.heading a {
  color: orange;
  #bundle.button();
}
/* mixin 允许使用参数(类型 JavaScript 中的函数), 包括参数默认值、命名参数(引用名称即可,不必按任何特殊顺序)、剩余参数(@rest...)、参数集(@arguments) */
/* 也支持将逗号分隔的列表值传递给单个参数 */
/* mixin 也允许重载 */
/* 在 mixin 调用后使用 !important 关键字会将其 mixin 内定义的所有属性标记为 !important */
.mixin(@color) {
  color: @color;
}
.mixin(@color, @padding: 2) {
  color: @color;
  padding: @padding;
}
.mixin(@color, @padding, @marin: 2, @rest...) {
  color: @color;
  padding: @padding;
  margin: @margin @margin @margin @margin;
}

/* 调用 mixin */
.class {
  /* 调用 mixin 时可选的括号已经被弃用,因此一定要加括号 */
  .my-mixin();
  .my-other-mixin();
}
.button {
  .my-hover-mixin();
}
.class-other {
  #my-library.my-mixin(); /* > 语法已弃用 */
}
.some .selctor div {
  .mixin(#008000) !important;
}

/* 编译后 */
.my-mixin {
  color: black;
}
.class {
  color: black;
  background-color: white;
}
.button:hover{
  border: 1px solid red;
}
.heading a {
  display: block;
  color: orange;
}
.heading a:hover {
  background-color: #ffffff;
}
.some .selctor div {
  color: #008000 !important;
  padding: 2 !important;
}
/* mixin 中递归调用自身即可形成循环 */
.loop(@counter) when (@conter > 0) {
  /* 递归调用自身 */
  .loop(@counter - 1);

  widht: (10px * @counter);
}

.container {
  .loop(5);
}
/*  */
.container {
  width: 10px;
  width: 20px;
  width: 30px;
  width: 40px;
  width: 50px;
}

@media 或 @supports 等 at 规则能以与选择器相同的方式嵌套。编译后,at 规则位于外层,并且与同一规则集中的其他元素的相对顺序保持不变,这称为冒泡。

/* 编译前, at-rule 规则定义在选择器内部,更加统一 */
.component {
  widht: 300px;
  @media (min-width: 768px) {
    width: 600px;
    @media (min-resolution: 192dpi) {
      background-image: url(/img/retina2x.png);
    }
  }
  @media (min-width: 1280px) {
    width: 800px;
  }
}

/* 编译后 */
.component {
  width: 300px;
}
@media (min-width: 768px) {
  .component {
    width: 600px;
  }
}
@media (min-width: 768px) and @media (min-resolution: 192dpi) {
  .component {
    background-image: url(/img/retina2x.png);
  }
}
@media (min-width: 1280px) {
  .component {
    width: 800px;
  }
}

函数(Function):包括多种转换颜色、字符串操作、数学运算、参数检测的函数。

@base: #f04615;
@width: 0.5
.class {
  width: percentage(@width); /* return 50% */
  color: saturate(@base, 5%); /* 增加 5% 的饱和度 */
  background-color: spin(lighten(@base, 25%), 8); /* lighten 亮度增加 25% 并使用 spin 旋转颜色的色调 8 deg, spin 不能直接传入颜色值,需要确保以保留色调的方式调用 */
}

/* 检测参数类型 */
iscolor
isnumber
isstring
iskeyword
isurl
/* 检测参数单位 */
ispixel
ispercentage
isem
isunit

注释(comments):less 支持块注释(即 css 注释:/* */)和行注释(//),由于在编译 less 代码时,行注释不会出现在结果 css 文件中,因此更多推荐在 less 中使用行注释。

2 CSS 后处理器

PostCSS

Postcss 是一个用 JavaScript 工具和插件转换 CSS 代码的工具。通过完整的插件化,Postcss 可以具有以下能力:

  1. 增强代码的可读性:利用从 Can I Use 网站获取的数据为 CSS 规则添加特定厂商的前缀。Autoprefixer 自动获取浏览器的流行度和能够支持的属性,并根据这些数据帮你自动为 CSS 规则添加前缀。
  2. 将未来的 CSS 特性带到今天:PostCSS Preset Env 帮你将最新的 CSS 语法转换成大多数浏览器都能理解的语法,并根据你的目标浏览器或运行时环境来确定你需要的 polyfills,此功能基于 cssdb 实现。
  3. 终结全局 CSS:CSS 模块使得永远不用担心命名太大众化而造成冲突,只要用最有意义的名字就行了。
  4. 避免 CSS 代码中的错误:通过使用 stylelint 强化一致性约束并避免样式表中的错误。

PostCSS,通常被视为在完成的样式表中根据 CSS 规范处理 CSS,让其更有效。它的初始功能只有源文件生成 AST 树,AST 树生成新文件,借助插件机制实现定制化的功能,目前最常做的是给CSS属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。

比如,插件 Autoprefixer 支持自动从 Can I Use 网站获取浏览器的流行度和能够支持的属性,并根据这些数据自动为 CSS 规则添加特定厂商前缀。实现简易版 Autoprefixer:  

import postcss from 'postcss';
// 假设这是从 Can I Use 网站获取的浏览器兼容数据
const mockPrefixerConfig = {
  // 需要添加厂商前缀的属性名
  key: ['transform', 'opacity'],
  // 需要添加厂商前缀的属性值
  values: [{
    name: display,
    preValue: 'flex',
    newValue: ['-webkit-box', '-webkit-flex', '-moz-box', '-ms-flexbox']
  }]
}

const myPrefixPlugin = postcss.plugin('myPrefixPlugin', (opt) => {
  return (ast) => {
    opt = opt || {};
    ast.each((node) => {
      // node 是每一个 selector 选择器节点
      node.each((declaration => {
        // declaration 是当前 selector 选择器节点内的每一条规则声明,即属性:值
        const { prop, value, cloneBefore } = declaration;
        if (mockPrefixerConfig.key.includes(prop)) {
          // 克隆规则声明节点并将生成的节点插入到当前节点之前
          cloneBefore({ prop: `-webkit-${prop}`;
        }
        const item = mockPrefixerConfig.values.find((value) => value.name === prop);
        item && item.preValue === value && item.newValue.forEach((newVal) => {
          // 克隆规则声明并将生成的克隆节点插入到当前节点之前
          cloneBefore({ value: newVal });
        });
      }
    }
  }
});

export default myPrefixPlugin;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的猫96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值