PostCSS
Andrey Sitnik
Evil Martians
Russia
We Work with
Our Open Source
1. PostCSS is Important
2 000 000 downloads per month
Users
Used Inside
UnCSS
2. What is PostCSS?
CSS
Stringifier
Parser
Plugin 1
Plugin 2
New CSS
gulp.task('css', () => {
let postcss = require('gulp-postcss');
return gulp.src('src/*.css')
.pipe( postcss([ plugin1, plugin2 ]) )
.pipe( gulp.desc('build/') );
});
Usage
postcss.plugin('my-plugin', function () {
return function (css) {
doSomething(css);
};
});
Plugin
.block {
&_title {
font-size: 200%;
}
}
Plugins like Less / Sass
.block_title {
font-size: 200%;
}
.foo {
opacity: 0.8;
}
Plugins for Fallbacks
.foo {
opacity: 0.8;
filter: alpha(opacity=80)\9;
}
.foo {
border: none;
}
Plugins for Minify
.foo{border:0}
.foo {
margin-top: 10px;
margin: 0 auto;
}
Plugins for Lint
foo.css:3:5: margin overrides margin-top.
Is it accidentally mistake?
PostCSS vs. Less / Sass
PostCSS:
Less:
Mixins
Mixins
Transform
Lint
PostCSS vs. Gulp
PostCSS:
Gulp:
Parse
Transform
Fallbacks
Minify
Parse
Transform
Fallbacks
Minify
Parse
Parse
3. How to Start
Step 1
Less + PostCSS
return gulp.src('src/*.less')
.pipe( less() )
.pipe( postcss([]) )
.pipe( gulp.desc('build/') );
postcss( no plugins ):
input == output
*.less
Less
CSS
PostCSS
Same CSS
Happy
product manager
Step 2
postcss([
require('autoprefixer')
])
"last 2 version", "ie > 8"
+
.foo {
user-select: none;
}
.foo {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
No Mixins
.foo {
transform: rotate(10deg);
}
.foo {
-webkit-transform: rotate(10deg);
transform: rotate(10deg);
}
Only Actual Prefixes
.foo {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.foo {
border-radius: 5px;
}
Clean Old Prefixes
Step 2
postcss([
require('postcss-csssimple'),
require('autoprefixer')
])
IE Fallbacks
.foo {
display: inline-block;
}
.foo {
display: inline-block;
*display: inline;
*zoom: 1;
}
postcss-svg-fallback
.icon {
background: url(icon.svg) no-repeat;
background-size: 20px 20px;
}
.icon {
background: url(icon.svg) no-repeat;
background-size: 20px 20px;
}
.no-svg .icon {
background-image: url(icon-20x20.png);
}
Step 3
postcss([
require('postcss-cssnext'),
require('postcss-csssimple'),
require('autoprefixer')
])
@custom-media --phone (width <= 600px);
@media (--phone) {
.promo-image {
display: none;
}
}
“CSS 4” today
Step 4
postcss-sprites
.comment {
background: url(sprite/comment.png) no-repeat 0 0;
}
.bubble {
background: url(sprite/bubble.png) no-repeat 0 0;
}
.comment {
background: url(sprite.png) no-repeat 0 0;
}
.bubble {
background: url(sprite.png) no-repeat 0 -50px;
}
postcss-url
.comment {
background: url(comment.png);
}
.comment {
background: url(data:image/png;base64,
R0lGODdhMAAwA…);
}
Step 5
gulp.task('lint:css', function () {
return gulp.src('src/*.less')
.pipe( postcss([
require('stylelint'),
require('postcss-reporter'),
], {
syntax: require('postcss-less')
}) );
});
Stylelint
Lead
Junior
Junior
Stylelint
Lead
RTLCSS
.logo {
float: left;
margin: 0 0 0 10px;
}
.logo {
float: right;
margin: 10px 0 0 0;
}
RTLCSS
Advanced Topics
PreCSS
Links
twitter.com/ andreysitnik
twitter.com/ postcss
gitter.im/ postcss/postcss
PostCSS Intro
By Andrey Sitnik
PostCSS Intro
- 11,200