CSS-препроцессоры в своё время значительно облегчали работу по написанию CSS кода. Однако в некотором роде все они были несовершенны и имели значительные изъяны в работе. А потому на смену препроцессорам пришёл постпрепроцессор PostCSS.

Это довольно таки мощный инструмент, облегчающий работу с CSS. Постпрепроцессор уже сегодня используется в таких крупных компаниях как Twitter и Google. Кроме того, по сообщениям разработчиков Bootstap, пятая версия CSS-фреймворка вероятнее всего также будет написана на PostCSS.

Многие здесь наверно уже знакомы с простпрепроцессингом. Кто-то уже активно использует PostCSS во всех своих проектах, кто-то планирует начать его использовать.

Для ускорения работы в области фронтэнд веб-разработки я написал собственный Yeoman генератор, который называется generator-alchemist. О нём и о моём процессе разработки интернет-сайтов пойдёт речь в данной статье.

Состав


Jade


jade

Использование шаблонизатора Jade опционально. Yeoman генератор при установке позволяет нам выбрать, хотим ли мы использовать Jade в нашем новом проекте или нет.

После установки пишите свой Jade код в папке /src/jade/ и он будет автоматически компилироваться в HTML.

HTML


HTML Hint

После компиляции Jade, HTML файл попадает в папку /src/html/, где проходит W3C валидацию кода и отправляется в папку /dist/. В том случае, если вы не используете Jade, вы пишите HTML код в папке /src/html/.

CSS


Изначальный CSS файл включает в себя несколько базовых вещей:

Normalize CSS

Grid System

<div class="container">
  <div class="row">
    <div class="col-8">
      Content block
    </div>
    <div class="col-4">
      Right sidebar
    </div>
  </div>
</div>


PostCSS


А вот тут начинается самое интересное. Сборка проекта включает себя большое количество PostCSS плагинов, которые позволяют писать CSS быстро и качественно. Ниже список плагинов, которые я использую:

Clearfix

Добавляет Clearfix аттрибуты для очистки плавающих элементов.

Было:

.foo {
  clear: fix;
}

.bar {
  clear: fix-legacy;
}


Стало:

.foo:after{
  content: '';
  display: table;
  clear: both;
}

.bar {
  clear: fix-legacy;
}

.bar:before,
.bar:after {
  content: '';
  display: table;
}

.bar:after {
  clear: both;
}

.bar {
  zoom: 1;
}


Color Short

Позволяет сокращать названия цветов.

Было:

.hello {
  border-bottom: 1px solid rgb(200);
  background: #20;
  color: #f;
  box-shadow: 0 1px 5px rgba(0, 0.5);
}


Стало:

.hello {
  border-bottom: 1px solid rgb(200, 200, 200);
  background: #202020;
  color: #fff;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
}


CSS Mqpacker

Группирует медиазапросы и помещает их в конец CSS документа.

CSS Nano

Крайне мощный инструмент для минификации CSS кода, идущего на продакшен.

CSS Next

Позволяет использовать возможности CSS-4 уже сегодня.

О возможностях CSS Next можно прочесть в этой статье.

Discard Comments

Удаляет все комментарии из CSS кода. Раньше с этой задачей отлично справлялся плагин CSS Nano, однако после обновления PostCSS до версии 5.0.x эта возможность перестала работать. Надеюсь, эту проблемы в ближайшее время исправят разработчики.

Focus

Добавляет псеводэлемент :focus ко всем селекторам, где используется :hover.

Было:

.button:hover {
  background: red;
}


Стало:

.button:hover,
.button:focus {
  background: red;
}


PreCSS

Позволяет использовать синтаксис Sass в работе с CSS: вложенность, переменные и многое другое. Подробнее обо всех возможностях PreCSS можно ознакомиться на странице плагина.

Было:

$blue: #056ef0;
$column: 200px;

header {
  background: $blue;
  width: $column;
    h1 {
      font-size: 18px;
    }
}


Стало:

header {
  background: #056ef0;
  width: 200px;
}

header h1 {
  font-size: 18px;
}


PxtoRem

Плагин, генерирующий rem и em из px.

Было:

p {
    font-size: 16px;
}


Стало:

p {
    font-size: 1rem;
}


Short

Ещё один мощный PostCSS плагин, позволяющий сокращать написание CSS кода.

Было:

.section {
  margin: 40px;
  text: bold center uppercase dimgrey 1.25em 1.5 .05em;
}

.section.inset {
  margin: * auto;
}


Стало:

.section {
  margin: 40px;
  color: dimgrey;
  font-weight: bold;
  text-align: center;
  text-transform: uppercase;
  font-size: 1.25em;
  line-height: 1.5;
  letter-spacing: .05em;
}

.section.inset {
  margin-right: auto;
  margin-left: auto;
}


Size

Добавляет CSS свойство size для обозначения ширины и высоты элемента.

Было:

.two {
    size: 20px 10px;
}

.one {
    size: 10px;
}


Стало:

.two {
    width: 20px;
    height: 10px;
}

.one {
    width: 10px;
    height: 10px;
}


JavaScript


Uglify

Минифицирует JavaScript код, располагающийся в папке /src/js/ и отправляет минифицированный файл в папку /dist/js/.

Изображения


Imagemin

Минифицирует изображения, которые находятся в папке /src/images/ и отправляет их в папку /dist/images/.

Сервер



Одновременно с запуском Gulp.js вы запускайте локальный сервер с использованием BrowserSync, доступный по адресу:

http://localhost:3000


Установка


Перед установкой генератора вам нужно иметь на своём компьютере установленные:


Если у вас уже всё вышеперечисленное установлено, запустите в терминале следующую команду для глобальной установки генератора:

$ sudo npm install -g generator-alchemist


После чего инициализируйте генератор в папку будущего проекта:

$ yo alchemist


Вот и всё. Все необходимые файлы для старта работы над проектом установлены. Осталось только запустить Gulp:

$ gulp


Пишите ваш Jade / HTML код в папке /src/jade/ или /src/html/
Пишите ваш CSS код в папке /src/css/
Пишите ваш JavaScript код в папке /src/js/
Помещайте ваши изображения в папку /src/images/

И все файлы будут автоматически оптимизироваться публиковаться в папку /dist/, идущую на продакшен.

Спасибо за ваше внимание!

github.com/azat-io/generator-alchemist

Комментарии (27)


  1. set
    26.08.2015 13:32

    Попробовал только что. Запустил дефолтную задачу и при попытке изменить css файл сразу же получил вот что:

    [12:27:46] Task 'postcss' is not in your gulpfile
    [12:27:46] Please check the documentation for proper gulpfile formatting
    gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.

    Process finished with exit code 1


    1. azat-io
      26.08.2015 16:07

      Хмм… Странно. У меня всё работает. У кого-то ещё есть такая проблема?
      Пришлите пожалуйста, что написано в gulpfile.js, который находится в корне проекта.


      1. set
        26.08.2015 16:11

        Пожалуйста
        var autoprefixer = require('autoprefixer-core');
        var center = require('postcss-center');
        var clearfix = require('postcss-clearfix');
        var colorshort = require('postcss-color-short');
        var cssnano = require('cssnano');
        var discardcomments = require('postcss-discard-comments');
        var focus = require('postcss-focus');
        var gulp = require('gulp');
        var htmlhint = require('gulp-htmlhint');
        var imagemin = require('gulp-imagemin');
        var mediaminmax = require('postcss-media-minmax');
        var pngquant = require('imagemin-pngquant');
        var postcss = require('gulp-postcss');
        var precss = require('precss');
        var pxtorem = require('postcss-pxtorem');
        var short = require('postcss-short');
        var size = require('postcss-size');
        var uglify = require('gulp-uglify')
        
        gulp.task('default', function() {
          gulp.watch('src/html/**', function(event) {
            gulp.run('html');
          });
          gulp.watch('src/css/**', function(event) {
            gulp.run('postcss');
          });
          gulp.watch('src/js/**', function(event) {
            gulp.run('js');
          });
          gulp.watch('dist/images/**', function(event) {
            gulp.run('images');
          });
        });
        
        
        // HTML
        
        gulp.task('html', function() {
          gulp.src('src/html/**/*.html')
              .pipe(htmlhint())
            .pipe(gulp.dest('dist/'))
        });
        
        
        // PostCSS
        
        gulp.task('css', function () {
            var processors = [
                colorshort,
                focus,
                center,
                mediaminmax,
                precss,
                short,
                size,
                clearfix,
                pxtorem,
                discardcomments,
                autoprefixer({browsers: ['last 5 version', 'ie 8']}),
                cssnano
            ];
            return gulp.src('src/css/*.css')
                .pipe(postcss(processors))
                .pipe(gulp.dest('dist/css/'));
        });
        
        // JavaScript
        
        gulp.task('js', function () {
            return gulp.src('src/js/*')
                  .pipe(uglify())
                .pipe(gulp.dest('dist/js'));
        });
        
        // Image files
        
        gulp.task('images', function () {
            return gulp.src('src/images/*')
                .pipe(imagemin({
                    progressive: true,
                    svgoPlugins: [{removeViewBox: false}],
                    use: [pngquant()]
                }))
                .pipe(gulp.dest('dist/images'));
        });
        
        


        1. azat-io
          26.08.2015 16:17
          +2

          Понял. Спасибо, благодаря вам нашёл ошибку в версии сборки без Jade.

          Строку 47 следует заменить на:

          gulp.task('css', function () {
          


          1. set
            26.08.2015 16:57
            +1

            :) всегда пожалуйста.


          1. azat-io
            26.08.2015 17:08

            Пардон, конечно же:

            gulp.task('postcss', function () {
            


  1. Synoptic
    26.08.2015 13:38
    +11

    Крайне сомнительна целесообразность использования перечисленных плагинов, кроме autoprefixer. Для своего проекта, который хочется пилить так, как нравится — да. Если бы мне пришлось работать со всеми этими top: center или text: bold ...; на каком-то проекте, я был бы крайне недоволен.

    P.S. Поясните, в чем профит от использования sass синтаксиса в постпроцессоре? В чем в таком случае разница между постпроцессором и препроцессором? Почему не взять нормальный SASS?


    1. olegkrasnov
      26.08.2015 13:51

      Большой разницы между препроцессором и PostCSS нет. Просто название такое. Профит от PostCSS в гибкости. Любую недостающую фичу можно реализовать уже сейчас, а не ждать, пока она появится в SASS. Стандартизация синтаксиса для коллективной работы — это уже дело другое.


      1. azat-io
        26.08.2015 16:08

        А также скорость работы и более быстрое написание кода.


        1. Synoptic
          26.08.2015 19:42
          +3

          В чем разница в скорости работы и написании кода между SASS и PostCSS?


          1. Iskin
            27.08.2015 10:34

            PostCSS раз в 10-20 быстрее Ruby Sass. Обычно PostCSS так же в несколько раз быстрее libsass — но там результат уже зависит от плагинов, есть пару плагинов, которые очень неоптимально написаны.


        1. porcelanosa
          28.08.2015 01:14

          C Emmet — преимущество написания с помощью сокращений сводится на нет.
          И опять же подсветка ошибок в IDE


      1. porcelanosa
        28.08.2015 01:13

        PreCSS плагин для PostCSS — это не совсем SASS.
        Скорее это такой вариант SCSS — многое надо писать по-другому.

        Т.е. другой синтаксис, например для Mixins

        /* before */
        
        @define-mixin icon $name {
            padding-left: 16px;
        
            &::after {
                content: "";
                background-url: url(/icons/$(name).png);
            }
        }
        
        .search {
            @mixin icon search;
        }
        
        /* after */
        
        .search {
            padding-left: 16px;
        }
        
        .search::after {
            content: "";
            background-url: url(/icons/$(name).png);
        }
        

        … да и не все возможности SASS поддерживаются
        И все бы хорошо, но как сказали выше — это вот когда ты один пишешь.
        И кроме того в IDE куча ошибок подсвечивается.


    1. Iskin
      26.08.2015 14:53

      Автор поста зря не упоминал postcss-use — www.npmjs.com/package/postcss-use

      Этот инструмент как раз решает обозначенную вами задачу — в начале каждого файла явно указываются плагины, которые для него нужны.


    1. Iskin
      26.08.2015 14:55
      +1

      В целом — да, все задачи которые автор статьи решает с помощью PostCSS, можно решить и без PostCSS.

      Смысл PostCSS в другом — решать те задачи, которые нельзя решить на Sass. То есть это не вопросы синтаксического сахара.

      Например, CSS Modules — как развитие идеи БЭМ, стал возможен только из-за PostCSS glenmaddern.com/articles/css-modules

      Другой пример, минифиактор cssnano и исправление стиля код с помощью CSSfmt.

      Третий пример — cssnext, чтобы уже сейчас писать на CSS4.


      1. azat-io
        26.08.2015 16:11

        Да, спасибо. Я планирую расширить возможности сборки в ближайшее время некоторыми из перечисленных вами вещей. Опять же, сборку писал под себя и она отнюдь не претендует на звание единственно правильного способа использования PostCSS в работе.


      1. porcelanosa
        28.08.2015 01:18
        +1

        Именно!!!
        Смысл PostCSS именно в модульности и расширяемости.
        Легко написать плагин самостоятельно. Это же обычный JS
        Например, я написала плагинчик, кототый меняет урлы изображений в соответствии со структурой моего проекта.
        Исходные изображения лежат в одной папке — и при редактировании в IDE их урлы, да и размеры легко подставляются автоматом.
        А при компиляции они в другую папку ложатся — и урлы в css конечном уже другие.


  1. olegkrasnov
    26.08.2015 13:50

    .


  1. Diokuz
    26.08.2015 14:44
    +3

    Важно понимать, что PostCSS — это препроцессор)


  1. fareloz
    27.08.2015 12:37

    generator-alchemist и картинка до ката сразу наводят на мысль о Full Metal Alchemist


  1. porcelanosa
    28.08.2015 01:24

    Добавлю полезные плагины:
    github.com/corysimmons/lost css grid в виде аля миксинов.
    github.com/justim/postcss-svg-fallback Fallback для SVG —
    github.com/hail2u/node-css-mqpacker группирует media queries и перемещает их в конец файла.
    это то что сама использую.
    А вообще вот github.com/postcss/postcss#plugins


    1. azat-io
      28.08.2015 01:40

      Там лишь самый смак. Больше плагинов тут: postcss.parts


      1. porcelanosa
        28.08.2015 10:56

        по-моему не больше — всё тоже самое, но за ссылку спасибо.


    1. azat-io
      28.08.2015 01:45

      Что касается тех плагинов, что привели вы, то у меня гридная сетка уже изначально встроена в сборку. А вот с последним я был не знакомы и обязательно его включу.


      1. porcelanosa
        28.08.2015 10:59

        github.com/luisrudge/postcss-flexbugs-fixes — вот очень полезный плагин. Исправляет все баги с flex — коих тьма пока еще.
        Почему-то изъяли из каталогов.


  1. azat-io
    01.09.2015 16:20

    Обновил статью ввиду обновления содержимого сборки новой версии.


  1. Finom
    06.09.2015 14:06

    В postcss меня отпугивает отсутствие умного extend, который есть в sass.