PostCSS学习笔记
由于CSS语言本身的表达能力较差,Web开发人员常常使用SASS、LESS之类的CSS预处理器语言来编写样式,然后再编译为普通的CSS代码。
PostCSS是一个类似的、较晚出现的CSS处理器,它基于JavaScript语言编写。PostCSS使用插件式的架构,而不是像以前的CSS预处理器那样内置所有特性。目前PostCSS的插件数量已经有数百个。
尽管名字中带有Post,PostCSS并不是所谓后处理器。它可以执行其它预处理器能够完成的任务。PostCSS本身只做两件事情:
- 将输入代码转换为抽象语法树(AST)
- 调用插件处理AST
PostCSS依赖于插件完成实际的工作,例如Lint、变量和混入的支持、未来CSS特性支持(transpile)、内联图片,等等。本节列出常用的插件。
插件 | 说明 |
postcss-use |
允许你在CSS中明确声明使用PostCSS特性,这样可以仅针对某些文件使用PostCSS |
postcss-modules | 可以让你在任何地方使用CSS Modules——自动进行CSS选择器的命名隔离,不仅仅限于客户端 |
react-css-modules | 针对React扩展CSS Modules |
postcss-autoreset | 条件式的自动重置 |
postcss-initial | 支持 all: initial 规则,以便重置所有继承得到的样式 |
cq-prolyfill | 添加容器查询(container query)支持,允许根据父元素的宽度来决定样式 |
插件 | 说明 |
autoprefixer | 自动添加厂商相关的规则前缀 |
postcss-cssnext | 支持未来的CSS特性 |
插件 | 说明 |
precss |
提供SASS风格的特性,例如变量、嵌套、混入 |
postcss-sorting | 对规则的内容进行排序 |
postcss-utilities | 包含很多常用的助手工具 |
short | 支持某些属性简写 |
插件 | 说明 |
postcss-assets | 管理资产,把样式表和环境改变隔离。可以自动寻找图片的URL、自动生成图片的尺寸 |
postcss-sprites | 生成图片sprites,自动合并多张小图片 |
font-magician | 生成CSS中所有需要的@font-face规则 |
postcss-inline-svg | 支持内联SVG图片并设置样式 |
postcss-write-svg | 支持在CSS中直接写入简单的SVG |
PostCSS可以转换基于任何语法的样式,不仅仅是CSS
插件 | 说明 |
sugarss | 类似于SASS的基于缩进的语法 |
postcss-scss | 与SCSS语言一起工作,但是不进行SCSS编译 |
postcss-less | 与LESS语言一起工作,但是不进行LESS编译 |
postcss-less-engine | 与LESS语言一起工作,并且把LESS编译为CSS |
postcss-js |
支持在JS中编写样式,或者把转换React内联样式、Radium、JSS |
postcss-safe-parser | 查找并修复CSS语法错误 |
插件 | 说明 |
cssnano | 模块化的CSS压缩器 |
lost | 基于calc()的特性丰富的网格系统 |
基于postcss-loader:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module.exports = { module: { loaders: [ { test: /\.css$/, // 需要在style、css等加载器之前执行 loader: "style-loader!css-loader!postcss-loader" } ] }, postcss: function () { // 列出启用的PostCSS插件 return [ require( 'autoprefixer' ), require( 'precss' ) ]; } } |
1 |
postcss --use autoprefixer -c options.json -o main.css css/*.css |
你需要安装PostCSS support插件,以获得以下特性:
- 自动识别.pcss文件
- 支持PostCSS语法高亮
- 智能的代码完成
- 可配置的代码样式和自动格式化
- 代码导航支持
- 对自定义选择器、自定义媒体查询的支持
如果要对任意.css文件启用PostCSS支持,你可以在Preferences ⇨ Languages & Frameworks ⇨ Stylesheets ⇨ Dialects 把方言切换为PostCSS。
这是一个必备的插件,可以让你脱离编写厂商特定的规则前缀的苦海。启用该插件后,如果需要编写弹性和子布局,你仅需要:
1 2 3 |
#content { display: flex; } |
该插件会将其转换为:
1 2 3 4 5 6 |
#content { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } |
你可以配置需要支持的浏览器:
1 2 3 4 5 6 |
require( 'autoprefixer' )( { // 仅仅支持支持主流浏览器的最近两个版本 browsers: [ 'last 2 versions' ] // ie 6-8 表示支持IE6-8 // > 1% 表示支持全球占用率超过1%的浏览器 } ) |
该插件允许你使用未来版本CSS可能纳入标准的特性,它会将其编译为当前浏览器能够理解的CSS规则。
cssnext已经使用了Autoprefixer,因此不需要明确声明后者。
CSS 的层叠变量的自定义属性规范(CSS Custom Properties for Cascading Variables)允许在CSS中定义属性,并在样式规则中将其作为变量引用。自定义属性以 -- 开头,你可以利用 var() 引用这些属性:
1 2 3 4 5 6 7 8 9 |
:root { /* 自定义属性 */ --text-color: black; } body { /* 引用自定义属性 */ color: var(--text-color); } |
你还可以定义一个属性集,然后通过@apply来应用:
1 2 3 4 5 6 7 8 9 10 11 12 |
:root { /* 自定义属性集 */ --danger-theme: { color: white; background-color: red; }; } .danger { /* 应用属性集,新增两条样式规则 */ @apply --danger-theme; } |
你可以在calc()函数中引用属性:
1 2 3 4 5 6 7 |
:root { --fontSize: 1rem; } h1 { font-size: calc(var(--fontSize) * 2); } |
1 2 3 4 5 |
@custom-media --small-viewport (max-width: 30em); @media (--small-viewport) { /* 对于小的viewport应用样式 */ } |
使用操作符代替min- / max-,让语法更易读:
1 2 3 4 5 6 7 8 9 |
@media (width >= 500px) and (width <= 1200px) { /* 样式规则 */ } /* 也可以和自定义媒体查询联用 */ @custom-media --only-medium-screen (width >= 500px) and (width <= 1200px); @media (--only-medium-screen) { /* 样式规则 */ } |
CSS 扩展规范(CSS Extensions)允许自定义选择器,你可以创建一个选择器来引用多个既有选择器:
1 2 3 4 5 |
@custom-selector :--heading h1, h2, h3, h4, h5, h6; :--heading { font-weight: bold; } |
转换后的结果为:
1 2 3 |
h1, h2, h3, h4, h5, h6 { font-weight: bold; } |
样式规则嵌套是非常实用的特性,可以减少重复的选择器声明。它是SASS、LESS等CSS预处理器能够流行的重要原因。
CSS 嵌套模块规范(CSS Nesting Module)中定义了标准的样式规则嵌套方式,cssnext支持这些规范。
规范引入了一种新的嵌套选择器,使用 & 来表示。在嵌套样式规则(nested style rule)中使用该选择器时,它代表当前被匹配的父规则;在其它地方使用该选择器不代表任何东西。
嵌套样式规则具有两种语法:
- 直接嵌套,直接编写在其它样式的内部,且规则的组合选择器(compound selector)的第一个必须是嵌套选择器:
123456789101112131415161718192021222324252627.foo {color: blue;& > .bar { color: red; }}/* 转换后 */.foo { color: blue; }.foo > .bar { color: red; }.foo {color: blue;&.bar { color: red; }}/* 转换后 */.foo { color: blue; }.foo.bar { color: red; }.foo, .bar {color: blue;& + .baz, &.qux {color: red;}}/* 等价于 */.foo, .bar { color: blue; }:matches(.foo, .bar) + .baz, :matches(.foo, .bar).qux { color: red; } - 嵌套@Rule:这种方式更加灵活,没有嵌套选择器的那些限制:
12345678910111213141516171819202122232425.foo {color: red;@nest & > .bar { color: blue; }}/* 等价于 */.foo { color: red; }.foo > .bar { color: blue; }.foo {color: red;/* & 仍然表示父规则,但是位置随意了 */@nest .parent & { color: blue; }}/* 等价于 */.foo { color: red; }.parent .foo { color: blue; }.foo {color: red;@nest :not(&) { color: blue; }}/* 等价于 */.foo { color: red; }:not(.foo) { color: blue; }
color函数可以让颜色操控更加方便,该函数会被编译为rgba:
1 2 3 4 5 6 7 |
a { color: color(red alpha(-10%)); } a:hover { color: color(red blackness(80%)); } |
更多的颜色修饰符参考官方。
hwb函数类似于hsl,但是更加易于人类理解,该函数会被编译为rgba:
1 2 3 |
body { color: hwb(90, 0%, 0%, 0.5); } |
gray函数用于指定灰度颜色 ,该函数会被编译为rgba:
1 2 3 4 5 6 7 |
.foo { color: gray(85); } .bar { color: gray(10%, 50%); } |
四位或者八位的 #rrggbbaa 格式的颜色代码被支持:
1 2 3 |
body { background: #9d9c; } |
cssnext允许任何样式属性取值initial,这个值不是浏览器默认值,而是规定的某个属性的默认值。例如display的默认值总是inline。
你可以使用
1 2 3 |
div { all: initial; } |
把所有属性设置为默认值。
该伪类匹配任何具有href属性的a/area/link元素:
1 2 3 |
nav :any-link { background-color: yellow; } |
该伪类:
1 2 3 |
p:matches(:first-child, .special) { color: red; } |
允许该伪类指定多个选择器:
1 2 3 |
p:not(:first-child, .special) { color: red; } |
对于不支持该语法的旧浏览器,自动转换为单个冒号:
1 |
a::before { } |
在某个样式类文件中启用PostCSS插件。例如清除CSS代码中的注释:
1 2 3 4 5 6 7 8 9 10 11 |
/* 标准语法 */ @use postcss-discard-comments(removeAll: true); /* 备选语法 */ @use postcss-discard-comments { removeAll: true } /* 这里的注释会被清除 */ h1 { color: red } |
为某些样式属性提供简写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/* 简写 */ .icon { size: 48px; } /* 等价于 */ .icon { width: 48px; height: 48px; } /* 简写 */ .frame { /* 第一个是下上,第二个是左右 */ margin: * auto; } /* 等价于 */ .frame { margin-right: auto; margin-left: auto; } /* 简写 */ .banner { position: fixed 0 0 *; } /* 等价于 */ .banner { position: fixed; top: 0; right: 0; left: 0; } /* 简写 */ .canvas { color: #abccfc #212231; } /* 等价于 */ .canvas { color: #abccfc; background-color: #212231; } |
目前IDE对这些简写的支持不太好,可能误判为语法错误。
Leave a Reply