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