Назад

Цикли в SCSS

html code

Якщо ви дивилися старі фантастичні фільми, то повинні знати, наскільки цикли там потужна штука. Скорміть роботу нескінченному циклу. Залишиться від роботи тільки пил. Цикли в препроцесорах не викликають драматичних вибухів в космосі (сподіваюся), але вони дуже корисні при написанні коду. Поки всі говорять про бібліотеки шаблонів і модульний дизайн, основна увага прикута до CSS селекторів. Неважливо, чим ви пишите селектори (BEM, OOCSS, SMACSS, ETC), цикли додадуть читабельності вашим шаблонам і спростять роботу з ними, заклавши їх в ваш код.

Умови циклу

Якщо необачно підійти до справи, нескінченний цикл може уповільнити або зламати компілятор. Не самий кращий спосіб перетворити роботу в пар, але нескінченні цикли можуть дратувати тих, хто використовує ваш код. Ось чому цикли завжди повинні розв’язувати обмежені завдання. Зазвичай задається ряд повторів з інкрементом або ставиться завдання по збору об’єктів.

З програмування:

  • 🡲 Цикли while – загальні, вони виконуються, поки виконується умова. Будьте обережні! Зазвичай саме тут виникають нескінченні цикли.
  • 🡲 Цикли for – інкрементні, повторюються заданою кількістю разів.
  • 🡲 Цикли for-each - проходяться по колекції або списку, витягаючи один елемент за раз.

Кожен тип циклів вузьконаправлений. Цикл for-each – особливий випадок циклу for, який в свою чергу є одним з варіантів циклу while. Однак більшість ваших випадків застосування будуть підпадати під більш конкретні категорії. Я не зміг знайти чистий цикл while на реальних сайтах, більша частина прикладів набагато краще працює на for або for-each. У Sass є синтаксис для всіх трьох циклів. Поїхали.

Колекція і цикли for-each

Цикли в препроцесорах найчастіше корисні, якщо вам потрібно обробити колекцію (список або масив) елементів. Наприклад, масив іконок соціальних мереж або список станів-модифікаторів (success, warning, error тощо). Цикли for-each прив’язані до відомої колекції елементів, з-за чого, як правило, це найбільш конкретні та зрозумілі цикли. Почнемо з прогону в циклі простого списку кольорів, щоб зрозуміти принцип роботи.

У Sass для одержання кольрів нам знадобиться скористатися директивою @each (@each $item in $list):


Кнопки соціальних мереж

Проганяти списки в циклі корисно, але найчастіше ви будете проходити в циклі по об’єктах. Один з найпоширеніших прикладів – привласнення різних кольорів та іконок кнопок соціальних мереж. Для кожного елемента списку, нам необхідно назву сайту і колір бренду цієї соціальної мережі.

У Sass щоб отримати доступ до пари ключ/значення (назва мережі/колір бренду), нам знадобиться синтаксис @each $key, $value in $array. Нижче представлений повний цикл:


Додаткові цикли for

Цикли for можуть повторюватися набагато більше, ніж довжина об’єкта. З їх допомогою можна створювати grid макети (for columns from 1 through 12), пробігатись колірним колесом (for from hue 1 through 360) і рахувати кількість тегів div з псевдоклассом nth-child і згенерованим контентом. Давайте почнемо з того, що пробіжимося в циклі через 36 елементів div, будемо присвоювати їм номери і задавати фон за допомогою :nth-child.

У Sass для цього є спеціальний синтаксис for: @for $count from $start through $finish, де $start і $finish – цілочисельні значення. Якщо перше значення більше другого, Sass запустить зворотний відлік.

Ключове слово through означає, що наш цикл буде повторюватися 36 разів. Також можна використовувати ключове слово to, але тоді останнє значення не буде включатися: @for $i from 1 to 36 повториться тільки 35 разів.

Варто відзначити, що нумерацію з допомогою nth-child в CSS можна написати і без препроцесорів. В CSS немає структури циклів, але в ньому є counter() – функція, яку можна інкрементувати за будь-яких DOM умов. Дану функцію можна використовувати в генерованому контенті. На жаль, її не можна використовувати за межами властивості content (поки що), тобто наш фон не застосується:


Система сіток

Час від часу я використовую інкрементні цикли в абстрактному Sass, але майже ніколи в цих стилях. Виняток становлять тільки генеровані нумеровані селектори, створювані з допомогою nth-child (як у прикладі вище) або за допомогою автоматичного генерувння класів (часто використовуються в системах сіток). Давайте побудуємо просту систему сіток без роздільників, щоб ускладнити обчислення:


Унікальні аватарки

Не так давно на сайті OddBird ми проектували додаток з дефолтними аватарками користувачів. Ми хотіли, щоб дефолтні аватарки були максимально унікальними. Зрештою, ми створили лише 9 унікальних іконок і використовували цикли, щоб трансформувати їх у 1296 різних аватарок. Більшість користувачів ніколи не побачать дублікат.

У всіх аватарів 5 атрибутів:

<svg class="avatar" data-dark="1" data-light="2" data-reverse="true" data-rotation="3">
<use xlink:href="#icon-avatar-1" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>

  • 🡲 форма початкової іконки (9 варіантів);
  • 🡲 поворот на 0, 90, 180 або 270 градусів (4 варіанти);
  • 🡲 темний колір заливки (6 варіантів);
  • 🡲 світлий колір фону (6 варіантів);
  • 🡲 атрибут true/false, інвертування кольору (2 варіанти).
  • 🡲 У коді 6 кольорів і три цикли:
  • 🡲 @for $i from 0 through 3 дає нам 4 повороту;

@for $i from 1 through length($colors) дозволяє пробігатись по циклу за списком кольорів ($colors) і присвоювати кожному кольору число ($i). Зазвичай я б скористався циклом @each для колекції кольорів, але з циклом @for легше, коли потрібно присвоїти число кожного елемента;

Вкладений @each $in reverse (true, false) дозволяє нам перевертати передній і задній фон для кожної комбінації кольору. Кінцевий результат Sass:


Загальні цикли while

Цикли while використовуються рідко, але я час від часу використовую їх. Для мене вони найбільш корисні, коли мені потрібно пройтись по якомусь шляху і дізнатися, що наприкінці. Я не хочу проходитись по циклу через всю колекцію або задане число ітерацій, я хочу проходитись по циклу доти, поки не знайду те, що шукав. Такі цикли я використовую в абстрактних засобах, але це не щось, що вам буде потрібно кожен день.

Я створив інструмент, який зберігає і маніпулює кольорами в Sass. Зберігання кольорів в змінних – напевно, найчастіший випадок використання в будь-яких препроцессорах. Більшість робить так:

$pink: #E2127A;
$brand-primary: $pink;
$site-background: $brand-primary;

Розумію, що pink, швидше за все, не єдиний колір на вашому сайті, але мені поки що знадобиться тільки він. Я спеціально привласнив кілька імен, так як корисно задавати шар абстракції – від простих кольорів (pink) до більш широких шаблонів (brand-primary) і конкретних кейсів (site-background). Також я хочу перевести список кольорів у палітру, яку буде розуміти мій препроцесор. Я повинен сказати, що всі ці значення пов’язані і входять в шаблон. Для цього я зберігаю всі кольори теми у одній карті Sass пар ключ-значення:

$colors: (
pink: #E2127A;
brand-primary: pink;
site-background: brand-primary;
);

Навіщо? Так я можу вказати генератор стилів в одну змінну і автоматично створити оновлену палітру кольорів. Але є і побічні ефекти, спосіб не для всіх. Карта не дозволяє мені робити пряме призначення в парах, як я можу це робити зі змінними. Щоб знайти значення для кожного кольору, мені потрібно пройти шлях із ключових імен в циклі while:

Я завжди так роблю, але якщо ви спробуєте пошукати мій код для Sass циклу @while, ви не знайдете його. Тому що те ж саме можна написати з допомогою рекурсивної функції, що зробить код повторно:

Тепер, коли мої кольори успішно зібрані в одній змінній, я можу за допомогою іншого циклу згенерувати палітру кольорів. Приклад Sass:

Упевнений, ви можете написати набагато краще, ніж я.

Зациклюємося!

Якщо ви не впевнені, коли використовувати цикли в своєму коді, а коли ні, слідкуйте за повтореннями. У вас в коді є безліч селекторів, наступних схожим шаблоном, або обчислення, які постійно повторюються? Як зрозуміти, який цикл краще підходить:

  • 🡲 Якщо ви можете перерахувати елементи в циклі і присвоїти їм імена, використовуйте цикл for-each.
  • 🡲 Якщо важливіше кількість повторень, ніж набір вихідних елементів, або якщо потрібно дізнатися загальну кількість елементів, використовуйте цикл for.
  • 🡲 Якщо в один цикл потрібно входити з різними даними, спробуйте використовувати рекурсивні функції.
  • 🡲 Для всього іншого (майже ніколи) використовуйте цикл while.

Бажаємо успіхів!