Локальні CSS змінні: що, як і навіщо

9 хв. читання

Кастомні CSS властивості (також відомі як CSS змінні) вже тут. Нарешті маємо справжні змінні в CSS! Що я маю на увазі під справжніми змінними? Це змінні, що можуть бути перевизначені динамічно у файлі. Хоча ми вже мали «змінні», дякуючи пре/пост-процесорам (наприклад, Sass і PostCSS), вони компілювалися в CSS і не могли динамічно оновлюватися. Ця ситуація змінилася з CSS змінними, чиї значення по-справжньому можуть бути оновленні.

Прописується змінна за допомогою --. Доступ до неї можна отримати так var(--varName). Ось у такий спосіб можна використовувати CSS змінну, яка встановлює значення кольору тексту як червоний:

div {
  --color: red;
  color: var(--color);
}

CSS змінні дуже потужні

Поговоримо трохи про те, чому динамічні CSS змінні набагато кращі за те, що ми мали раніше.

Динамічний JavaScript + CSS

Завдяки CSS змінним, тепер набагато легше оновлювати значення, встановленні через JavaScript. Це означає, що нам не треба використовувати інлайнове стилювання властивостей чи маніпулювати назвами класів. Замість цього ми просто задаємо значення в наших CSS змінних.

Аби передати значення в :root, можна зробити наступне:

document.documentElement.style.setProperty('--varName', 'propValue')

Це записує значення у корні CSS файлу. Таким чином, якби ми хотіли оновити значення ширини індикатора завантаження, аби вона позначала час завантаження у відсотках, ми могли б зробити щось на зразок цього:

function calculateLoadProgress() {
  let loadProgress = 0;

  // тут код, який змінює значення loadProgress

  return loadProgress;
}

// встановлюємо ширину індикатора
document.documentElement.style.setProperty('--progressBarWidth', calculateLoadProgress());

Це лише один з прикладів! Девід Коршид(David Khourshid) робить насправді цікаві дослідження, використовуючи React і JS Physics Libraries для ідентифікації значень, які він потім передає в CSS змінні. Він говорив про це та інше на CSSconf EU 2017:

Фрагменти динамічних властивостей

Ще, що круто стосовно CSS змінних, так це те, наскільки конкретно ми можемо вказувати значення властивостей. Якщо раніше потрібно було оголошувати декілька різних border властивостей, тепер ми можемо використовувати змінні для оновлення будь-якої частини властивості, включаючи короткий запис властивостей, як, скажімо, border, а також властивості, що приймають невідомий список аргументів, як drop-shadow і градієнти.

Ось приклад: gradient button

.button-gradient {
  background: linear-gradient(var(--gradientAngle), var(--gradientStart),var(--gradientStop));

  --gradientAngle: 60deg;
  --gradientStart: lightpink;
  --gradientStop: lightyellow;
}

.button-gradient:hover {
  --gradientAngle: 0deg;
}

Ми змінюємо лише --gradientAngle, а не background властивість у цілому. Це можна робити й за допомогою JavaScript, та змінювати ці значення по мірі того, як користувач взаємодіє з певним елементом. Фантастика!

Чистота компонентів

CSS змінні також дають нам змогу писати код модулями з модифікаторами чистіше. Типовим буде приклад мультистильових кнопок. Погляньмо на наступний приклад:

button example

Зазвичай, слідуючи правилам методології BEM, ми запишемо класи через пре/пост-процесор, а потім зробимо класи-модифікатори, які перепишуть базові класи.

// Змінні
$primaryColor: lightgreen;
$buttonBgColor: $primaryColor;

// Базовий клас
.button {
  background: $buttonBgColor;
  // інші властивості
}

// Клас-модифікатор
.button--blue {
  background: lightblue;
}

У вищенаведеному прикладі ми записуємо властивість, яка перепише раніше встановлену властивість, у такий спосіб збільшуючи специфічність, розмір файлу, а також роблячи бардак у коді. Та завдяки CSS змінним, нам більше не потрібно переписувати всі базові стилі властивостей! Ми лише оновлюємо змінні!

Це виглядатиме на кшталт цього:

// Змінні
:root {
  --primaryColor: lightgreen;
  --buttonBgColor: var(--primaryColor);
}

// Базовий клас
.button {
  background: var(--buttonBgColor);
}

// Клас-модифікатор
.button--blue {
  --buttonBgColor: lightblue;
}

Переваги локальної області видимості

Більшість прикладів CSS змінних в документаціях, статтях, та демо використовують :root CSS файлу для ініціювання та доступу до змінних. Такий варіант підходить, якщо ми хочемо прописати глобальні змінні, але це не є необхідністю. CSS змінні не мають обов'язково бути оголошенні в :root — вони можуть бути оголошенні в будь-якій частині CSS файлу та існувати в тій конкретній області видимості. Це схоже на змінні в JavaScipt, оголошені за допомогою ключового слова let, для яких областю видимості служить блок ({}), у якому вони знаходяться (також відома як блокова область видимості). Тож, ми можемо вижати максимум з цього при прописуванні стилів наших компонентів.

область видимості

Використання переваг CSS змінних зменшує розмір та покращує семантику наших стильових файлів. Наприклад, ми б не хотіли вписувати --buttonBgColor в :root як глобальну змінну (у попередньому прикладі). Краще було б перейменувати змінну на просто --bgColor і помістити її всередині компоненту <button>. Це робить її більш тісно пов'язаною з батьком, а також має більше сенсу в плані семантики, коли діло стосується порядку в CSS файлі. Є гарне загальне правило: використовуй локальні CSS змінні, поки не знадобляться глобальні. Таким чином, ми не забиваємо :root CSS змінними, що робить код набагато чистішим, коли діло доходить до створення систем проектування та кастомних властивостей.

Організація та приклади

За допомогою Sass, ми можемо піти далі й використати & для вкладеності, аби зробити код чистішим і візуально більш об'єктно-орієнтованим. Тут ми можемо зробити елегантну структуру, розбиту на такі частини:

  1. Стилі за замовчуванням (зазначення властивостей)
  2. Значення за замовчуванням (основні змінні)
  3. Варіювання (оновленні змінні)
.button {
  // 1. Стилі за замовчуванням
  background: var(--bgColor);
  padding: var(--size);
  line-height: var(--size);
  border: var(--outline);
  font-size: var(--size);
  
  // 2. Значення за замовчуванням
  --bgColor: lightgreen;
  --outline: none;
  --size: 1rem;
  
  // 3. Варіювання
  &--blue {
    --bgColor: lightblue;
  }
  
  &--pink {
    --bgColor: hotpink;
  }
  
  &--large {
    --size: 1.5rem;
  }
  
  &--outlined {
    --outline: 2px solid currentColor;
  }
}
Примітка: нам все одно варто використовувати :root для глобальних змінних, як, наприклад, основний колір і скидання розмірів, але локальні змінні зменшують специфічність, що у свою чергу зменшує розмір, а також покращує семантику коду.

Значення за замовчуванням

Значення за замовчуванням можна використовувати для заміщення змінних, у випадку якщо вони не існують. var() приймає 2 параметри, що дає нам таку можливість. У прикладі нижче, якщо --bgColor не визначена, буде використана змінна --colorPrimary. У такий спосіб ми потенційно можемо прибрати другий крок з базового стилю .button і просто оновити значення --bgColor (якби нам було потрібно, щоб основна кнопка мала стиль --colorPrimary).

// 0. Встановлюємо глобальні змінні
:root {
  --colorPrimary: red;
}

.button {
  // 1. Стилі за замовчуванням
  // Якщо --bgColor не визначена, буде використана запасна змінна, а колір буде червоним
  background: var(--bgColor, var(--colorPrimary));
  
  // 2. Значення за замовчуванням
  // Оскільки --bgColor визначена, кнопка залишається кольору lightgreen
  // Якби стрічка нижче була відсутня, колір був би червоним
  --bgColor: lightgreen;

  // ...
}

Стилювання за допомогою &

Навіть якщо наша система компонентів більш комплексна, ми все одно можемо користуватися цією технікою, а для того, щоб зробити код ще виразнішим, ми можемо скористатися CSS препроцесором, як, наприклад, Sass. Стилювання кнопок усередині компоненту card за допомогою & в Sass може виглядати наступним чином:

.button--large {
  .card & {
    --size: 1.7rem;
  }
}

Як результат — усі великі кнопки мають трохи більший --size усередині компоненту card, ніж у будь-якому іншому місці. Амперсанд дозволяє стилювання прямо у блоку елемента, а на виході отримуємо наступне:

.card .button--large {
  --size: 1.7rem;
}

Для наочності пропишемо для .card червоний border і застосуємо до коду вище. Можна помітити, що велика рожева кнопка стала ще більша.

card example

<div class="card">
  <button class="button button--pink button--large">
    Large Pink Button
  </button>
</div>

Браузерна підтримка

CSS змінні широко підтримуються в браузерах, хоча є проблеми з Internet Explorer, а Edge все ще працює над повною підтримкою. Втім, є дві альтернативи, якщо потрібна підтримка цих браузерів і ви хочете розпочати вже сьогодні.

Підтримка браузерів виглядає наступним чином:

browser support

@supports

Дізнатися, чи підтримується певна фіча можна у самому CSS за допомогою запиту @supports. (До речі, ви тільки задумайтесь на хвилину наскільки це крута річ!). @supports — корисний інструмент, якщо ви хочете протестувати найновіші технології, як, наприклад, CSS Grid. У такий спосіб можна перевірити підтримку змінних і прописати "fallback" код для браузерів, які не підтримують:

@supports(--color: red) {
  // тут імплементуємо змінні у код
}

Використовувати @supports, звичайно ж, варіант, але розраховувати на те, що CSS змінні будуть працювати не доводиться (хоча дуже добре працює з CSS Grid!), тому встановлення резервних значень може бути доречнішим рішенням для цієї проблеми.

Встановлення резервних значень

Суть полягає у тому, аби встановити декілька значень. Спочатку, ми записуємо значення, як ми зазвичай робимо, а після, використовуючи змінні:

div {
  --color: red;
  color: red;
  color: var(--color);
}

На даний момент це не актуально, втім, у такий спосіб ми можемо плавно почати вживати CSS змінні, а коли браузери почнуть їх повністю підтримувати, код буде набагато легше рефакторити.

Отже, CSS змінні — потужний інструмент, який дозволяє писати чистий, модульний код, особливо якщо використовувати їх у локальній області видимості.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.6K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація