Практика PostCSS

Андрей Ситник, Злые марсиане

Практика PostCSS

Андрей Ситник, Злые марсиане

Наши клиенты

Наш опенсорс

Глава 1 Что такое PostCSS?

Старые препроцессоры

a {
    <%= include clickable %>
    color: <%= $link-color %>;
}

Схема работы

CSS
карта кода
Парсер
Плагин
Плагин
Генератор
Новый CSS
новая карта

Использование

gulp.task('css', () => {
    let postcss = require('gulp-postcss');
 
    return gulp.src('src/*.css')
        .pipe( postcss([ plugin1, plugin2 ]) )
        .pipe( gulp.desc('build/') );
});

postcss-nested

.block {
    &_title {
        font-size: 200%;
    }
}
.block_title {
    font-size: 200%;
}

Спецификация W3C postcss-media-minmax

@media (width <= 600px) {

}
@media (max-width: 600px) {

}

Зачем?

Выйти за пределы старых препроцессоров:

1 000 000 загрузок в месяц

Пользователи PostCSS

Глава 2 Подключение плагинов

Задаём плагины

postcss([
    require('autoprefixer')({
        browsers: 'last 2 version'
    }),
    require('postcss-cssnext'),
    require('precss')
])

Проблема Неявность

.icon {
    top: center;
}

Решение postcss-use

@use postcss-center;
 
.icon {
    top: center;
}

Правило 1

Все плагины, добавляющие свой синтаксис,
подключать через postcss-use

Правило 2

Начинайте с пакетов плагинов

Глава 3 Изоляция

Правило 3

Используйте PostCSS для поддерживаемого кода, а не только синтаксического сахара

Изоляция в JS

var moment = require('moment');

Компонентный подход

Проблемы

  1. Конфликт селекторов
  2. Наследование стилей

Проблема 1 Конфликт селекторов

logo.css

header.css

.name {
    color: black;
}
.name {
    color: gray;
}

Решение 1 postcss-bem

@b Logo {
    @e name {
        color: gray;
    }
}
.Logo-name {
    color: gray
}

Решение 2 CSS Modules

.name {
    color: gray;
}
.Logo__name__sVK0p {
    color: gray
}

CSS Modules в JS

import styles from './logo.css';
 
class Logo extends React.Component {
    render() {
        return <div className={ styles.name }>We</div>;
    }
}

Что выбрать

CSS Modules:

БЭМ

Проблема 2 Наследование свойств

<Header>
    color: white
    <Logo>
        background: white
    </Logo>
</Header>

Проблема 3 Виджет для стороннего сайта

* {
    box-sizing: border-box;
}
div {
    margin-top: 10px;
}

Решение postcss-autoreset

.logo {
    color: black;
}
.logo--big {
    width: 200px;
}
.logo {
    all: initial; 
    color: black;
}
.logo--big {
    width: 200px;
}

Спецификация W3C postcss-initial — полифил для IE

.logo {
    all: initial;
}
.logo {
    color: black;
    background: white;
    box-sizing: content-box;
    line-height: normal;
    text-shadow: none;
    vertical-align: baseline;
    white-space: normal;

Идеальная изоляция

Глава 4 Явный код

Правило 4

Убирайте «магические числа» в стилях с помощью PostCSS

postcss-assets

Размеры картинок:

.icon {
    width: width('logo.png');
    height: height('logo.png');
    background: inline('logo.png');
}

postcss-property-lookup

Ссылка на другие свойства:

.icon {
    width: 20px;
    height: @width;
}

Спецификация W3C postcss-custom-media

@custom-media --phones (width <= 700px);
@custom-media --hidpi  (resolution >= 2dppx);
 
@media (--phones) { }
@media (--phones) and (--hidpi) { }

Правило 5

Прячем хаки в плагины

autoprefixer

:fullscreen { }
:-webkit-full-screen { }
:-moz-full-screen { }
:-ms-fullscreen { }
:fullscreen { }

postcss-font-magician

body {
    font-family: Alice;
}
@font-face {
    font-family: Alice;
    font-style: normal;
    font-weight: 400;
    src: local("Alice"),
         url("//fonts.gstatic.com/….woff")
             format("woff");
}
body {
    font-family: Alice;
}

postcss-color-rgba-fallback

.popup {
    background:
        rgba(153, 221, 153, 0.8);
}
.popup {
    background: #99dd99; /* IE 8 */
    background:
        rgba(153, 221, 153, 0.8);
}

postcss-svg-fallback

.icon {
    background: url(logo.svg);
    background-size: 20px 20px;
}
.icon {
    background: url(logo.svg);
    background-size: 20px 20px;
}
 
.no-svg.icon {
    background: url(logo-20x20.png);
}

postcss-svg

.icon {
    background: svg('logo.svg', '[fill]: #c00');
}

Глава 6 Линтеры