У CSS насправді вже є логіка булевого типу, хоча й реалізована інакше, ніж звикли бачити розробники в інших мовах програмування. Справжнього булевого типу даних мова поки не має, але вже зараз можна застосовувати принципи true/false для побудови логіки та прапорців у стилях.

Булевий тип зазвичай позначає одне з двох станів: увімкнено або вимкнено, 0 або 1, а найчастіше - true або false.

Ключові слова true та false

У CSS справді існують ключові слова true і false. Найімовірніше, ви вже стикалися з ними під час роботи з @property, де параметр inherits приймає саме ці значення.

@property --myProperty {
  inherits: true;
}

Щоб зберігати й гнучко використовувати ці значення, зручно застосувати кастомні властивості CSS, також відомі як CSS-змінні.

--isTrueOrFalse: true;

Варто зробити цю конструкцію суворішою: зареєструвати кастомну властивість --isTrueOrFalse так, щоб вона могла приймати лише одне з двох значень. Це можливо завдяки правилу @property, яке підтримує синтаксис перелічення ключових слів.

@property --isTrueOrFalse {
  syntax: "true | false";
}

Далі задається початкове значення властивості.

@property --isTrueOrFalse {
  syntax: "true | false";
  initial-value: false;
}

Крім того, можна заборонити успадкування цієї властивості дочірніми елементами.

@property --isTrueOrFalse {
  syntax: "true | false";
  initial-value: false;
  inherits: false;
}

У результаті --isTrueOrFalse стає зареєстрованою кастомною властивістю, яка зберігає лише true або false, за замовчуванням дорівнює false і не передається нащадкам. Це не справжній булевий тип, однак він достатньо точно його імітує для практичних задач.

Таку властивість можна застосувати для умовного стилювання:

@container style(--isTrueOrFalse: true) {
}

Перевіримо, як це працює на реальному прикладі.

Приклад застосування

Уявімо каталог сумок, товари в якому потрібно фільтрувати за типом: рюкзаки, спортивні сумки або обидва варіанти одразу.

Для фільтрації використовуються два чекбокси - «Backpacks» (рюкзаки) та «Duffel bags» (спортивні сумки). Логіка має бути такою: позначення «Backpacks» залишає лише рюкзаки, позначення «Duffel bags» - лише спортивні сумки, а якщо позначені обидва пункти, показуються і рюкзаки, і спортивні сумки, тоді як решта товарів приховується.

Реєстрація кастомних властивостей

Замість того, щоб перелічувати всі можливі комбінації станів :checked та :not(:checked) для чекбоксів і захаращувати селектори, зручніше підмінити ці стани значеннями true або false.

Нереєстровані кастомні властивості теж працюють, однак варто налаштувати саме зареєстровані - заради типобезпеки, продуктивності та контролю над успадкуванням.

@property --isBackpack {
  syntax: "true | false";
  inherits: false;
  initial-value: false;
}

@property --isDuffel {
  syntax: "true | false";
  inherits: false;
  initial-value: false;
}

За замовчуванням обидві властивості мають значення false. Коли користувач позначає чекбокс фільтра, відповідна властивість змінюється на true в якомусь елементі-предку. Підійде будь-який зручний предок, у цьому прикладі обрано :root.

:root {
  &:has(#isBackpack:checked) {
    --isBackpack: true;
  }
  &:has(#isDuffel:checked) {
    --isDuffel: true;
  }
}

Оскільки ці зареєстровані властивості потрібно буде перевіряти у значно глибшому нащадку, елементу :root варто надати ім'я контейнера, щоб потім посилатися на нього у запиті.

:root {
  container-name: root;
  &:has(#isBackpack:checked) {
    --isBackpack: true;
  }
  &:has(#isDuffel:checked) {
    --isDuffel: true;
  }
}

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

Контейнерні запити

Усередині #productsList, де розміщені всі товари, частину сумок потрібно приховати залежно від того, який чекбокс (або обидва) активовано.

Застосування @scope тут не є обов'язковим, але воно допомагає ізолювати елементи усередині #productsList.

@scope(#productsList) {
  @container root style(--isBackpack: true) and style(--isDuffel: true) {
    li:not(.backpacks, .duffels) {
      display: none;
    }
  }
  @container root style(--isBackpack: true) and style(--isDuffel: false) {
    li:not(.backpacks) {
      display: none;
    }
  }
  @container root style(--isBackpack: false) and style(--isDuffel: true) {
    li:not(.duffels) {
      display: none;
    }
  }
}

Запити @container style перевіряють значення --isBackpack та --isDuffel кореневого елемента. Залежно від комбінації true і false, з сітки товарів вилучається певна група сумок.

Ключові слова true та false наочно показують стан елементів фільтра, а їхнє застосування у запитах стилю зберігає цю наочність навіть у комбінованому стані кількох умов одразу.

Подібні сценарії можуть скористатися ключовими словами true та false, зберігаючи їх у кастомній властивості - зареєстрованій або ні. Автор матеріалу рекомендує саме зареєстрований варіант.

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

Джерело: Master.dev Blog