От автора: узнайте, как с помощью этой маленькой, но мощной PostCSS функции создавать системы сеток, о которых вы всегда мечтали. Flexbox – замечательный инструмент для сокращения кода. Кроме того, в нем есть несколько отличных функций по изменению порядка сортировки элементов и выравнивания. Однако данный инструмент не проводит вычисления по размерам колонок и разделителей. Эксперты повторяют из раза в раз: Flexbox – хороший инструмент, но это не система сеток.
Использовать Flexbox нужно, но нельзя забывать о базовых концепциях сетчатых систем, которые вытащили нас из эры дизайнов GeoCities:
создавайте колонки с пропорциональной привязкой к чему-то;
используйте одинаковые разделители в дизайне.
Мы можем взять одну из многих Flexbox систем, но если честно, стили в них по большей части основаны на обтеканиях. Разработчики просто добавляют display: flex к контейнеру, а также несколько классов-хелперов, только запутывающих Flexbox свойства (например, класс .grid-vertical-align-mid можно заменить на align-items: center).
Единственное различие – теперь колонки с приставкой «flex», т.е. они обладают теми преимуществами, о которых я писал в начале. Однако это не решает главные проблемы сеток: сетчатые системы сильно засоряют CSS, и они довольно скучные.
Проблема сеток
Загрязнение кода: Bootstrap CSS для сетки насчитывает 16 435 символов, большую часть которых вы никогда не используете
Создатели сеток обычно распространяют огромные пакеты CSS с возможностью сдвигать ячейки сетки, изменять их порядок, выравнивание и размер для произвольных устройств. Они пытаются заретушировать недостатки с помощью сжатия, но это не работает. А что, если вам не нужны все эти дополнительные функции?
Если предположить, что ваш текущий фреймворк поддерживает миксины, лучший выход – изучить их и самому создавать колонки. Данный подход немного снижает загрязнение кода, но ограничивает саму сетку до дробей, а также такая сетка не будет с легкостью работать с другими фреймворками.
Есть и вторая проблема. Дизайнеры психологически сами себя ограничили и принимают все свои решения на основе комбинаций равных по размеру колонок. В итоге весь интернет стал превращаться в антиутопию из мобильных дизайнов.
Flexbox представил свойство flex-grow, которое дало нам чуть больше свободы. Теперь мы можем задавать хорошие размеры, а оставшееся пространство заполнять, растягивая элементы. Но как выстраиваются разделители на странице? Контентные области выкладываются на макет с какими-то пропорциями, или мы вернулись к тому, от чего ушли?
Выход дракона
Обе проблемы решает функция postcss-ant. Плагины PostCSS можно использовать в паре с конструкторами типа webpack, gulp или просто с командной строкой. Ant бесшовно сливается с обычным CSS (или препроцессором) при помощи подозрительно простого API, проводящего множество вычислений при помощи calc. Функции на вход подаются два миксин-подобных параметра, и она вытягивает множество сетчатых размеров.
На примере будет понятнее: width: sizes(1/2) get(1) возвращает calc(99.99% * 1/2 — (30px — 30px * 1/2)). Разобьем на пункты:
sizes() – список размеров, разделенных запятой. Набор размеров может быть любым: фиксированные числа в единицах длины CSS (px, em, %), дроби или числа с плавающей точкой (возвращающие все что осталось и нефиксированные числа), а также ключевое слово auto (возвращающее все что осталось, нефиксированные дроби и фиксированные числа).
Pluck() – индекс, вытягивающий сетчатые размеры из списка. Т.е. sizes(1px 2px 3px) get(2) вернет 2px.
Формула calc – сетчатый размер.
Мы получаем ширину колонок в двухколоночной сетке с одним разделителем в 30px:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.grid { display: flex; flex-wrap: wrap; } .half { width: sizes(1/2) get(1); /* возвращает calc(99.99% * 1/2 - (30px - 30px * 1/2)) */ margin-right: 30px; /* помещает разделитель справа от колонок */ } .half:nth-child(2n + 2) { /* стартует со второго элемента и начинает отсчет с 2s */ margin-right: 0; /* удаляет последний разделитель из каждой строки */ } |
Функция уже позволяет дизайнерам делать все, что они только хотят, но давайте копнем чуть глубже.
sizes(100px 1/2) get(1) возвращает 100px. Просто, но зачем использовать ant, чтобы получить 100px? Сейчас объясню.
sizes(100px 1/2) get(2) возвращает calc((99.99% — (100px + (30px * 1))) * 1/2 — (30px — 30px * 1/2)). Ничего себе. Ant вычисляет общий размер фиксированных чисел и возвращает 1/2 от того, что осталось в формате, удобном для сетки.
С помощью формул calc можно создать сетку с колонкой в 100px и двумя колонками 1/2 (я не буду показывать стили для .grid, но не забудьте добавить их в свой код):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.fixed-size { width: sizes(100px 1/2) get(1); /* возвращает 100px (похоже на глупость, но потерпите, дочитайте до конца) */ margin-right: 30px; } .half { width: sizes(100px 1/2) get(2); /* возвращает calc((99.99% - (100px + (30px * 1))) * 1/2 - (30px - 30px * 1/2)) */ margin-right: 30px; } .half:nth-child(3n + 3) { margin-right: 0; } |
Теперь мы можем вычислять ранее недоступные нам размеры, но способ все еще не такой гибкий, а с множеством размеров наш код сильно разрастется.
Циклы в препроцессорах
Минимум разметки: минимум разметки, две колонки, сетка с повторяющимся количеством колонок при помощи postcss-ant. Обратите внимание на отсутствие margin-right на последнем элементе в строке
Препроцессоры не всегда ладят с PostCSS, особенно когда используется пользовательский синтаксис. К счастью API функции ant дружит с препроцессорами. Можно взять PostCSS-parser наподобие postcss-scss с плагином PreCSS, но такой подход задействует много незаконченных/необслуживаемых PostCSS плагинов, плохо имитирующих функционал Sass. По моему мнению, лучше всего поступить следующим образом:
использовать быстрый препроцессор типа node-sass для перевода in.scss в out.scss;
использовать PostCSS для перевода out.scss в final.css;
подключать final.css через в разметку.
Вы получаете лучший синтаксис среди препроцессоров и все PostCSS плагины, которые вам нужны. Теперь поговорим о кое-чем крутом. Обычно в препроцессорах можно создавать циклы с итераторами:
1 2 3 |
@for $i from 1 through 3 { content: $i; // returns content: 1; content: 2; content: 3; } |
С минимальными знаниями препроцессоров функцию ant можно использовать совершенно по-другому…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$sizes: 100px 1/2 1/2; $gutter: 30px; $length: length($sizes); .column { margin-right: $gutter; @for $i from 1 through $length { &:nth-child(#{$length}n + #{$i}) { width: sizes($sizes) get($i) gutter($gutter); } } &:nth-child(#{$length}n + #{$length}) { margin-right: 0; } } |
Теперь наши неравные колонки смещаются на новую строку без дополнительной разметки. Разберитесь в коде. Поменяйте размеры, разделители, добавьте новые размеры (100px auto 100px).
Это довольно простой шаблон с ant, я поместил его внутрь свойства, работающего с обычным CSS:
1 2 3 |
.grid { generate-grid: sizes(100px 1/2 1/2); /* можно передать доп. опции, pluck() уже не нужна. */ } |
Множество вариантов
Циклы в препроцессорах: ant показывает всю свою мощь в комбинации с циклами, с помощью этой функции можно создавать такие макеты, о которых раньше и думать было нельзя
Сетки с повторяющимися колонками хороши, когда знаешь размер и количество элементов, но иногда хочется просто создать контейнер и накидать внутрь элементов со случайными размерами. Тут вам поможет значение negative-margin. Просто передайте negative-margin в функцию ant:
1 2 3 4 5 6 7 8 |
.grid { margin: 0 -15px; } .column { width: sizes(1/3) get(1) grid(negative-margin); margin: 0 15px; } |
Заключение
Эти примеры лишь малая доля того, что может postcss-ant. Функция содержит несколько дополнительных параметров, множество обработок ошибок, но настоящая сила функции ant –это вы.
«Тупые» инструменты, просто возвращающие голые данные всегда самые лучшие, так как они позволяют разработчика делать все, что угодно. Именно для этого и была придумана функция postcss-ant. Заинтересовались? Зайдите на corysimmons.github.io/postcss-ant, там вы найдете красивые демо и документацию.
Автор: Cory Simmons
Источник: //www.creativebloq.com/
Редакция: Команда webformyself.