Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавляет статью про Псевдоприватные кастомные свойства #5577

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
156 changes: 156 additions & 0 deletions recipes/virtual-variables/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: "Виртуальные переменные"
descriptioin: "Как создать миксины на CSS"
---

## Введение

Веб-платформа не стоит на месте и стремительно развивается. Относительно недавно был принят стандарт **нативного нестинга в CSS**.
Раньше такая технология была только в препроцессорах и позволяла весьма удобно работать с БЭМом:
Alex-Andr-19 marked this conversation as resolved.
Show resolved Hide resolved

```scss
.parent-block {
...

&__child-element {
...

&_modificator-1 { ... }
&_modificator-2 { ... }
&_modificator-3 { ... }
}
}
```

Ранее уникальной для препроцессоров таких как **Less, SASS и Stylus** была возможность создавать переменные прямо в стилях, что не мог предоставить CSS.
Но этот пункт относительно давно перестал быть уникальной частью этих библиотек – были созданы `custom variables` в CSS'е:
TatianaFokina marked this conversation as resolved.
Show resolved Hide resolved

```css
:root {
--text-primary: #ffffff;
--text-secondary: #999999;

--text-negative: #f00000;
}

span.error {
color: var(--text-negative);
}
```

## Проблемы миксинов

Возвращаясь к теме с **нативным нестингом в CSS**, я не могу не сказать о возникших сложностях в работе с последними версиями препроцессоров (в моём случае с SASS'ом).

Сразу оговорю – дальше будет показан код на SCSS в режиме `api: "modern-compiler"`.

В нативном нестинге CSS'а считается невалидной следующая ситуация:

```css
.parent-block {
display: flex;

&__child-element {
...;
}

gap: 20px;
}
```

в отличии от SASS'а.

Я полностью поддерживаю данное решение, потому что такая ситуация рушит читаемость кода.
Но в SASS'е такая ситуация вполне возможна на уровне интерпритации в CSS. Пример:

```scss
.parent-block {
display: flex;
@include child-element-mixin;
gap: 20px;
}
```

В последних версиях SASS начинает кидать варнинги на такие кейсы.

## Решение

На случай неуникальных, но достаточно больших стилей с возможностью кастомизации я нашёл, как мне кажется, хорошее решение.

В CSS при выозове переменной через функцию `var()` можно передать второй аргумент, который вернётся, если переменная отсутствует:

```css
color: var(--text-primary, #ddd);
```

Пытаясь найти способ реализовать миксины на CSS'е, я набрёл на видео (ссылку потерял), в котором была концепция "виртуальных" CSS переменных. Пример:

```css
span.plain-text {
--_text-color: var(--text-color, #ddd);
Copy link
Contributor

@baileys-li baileys-li Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это так называемые sudo кастомные свойства / псевдо приватные кастомные свойства
Скорее всего речь про видео Кевина Повелла

Так же оригинальный рецепт Леи Веру

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, именно из этого видео взял идею. Обязательно вставлю как источник

color: var(--_text-color);
}
```

Смысл в том, чтобы использовать атомарный класс как имя миксина, а в качестве аргументов для нашего
атомарного класса будут CSS переменные, которые возвращаются в переменные, которые уже и применяются.

Пример возможности кастомизации миксина выше:
```html
<span class="description plain-text">Text</span>
```
```css
.plain-text {
--_text-color: var(--text-color, #ddd);
color: var(--_text-color);
}

.description {
--text-color: #fff;
}
```

## Применение

Я понял какой потенциал стоит за таким подходом я решил применить это к стилизации размера текста:

```css
[class*="static-font"] {
--_font-size: var(--font-size, 1em);
--_line-height: var(--line-height, calc(var(--_font-size) + 4px));

font-size: var(--_font-size);
line-height: var(--_line-height);
}

.static-font__M {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вне контекста этот код выглядит перегруженным и нарушением принципа KISS.

Не понятно, что мешает сделать так

<span class="static-font another-class">Lorem ipsum</span>
.static-font {
    font-size: 1em;
    line-height: calc(1em + 4px);
}

.another-class {
    font-size: 20px;
    line-height: 26px;
}

То есть старый добрый каскад даёт тот же эффект при меньшем коде.

Обычно приватные кастомные свойства нужны для компонентных фреймворков, где ты не можешь быть на 100% уверен в каком порядке сборщик соберёт стили. И в итоге тебе, чтобы гарантировано перебить внутренние стили компонента нужно либо перебивать вес селектора, либо делать кастомные свойства с дефолтом (в том числе и псевдо приватные), либо разбить по css слоям, если браузерная поддержка позволяет.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Таким образом, как описал я, в проект может зайти новый разработчик, увидеть все стандартные размеры текста, которые описаны в дизайн системе и легко их применить, воткнув всего один класс.
Так же, если понадобиться создать что-то отличающееся от стандартных шрифтов ему достаточно создать класс который будет иметь в своем названии static-font, реализовать два свойства и все будет работать

--font-size: 20px;
--line-height: 26px;

@media (max-width: 1024px) and (min-width: 510px) {
--font-size: 18px;
--line-height: 22px;
}

@media (max-width: 509px) {
TatianaFokina marked this conversation as resolved.
Show resolved Hide resolved
--font-size: 16px;
--line-height: 20px;
}
}
```

Так как CSS переменные возможно переопределять в медиа запросах, реализация отдельно размера шрифта выглядит
лаконично и понятно.

И вот ещё один небольшой "миксин" для обрезания количества строк:

```css
.clamp-text-lines {
--_lines-count: var(--lines-count, 3);

display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--_lines-count);
overflow: hidden;
}
```
Loading