Эта статья — перевод оригинальной статьи «CSS Custom Functions are coming … and they are going to be a game changer!»

Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

В настоящее время Chrome использует прототип CSS Functions из спецификации css-mixins-1.

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

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

@function --negate(--value) {
	result: calc(-1 * var(--value));
}

Вы вызываете функцию как бы напрямую - нет необходимости в var() или т. п. - и можете использовать ее везде, где принимается значение. Например:

:root {
  padding: --negate(1px); /* = -1px */
}

Реализация в Chrome Canary на данный момент не завершена, и дата отправки не назначена, но вы уже можете опробовать WIP-реализацию, включив флаг Experimental Web Platform Features.

Я очень рад этой грядущей функции, поскольку она откроет множество возможностей, гораздо более значимых, чем тот пример с --negate из спецификации.

Например, ограничение функции CSS light-dark() заключается в том, что она работает только со значениями <color>. Благодаря Custom Functions вы можете написать свою собственную --light-dark(), которая будет работать с любым значением.

@function --light-dark(--light, --dark) {
	result: var(--light);
	
	@media (prefers-color-scheme: dark) {
		result: var(--dark);
	}
}

Если вы посещаете сайт в темном режиме, будет возвращено значение --dark. В противном случае будет возвращено значение --light.

Например, вы можете использовать эту --light-dark(), чтобы иметь разный вес шрифта - то, что советует делать Робин:

:root {
	color-scheme: light dark;
  font-family: "Literata", serif;
	
	color: light-dark(#333, #e4e4e4);
	background-color: light-dark(aliceblue, #333);
	font-weight: --light-dark(500, 300);
}

Вот демонстрационный пример, в котором используется этот код (и который также изменяет font-size и некоторые свойства, связанные с border): https://codepen.io/bramus/pen/EaYBJJx

?‍♂️ Обратите внимание, что пользовательская функция --light-dark() не является полной копией light-dark(). Встроенная функция light-dark() может возвращать различные значения в зависимости от используемой цветовой схемы элемента, в то время как --light-dark() полагается на глобальное предпочтение светлого/темного. Возможность реагировать на используемые значения не покрывается самой @function. Для этого нам также понадобится функция CSS if(), которая также находится в разработке (но пока не готова к тестированию). Контейнерные запросы внутри функции также работают - чтобы учитывать родительский контекст - но это пока не прототипировано.

?️ Также обратите внимание, что для значений <color> я все еще использую встроенную функцию light-dark(), но мог бы использовать и свою собственную. У меня есть подозрение, что встроенная версия работает быстрее, но для этого нужен соответствующий бенчмарк.

В этой статье я ограничился лишь базовым примером, не раскрывая слишком много деталей. Не упомянуты, например, значения по умолчанию для параметров функции и то, как указать типы для любого из них. Для этого вы можете покопаться в спецификации. Обратите внимание, что в спецификации еще много подвижных частей, поскольку на нее влияют результаты работы над прототипом, который создает Chrome.

Чтобы следить за ходом работы Chrome над прототипом, подпишитесь на рассылку crbug/325504770, нажав на звездочку рядом с ее названием.

Комментарии (7)


  1. Mozzzez
    13.02.2025 06:15

    Отрицательный паддинг?


  1. ant_dgt
    13.02.2025 06:15

    css потихоньку превращается в js


    1. isumix
      13.02.2025 06:15

      Да, тоже об этом подумал. Не лучше было бы переиспользовать части js вместо изобретения своего собственного dsl, по крайней мере в синтаксисе? Двигаться в сторону унификации.


  1. JerryI
    13.02.2025 06:15

    Мне интересно, комитет прям уверен, что это необходимо? Разве в 2025 возможности webui не безграничны? Новые фичи это опять же дополнительная нагрузка на процессор, раздувание размеров электронов и браузеров. Почему нельзя сказать: стоп, окей, мы дали достаточно возможностей для того, чтобы сделать любое настольное приложение в вебе.


    1. johngetman
      13.02.2025 06:15

      ну нагрузка на проц почти никакущая будет, но проблема в другом - это лишняя нагрузка на программистов)


      1. JerryI
        13.02.2025 06:15

        А все граничные случаи, оптимизации вычислений в cssdom наверное тысячу строчек кода займут. Электрон сейчас 98мБ, станет еще на 2мБ больше и так далее. :(

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


        1. jakobz
          13.02.2025 06:15

          Лучше уж так, чем добавлять по 50 новых встроенных функций. Я бы с радостью бы поменял все хитрые градиенты, и прочие border-radius, на paint api. И уверен что браузер бы от этого бы стал проще и легче.