PostCSS

Введение

PostCSS — программа, которая автоматизирует рутинные операции с CSS с помощью расширений, написанных на языке JavaScript.

Используется при разработке Википедии, Facebook и GitHub.

Один из самых часто загружаемых с npm инструментов для работы с CSS. Разработана Андреем Ситником в компании «Злые марсиане».

Я пользуюсь PostCSS вместе с Gulp, изучить Gulp 4 Вы можете в моей статье Gulp 4

Содержание статьи:
Введение
Установка
Переменные в CSS (postcss-simple-vars)
Импорт файлов CSS (postcss-simple-vars)
Mixins
Видео о PostCSS
Ошибки

Установка PostCSS

Установим PostCSS пакет для Gulp

npm install gulp-postcss --save-dev

Сразу же добавим один из самых популярных плагинов для PostCSS - autoprefixer

Некоторые разработчики пользуются одновременно SASS и PostCSS именно ради этого плагина.

npm install autoprefixer --save-dev

Добавим в gulpfile.js postcss = require('gulp-postcss'), autoprefixer = require('autoprefixer')

А также убедимся, что autoprefixer и gulp-postcss добавились в devDependencies в файле package.json

"devDependencies": { "autoprefixer": "^9.6.1", "browser-sync": "^2.26.7", "gulp": "^4.0.2", "gulp-postcss": "^8.0.0", "gulp-sass": "^4.0.2" }

Отредактируем файл gulpfile.js мы добавили postcss и autoprfixer уберем sass и если что-то было лишнее - тоже уберём.

Для тренировки переименуем функцию style в styles - в скольки местах нужно будет это сделать?

Мы пока что установили только autoprefixer, поэтому сбор нескольких файлов в один нам пока не доступен. укажем исходный файл явно

const gulp = require('gulp') , postcss = require('gulp-postcss'), autoprefixer = require('autoprefixer'); gulp.task('default', function(done) { console.log("Gulp is running!"); done(); }); function styles() { console.log("style is running!"); // 1. where is my dev css files return gulp.src('./app/assets/styles/style.css') // 2. pass that file through postcss compiller .pipe(postcss([autoprefixer])) // 3. where do I save the compiled CSS? .pipe(gulp.dest('./app/temp/styles/style.css')) } function html() { console.log("Some change in index.html happened!"); } function watchFiles() { gulp.watch("./app/assets/index.html", html); gulp.watch("./app/assets/styles/**/*.css", styles); } exports.styles = styles; exports.html = html; exports.watch = watchFiles;

Запустим наш новый watch

gulp watch

Теперь, если мы создадим свойство, которое нуждается в автопрефиксе, например columns и сохраним файл

body {     padding: 27px;     margin: 12px;     columns: 300px 2; }

На выходе - в папке heiheiru/app/temp/styles/style.css мы увидим

body {     padding: 27px;     margin: 12px;     -moz-columns: 300px 2;          columns: 300px 2; }

Если у Вас появились сложности - изучите решение ошибки с path

Переменные в css

Установим пакет postcss-simple-vars

$ npm install postcss-simple-vars --save-dev

npm WARN heihei@1.0.0 No description
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ postcss-simple-vars@5.0.2
added 1 package from 1 contributor and audited 10643 packages in 7.83s
found 0 vulnerabilities

Добавим новую константу

cssvars = require('postcss-simple-vars');

И вставим её в pipe функции styles

.pipe(postcss([cssvars, autoprefixer]))

Теперь можно смело добавить в heiheiru/app/assets/styles/style.css переменные.

Например, цвета. Мне нужно задать основной цвет для раздела о Финляндии. Назовём его finBlue и сделаем таким же как синий во флаге Финляндии.

$finBlue: #002f6c; body { color: $finBlue; padding: 27px; margin: 12px; columns: 300px 2; }

Перезапустим watch и сохраним файл.

Посмотрим, что будет на выходе в папке heiheiru/app/temp/styles/style.css

$finBlue: #002f6c; body { color: #002f6c; padding: 27px; margin: 12px; -moz-columns: 300px 2; columns: 300px 2; }

Как видите, значение из переменной успешно получено и никакого неотносящегося к CSS кода на выходе нет - такой файл можно смело выкладывать на хостинг.

Какой хостинг выбрать - читайте в моей статье Выбор хостинга для сайта

Какой хостинг выбрать

Вложенные теги CSS (nested css)

Для удобства разработчиков создано много плагинов, которые позволяют делать вложенные теги, например создать класс и прямо внутри {написать свойства разных элементов}

В PostCSS за это отвечает плагин postcss-nested

$ npm install postcss-nested --save-dev

npm WARN heihei@1.0.0 No description
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ postcss-nested@4.1.2
added 5 packages from 6 contributors and audited 10659 packages in 12.936s
found 0 vulnerabilities

Добавим в gulpfile.js

nested = require('postcss-nested'); .pipe(postcss([cssvars, nested, autoprefixer]))

А в heiheiru/app/assets/styles/style.css добавим

.box { a { display: block; padding: 10px; } }

Это не валидный CSS, но после обработки PostCSS он превратится в

.box a { display: block; padding: 10px; }

Импорт CSS файлов

Во время разработки сайта удобно иметь небольшие отдельные файлы для каждого блока.

С другой стороны на хостинге лучше иметь один файл style.css, чтобы вебсервер делал меньшее количество обращений к файлам и время загрузки уменьшалось.

Включать несколько файлов в один умеет postcss-import

$ npm install postcss-import --save-dev

npm WARN heihei@1.0.0 No description
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ postcss-import@12.0.1
added 3 packages from 2 contributors and audited 10676 packages in 8.49s
found 0 vulnerabilities

Добавим в gulpfile.js

cssImport = require('postcss-import');

и

.pipe(postcss([cssImport, cssvars, nested, autoprefixer]))

cssImport нужно поставить в самое начало pipe, чтобы PostCSS сперва собрал все модули, а уже потом начал обрабатывать.

Для поддержания порядка в файлах создадим в папке heiheiru/app/assets/styles подпапку modules.

Разместим там файл _topmenu.css

В файле heiheiru/app/assets/styles/style.css напишем

@import "modules/_topmenu";

Mixins

Миксины нужны для удобства разработки адаптивных сайтов. Можно обойтись без них и просто писать везде

@media screen and (max-width: 360px) and (min-width: 310px)

Но с миксинами мне кажется проще. Можете сами попробовать и сравнить.

npm install postcss-mixins --save-dev

npm WARN heihei@1.0.0 No description
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ postcss-mixins@6.2.2
added 20 packages from 45 contributors and audited 12743 packages in 19.791s
found 0 vulnerabilities

Добавим новую переменную

const mixins = require('postcss-mixins');

И добавим в pipe postcss mixins

function css() { console.log('MY_LOG: css function is running'); return src('./app/assets/styles/style.css', {base: './app/assets/styles'}) .pipe( sourcemaps.init() ) .pipe(postcss([cssImport, mixins, nested,autoprefixer,cssvars,cssnano])) .on('error', function(errorInfo){ console.log("MY_LOG: postcss Failed"); console.log(errorInfo.toString()); this.emit('end'); }) .pipe( sourcemaps.write('.') ) .pipe(gulp.dest('./dist')) .pipe(gulp.dest('./preFtp/css')); }; exports.css = css;

Создадим отдельный файл _mixins.css и не забываем импортировать его в style.css

@import "base/_mixins";

Определимся сколько диапазонов ширины нужно. Если Вы уже делали адаптивные сайты, то знаете сколько какому сайту нужно. Синтаксис media такой-же как в css

Не забудьте вставить внутрь каждой media query @mixin-content;

@define-mixin atSmall { @media (min-width: 500px) { @mixin-content; } } @define-mixin atMedium { @media (min-width: 501px) and (max-width:1000px){ @mixin-content; } } @define-mixin atLarge { @media (min-width: 1001px) and (max-width:1840px){ @mixin-content; } } @define-mixin atXL { @media (min-width: 1841px) { @mixin-content; } }

В данном примере используется подход Mobile First, то есть по умолчанию стили будут для мобильного телефона.

Видео о PostCSS

Ошибки

No PostCSS Config found in

Скорее всего эта ошибка появилась в результате исплоьзования Postcss с Gulp без sourcemaps

Например был такой код:

gulp.task('serve', function() { gulp.watch("./app/**/*.css", series(css)) console.log('MY_LOG: serve function is running'); }); function css() { console.log('MY_LOG: css function is running'); return gulp.src('./app/assets/**/*.css') .pipe(postcss()) .pipe(gulp.dest('./dest')); }; exports.css = css;

А в спецификации к Postcss сказано, что при использовании с Gulp нужно также добавить sourcemaps. Читать спецификацию

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

Поэтому код должен выглядеть примерно так:

const sourcemaps = require('gulp-sourcemaps'); function css() { console.log('MY_LOG: css function is running'); return gulp.src('./app/assets/**/*.css', {base: './app/assets'}) .pipe( sourcemaps.init() ) .pipe(postcss([cssImport, nested,cssvars,autoprefixer ])) .pipe( sourcemaps.write('.') ) .pipe(gulp.dest('./dest')); }; exports.css = css;

Share in social media: