Несколько сирен прозвучали пару недель назад, когда рабочая группа CSS (CSSWG) решила добавить if()
условный оператор в спецификацию CSS Values Module Level 5. Мое внимание привлек пост Лии Веру X в тот же день:
Исторический день для CSS 😀🎉
Если вы пишете какие-либо компоненты, используемые и/или стилизованные другими, вы знаете, насколько это важно!
background: if(style(–variant: success), var(–green));
Даже если вы этого не сделаете, это позволит делать такие вещи, как:padding: if(var(–2xl), 1em, var(–xl) или var(–m),… pic.twitter.com/cXeqwBuXvK— Леа Вероу (@LeaVerou)
Лия — та, кто открыла проблему на GitHub, приведшую к обсуждению, и по счастливому совпадению — или, может быть, по счастливой случайности — решение пришло в ее день рождения. Это должен был быть довольно бурный день! Что вы получили на свой день рождения? «О, вы знаете, просто принятое предложение по спецификации CSS». Дико, просто дико.
Принятое предложение — это зеленый свет для CSSWG, чтобы работать над идеей с намерением распространить проект спецификации для дальнейшего внесения и рассмотрения на пути, как мы надеемся, к тому, чтобы он стал рекомендуемой функцией CSS. Так что, это будет горячая минута, прежде чем что-либо из этого будет готово, то есть, если это будет готово полностью.
Но идея применения стилей на основе условного требования очень захватывающая и стоит того, чтобы взглянуть на нее пораньше. Я набросал несколько заметок об этом в своем блоге в тот же день, когда Ли опубликовала пост в X, и подумал, что вынесу их сюда для потомков, а также соберу больше подробностей, которые появились с тех пор.
Многие предложения рождаются из ранее отклоненных предложений и if()
ничем не отличаются. И, действительно, в последние дни мы получили несколько функций CSS, которые позволяют использовать условную стилизацию — :has()
и запросы стилей контейнеров являются двумя наиболее очевидными примерами. Ли даже приводит тикет 2018 года , который выглядит и читается очень похоже на принятое предложение.
Разница?
Запросы стилей уже были реализованы, и мы могли просто ссылаться на тот же синтаксис для условий (плюс
media()
иsupports()
из предложения Таба@when
), тогда как в предложении 2018 года то, как будут работать условия, было в значительной степени не определено.Леа Вероу, «Встроенные условные операторы в CSS?»
Мне нравится, как Ли указывает на то, что CSS продолжает описывать, что CSS всегда был условным языком:
Ребята… В CSS с самого начала были условные операторы. Каждый селектор по сути является условным оператором!Леа Вероу, «Встроенные условные операторы в CSS?»
Правда! Cascade — это средство оценки селекторов и сопоставления их с элементами HTML на странице. То, что if()
приносит в таблицу, — это способ записи встроенных условий с селекторами.
Все сводится к следующему:
<if()> = if( <container-query>, [<declaration-value>]{1, 2} )
…где:
Все это на данный момент концептуально, и ничего не высечено на камне. Мы, вероятно, увидим изменения, пока CSSWG работает над этой функцией. Но в текущем виде идея, похоже, вращается вокруг указания условия и установки одного из двух объявленных стилей — одного как стиля «по умолчанию» и одного как «обновленного» стиля при совпадении.
.element {
background-color:
/* If the style declares the following custom property: */
if(style(--variant: success),
var(--color-green-50), /* Matched condition */
var(--color-blue-50); /* Default style */
);
}
В этом случае мы ищем style()
условие, при котором переменная CSS --variant
объявляется и ей присваивается значение success
, и:
--variant
установлено значение success
, мы устанавливаем значение , success
которое --color-green-50
является переменной, сопоставленной некоторому значению зеленоватого цвета.--variant
не установлено значение success
, мы устанавливаем значение , success
которое --color-blue-50
является переменной, сопоставленной с некоторым значением голубоватого цвета.Стиль по умолчанию необязателен, поэтому я думаю, что в некоторых случаях его можно опустить для лучшей читаемости:
.element {
background-color:
/* If the style declares the following custom property: */
if(style(--variant: success),
var(--color-green-50) /* Matched condition */
);
}
В определении синтаксиса выше упоминается, что мы могли бы поддерживать третий аргумент в дополнение к соответствующему условию и стилю по умолчанию, что позволяет нам вкладывать условия друг в друга:
background-color: if(
style(--variant: success), var(--color-success-60),
if(style(--variant: warning), var(--color-warning-60),
if(style(--variant: danger), var(--color-danger-60),
if(style(--variant: primary), var(--color-primary)
)
),
)
);
Ой, похоже, там происходит какая-то дикая инициация! Ли продолжает предлагать синтаксис, который приведет к гораздо более плоской структуре:
<if()> = if(
[ <container-query>, [<declaration-value>]{2} ]#{0, },
<container-query>, [<declaration-value>]{1, 2}
)
Другими словами, вложенные условия гораздо более плоские, поскольку их можно объявить
вне начального условия. Та же концепция, что и раньше, но другой синтаксис:
background-color: if(
style(--variant: success), var(--color-success-60),
style(--variant: warning), var(--color-warning-60),
style(--variant: danger), var(--color-danger-60),
style(--variant: primary), var(--color-primary)
);
Таким образом, вместо того, чтобы помещать одно if()
утверждение в другое if()
, мы можем объединить все возможные условия соответствия в одно утверждение.
Мы пытаемся сопоставить if()
условие, запрашивая стили элемента. Соответствующей size()
функции для запроса измерений нет — запросы контейнера неявно предполагают размер:
.element {
background: var(--color-primary);
/* Condition */
@container parent (width >= 60ch) {
/* Applied styles */
background: var(--color-success-60);
}
}
А запросы контейнера становятся запросами
стиля , когда мы вместо этого вызываем style()
функцию:
.element {
background: orangered;
/* Condition */
@container parent style(--variant: success) {
/* Applied styles */
background: dodgerblue;
}
}
Запросы стиля кажутся мне гораздо более осмысленными, когда они рассматриваются в контексте if()
. Без if()
, легко усомниться в общей полезности запросов стиля . Но в этом свете становится ясно, что запросы стиля являются частью гораздо более обширной картины, которая выходит за рамки одних только запросов контейнеров.
Еще много чего нужно выяснить о синтаксисе if()
. Например, Таб Аткинс описывает возможный сценарий , который может привести к путанице между тем, что такое совпадающее условие и параметрами стиля по умолчанию. Так что, кто знает, чем все это в итоге обернется!
Как мы уже отметили, if()
это далеко не единственный тип условной проверки, уже предусмотренный в CSS. Как бы выглядело написание встроенного условного оператора, который проверяет другие условия, такие как @supports
и @media
?
В коде:
background-color: if(
supports( /* etc. */ ),
@media( /* etc. */ )
);
Проблема будет в контейнере, поддерживающем запросы размера. Как упоминалось ранее, явной функции нет size()
; вместо этого это больше похоже на анонимную функцию.