Створення складних макетів з PostCSS-Flexbox

363

Від автора: дізнайтеся, як за допомогою цієї маленької, але потужної PostCSS функції створювати системи сіток, про які ви завжди мріяли. Flexbox – чудовий інструмент для скорочення коду. Крім того, в ньому є кілька відмінних функцій щодо зміни порядку сортування елементів і вирівнювання. Однак цей інструмент не проводить обчислення за розмірами колонок і роздільників. Експерти повторюють з разу в раз: Flexbox – хороший інструмент, але це не система сіток.

Використовувати Flexbox потрібно, але не можна забувати про базових концепціях сітчастих систем, які витягли нас з ери дизайнів GeoCities:

створюйте колонки з пропорційною прив’язкою до чогось;

використовуйте однакові роздільники в дизайні.

Ми можемо взяти одну з багатьох Flexbox систем, але якщо чесно, стилі в них по більшій частині засновані на обтеканиях. Розробники просто додають display: flex до контейнера, а також кілька класів-хелперів, тільки запутывающих Flexbox властивості (наприклад, клас .grid-vertical-align-mid можна замінити на align-items: center).

Єдина відмінність – тепер колонки з приставкою «flex», тобто вони володіють тими перевагами, про які я писав на початку. Однак це не вирішує головні проблеми сіток: сітчасті системи сильно засмічують CSS, і вони досить нудні.

Проблема сіток

Створення складних макетів з PostCSS-Flexbox

Забруднення коду: 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:

.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, але не забудьте додати їх в свій код):

.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-Flexbox

Мінімум розмітки: мінімум розмітки, дві колонки, сітка з повторюваним кількістю колонок за допомогою 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 плагіни, які вам потрібні. Тепер поговоримо про дещо крутому. Зазвичай в препроцессорах можна створювати цикли з итераторами:

@for $i from 1 through 3 {
content: $i; // returns content: 1; content: 2; content: 3;
}

З мінімальними знаннями препроцесорів функцію ant можна використовувати зовсім по-іншому…

$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:

.grid {
generate-grid: sizes(100px 1/2 1/2); /* можна передати доп. опції, pluck() вже не потрібна. */
}

Безліч варіантів

Створення складних макетів з PostCSS-Flexbox

Цикли в препроцессорах: ant показує всю свою міць в комбінації з циклами, з допомогою цієї функції можна створювати такі макети, про які раніше й думати не можна було

Сітки з повторюваними колонками хороші, коли знаєш розмір і кількість елементів, але іноді хочеться просто створити контейнер і накидати всередину елементів з випадковими розмірами. Тут вам допоможе значення negative-margin. Просто передайте negative-margin у функцію ant:

.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, там ви знайдете гарні демо і документацію.