首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 PostCSS 进行 CSS 处理(2)

使用 PostCSS 进行 CSS 处理(2)

常用插件AutoprefixerAutoprefixer 是一个流行的 PostCSS 插件,其作用是为 CSS 中的属性添加浏览器特定的前缀。由于 CSS 规范的制定和完善一般需要花费比较长的时间,浏览器厂商在实现某个 CSS 新功能时,会使用特定的浏览器前缀来作为正式规范版本之前的实验性实现。比如 Webkit 核心的浏览器使用-webkit-,微软的 IE 使用-ms-。为了兼容不同浏览器的不同版本,在编写 CSS 样式规则声明时通常需要添加额外的带前缀的属性。这是一项繁琐而无趣的工作。Autoprefixer 可以自动的完成这项工作。Autoprefixer 可以根据需要指定支持的浏览器类型和版本,自动添加所需的带前缀的属性声明。开发人员在编写 CSS 时只需要使用 CSS 规范中的标准属性名即可。
  中给出了使用 CSS 弹性盒模型的 display 属性声明。
清单 4. 标准的 CSS 弹性盒模型的 display 属性声明
1
2
3
#content {
display: flex;
}




在经过 Autoprefixer 处理之后得到的 CSS 如  所示。
清单 5. 使用 Autoprefixer 处理之后的 CSS
1
2
3
4
5
6
#content {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}




Autoprefixer 使用 Can I Use 网站提供的数据来确定所要添加的不同浏览器的前缀。随着浏览器版本的升级,浏览器在新版本中可能已经提供了对标准属性的支持,从而不再需要添加额外的前缀。Autoprefixer 可以配置需要支持的浏览器。如“last 2 versions”表示主流浏览器的最近两个版本,“ie 6-8”表示 IE 6 到 8,“> 1%”表示全球使用率大于 1%的浏览器版本。  中给出了配置 Autoprefixer 插件的示例。
清单 6. 配置 Autoprefixer 插件
1
2
3
require('autoprefixer')({
browsers: ['last 2 versions']
})




Autoprefixer 除了添加所需要的属性名称前缀之外,还可以移除 CSS 代码中冗余的属性名称前缀。遗留 CSS 代码中可能包含由开发人员手动添加的旧版本的浏览器所支持的带前缀的属性名称。Autoprefixer 默认情况下会移除这些冗余的前缀。可以通过配置对象中的 remove 属性来配置该行为。
cssnextcssnext 插件允许开发人员在当前的项目中使用 CSS 将来版本中可能会加入的新特性。cssnext 负责把这些新特性转译成当前浏览器中可以使用的语法。从实现角度来说,cssnext 是一系列与 CSS 将来版本相关的 PostCSS 插件的组合。比如,cssnext 中已经包含了对 Autoprefixer 的使用,因此使用了 cssnext 就不再需要使用 Autoprefixer。
自定义属性和变量
CSS 的层叠变量的自定义属性规范(CSS Custom Properties for Cascading Variables)允许在 CSS 中定义属性并在样式规则中作为变量来使用它们。自定义属性的名称以“--”开头。当声明了自定义属性之后,可以在样式规则中使用“var()”函数来引用,如  所示。
清单 7. CSS 自定义属性和变量
1
2
3
4
5
6
7
:root {
--text-color: black;
}

body {
color: var(--text-color);
}




在经过 cssnext 转换之后的 CSS 代码如  所示。
清单 8. 转换之后的 CSS 代码
1
2
3
4
5
body {
color: black;
}

自定义选择器




CSS 扩展规范(CSS Extensions)中允许创建自定义选择器,比如可以对所有的标题元素(h1 到 h6)创建一个自定义选择器并应用样式。通过“@custom-selector”来定义自定义选择器。在  中,“--heading”是自定义选择器的名称,其等同于选择器声明“h1, h2, h3, h4, h5, h6”。
清单 9. 自定义选择器
1
2
3
4
5
@custom-selector :--heading h1, h2, h3, h4, h5, h6;

:--heading {
font-weight: bold;
}




经过 cssnext 处理之后的 CSS 如  所示。
清单 10. 转换之后的 CSS 代码
1
2
3
4
5
6
7
8
9
10
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
}

样式规则嵌套




样式规则嵌套是一个非常实用的功能,可以减少重复的选择器声明。这也是 SASS 和 LESS 等 CSS 预处理器流行的一个重要原因。CSS 嵌套模块规范(CSS Nesting Module)中定义了标准的样式规则嵌套方式。可以通过 cssnext 把标准的样式嵌套格式转换成当前的格式。CSS 嵌套规范中定义了两种嵌套方式:第一种方式要求嵌套的样式声明使用“&”作为前缀,“&”只能作为声明的起始位置;第二种方式的样式声明使用“@nest”作为前缀,并且“&”可以出现在任意位置。  中给出了两种不同声明方式的示例。
清单 11. 样式规则嵌套
1
2
3
4
5
6
7
8
9
.message {
font-weight: normal;
& .header {
   font-weight: bold;
}
  @nest .body & {
   color: black;
}
}




经过 cssnext 转换之后的 CSS 代码如  所示。
清单 12. 转换之后的 CSS 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
.message {
font-weight: normal
}

.message .header {
font-weight: bold;
}

.body .message {
color: black;
}

CSS 模块化




在编写 CSS 代码时会遇到的一个很重要的问题是 CSS 代码的组织方式。当项目中包含的 CSS 样式非常多时,该问题尤其突出。这主要是由于不同 CSS 文件中的样式声明可能产生名称冲突。现在的 Web 开发大多采用组件化的组织方式,即把应用划分成多个不同的组件。每个组件都可以有自己的 CSS 样式声明。比如,两个组件的 CSS 中可能都定义了对于 CSS 类 title 的样式规则。当这两个组件被放在同一个页面上时,冲突的 CSS 类名称可能造成样式的错乱。对于此类 CSS 类名冲突问题,一般的做法是避免全局名称空间中的样式声明,而是每个组件有自己的名称空间。BEM 通过特殊的命名 CSS 类名的方式来解决名称冲突的问题。两个不同组件中的标题的 CSS 类名可能为 component1__title 和 component2__title。
CSS 模块(CSS modules)并不要求使用 BEM 那样复杂的命名规范。每个组件可以自由选择最合适的简单 CSS 类名。组件的 CSS 类名在使用时会被转换成带唯一标识符的形式。这样就避免了名称冲突。在组件开发中可以继续使用简单的 CSS 类名,而不用担心名称冲突问题。  中给出了使用 CSS 模块规范的 CSS 代码。样式规则之前的“:global”表示这是一个全局样式声明。其他的样式声明是局部的。
清单 13. 使用 CSS 模块规范的 CSS 代码
1
2
3
4
5
6
7
:global .title {
font-size: 20px;
}

.content {
font-weight: bold;
}




经过转换之后的 CSS 样式声明如  所示。全局的 CSS 类名 title 保存不变,局部的 CSS 类名 content 被转换成_content_6xmce_5。这样就确保了不会与其他组件中名称为 content 的类名冲突。
清单 14. 转换之后的 CSS 代码
1
2
3
4
5
6
7
.title {
font-size: 20px;
}

._content_6xmce_5 {
font-weight: bold;
}




由于在组件的 HTML 代码中引用的 CSS 类名和最终生成的类名并不相同,因此需要一个中间的过程来进行类名的转换。对于 React 来说,可以使用 react-css-modules 插件;在其他情况下,可以使用 PostHTML 对 HTML 进行处理。postcss-modules 插件把 CSS 模块中的 CSS 类名的对应关系保存在一个 JavaScript 对象中,可以被 PostHTML 中的 posthtml-css-modules 插件来使用。
在  中,在使用 postcss-modules 插件时提供了一个方法 getJSON。当 CSS 模块的转换完成时,该方法会被调用。该方法的参数 json 参数表示的是转换结果的 JavaScript 对象。该对象被以 JavaScript 文件的形式保存到 cssModules 目录下,并添加了模块导出的逻辑。
清单 15. 保存 CSS 模块的输出文件
1
2
3
4
5
6
7
8
require('postcss-modules')({
   getJSON: function(cssFileName, json) {
     var cssName = path.basename(cssFileName, '.css');
     var jsonFileName = path.resolve(dist, 'cssModules', cssName + '.js');
     mkdirp.sync(path.dirname(jsonFileName));
     fs.writeFileSync(jsonFileName, "module.exports = " + JSON.stringify(json) + ";");
   }
})




  中给出了使用 Gulp 的 gulp-posthtml 来处理 HTML 文件的任务。posthtml-css-modules 可以处理一个目录下的多个 CSS 模块输出文件。
清单 16. 使用 PostHTML 处理 HTML 里支持 CSS 模块
1
2
3
4
5
6
gulp.task('posthtml', function() {
var posthtml = require('gulp-posthtml');
return gulp.src('app/**/*.html')
   .pipe(posthtml([ require('posthtml-css-modules')(path.join(dist, 'cssModules')) ]))
   .pipe(gulp.dest('dist/'));
});




在 HTML 文件中使用“css-module”属性来指定对应的 CSS 类名。在  中,名称“header.content”的 header 表示的是 CSS 文件名,而 content 是该文件中定义的 CSS 类名。
清单 17. 使用 CSS 模块的 HTML 文件
1
<div css-module="header.content">Hello world</div>




在经过处理之后,得到的 HTML 内容如  所示。
清单 18. 转换之后的 HTML 文件
1
2
3
<div class="_content_6xmce_5">Hello world</div>

资源文件处理




在 CSS 中经常会需要引用外部资源,如图片和字体等。在 CSS 代码中处理这些资源时会遇到一些常见的问题,比如图片的路径问题,内联图片内容,生成图片 Sprites 等。对于这些问题,都有专门的 PostCSS 插件来提供所需的功能。
postcss-assets 插件用来处理图片和 SVG。在 CSS 声明中引用图片时,可以使用 resolve 加上图片路径的形式,如“resolve(‘logo.png’)”。在插件处理时,会按照一定的顺序在指定的目录中查找该文件,如果找到,会用图片的真实路径来替换。可以通过选项 loadPaths 来指定查找的路径,basePath 来指定项目的根目录。在 CSS 声明中,可以使用 width、height 和 size 方法来获取到图片的宽度、高度和尺寸。当需要内联一个图片时,可以使用 inline 方法。inline 会把图片转换成 Base64 编码的 data url 的格式,这样可以减少对图片的 HTTP 请求。  给出了使用示例。
清单 19. Postcss-assets 插件使用示例
1
2
3
require('postcss-assets')({
   loadPaths: ['assets/images']
})




  中给出了使用 resolve 的 CSS 样式声明。
清单 20. 使用 resolve 的 CSS 样式声明
1
2
3
.logo {
background-image: resolve('logo.png');
}




  中给出了 cssnext 处理之后的 CSS 代码。
清单 21. 转换之后的 CSS 代码
1
2
3
4
5
.logo {
background-image: url('/assets/images/logo.png');
}

其他插件




还有其他实用的 PostCSS 插件可以在开发中使用。如 postcss-stylelint 用来检查 CSS 中可能存在的格式问题。cssnano 用来压缩 CSS 代码。postcss-font-magician 用来生成 CSS 中的 @font-face 声明。precss 允许在 CSS 中使用类似 SASS 的语法。
返回列表