Переопределение: корневые переменные CSS из внутренних областей
В нашей системе проектирования в Qaru мы используем Less для компиляции значений цвета CSS.
У нас есть глобальные переменные Less, такие как @orange-500
, которые часто модифицируются для состояний наведения, стилевого оформления границ, цветов фона и т.д.
В Less это записывается как darken(@orange-500, 5%)
. Я пытаюсь добиться чего-то похожего, используя собственные переменные CSS. Переключение на CSS-переменные позволит нам быстрее отправлять функции, основанные на их создании (Stack Exchange Network, Dark Mode и т.д.), С меньшим количеством строк CSS, при этом позволяя менять переменные в медиазапросе (высокая контрастность, темный режим и т.д.).).
Этот пример переопределения значения яркости наших цветов в hsl
работает, когда переменные находятся в классе CSS:
.card {
--orange: hsl(255, 72%, var(--lightness, 68%));
background: var(--orange);
}
.card:hover {
--lightness: 45%;
}
<div class="card">
Hello world
</div>
Ответы
Ответ 1
Это ограниченная проблема. То, как вы это делаете, вы наследуете --orange
от :root
, а --orange
в :root
имеет легкость 68%.
Чтобы изменить его, вам нужно изменить область действия переменной --orange
на элемент, который будет искать новое значение --lightness
. Есть несколько способов сделать это:
Вариант 1: продублируйте переменную --orange
для элемента:
:root {
--lightness: 68%;
--orange: hsl(255, 72%, var(--lightness));
}
.card {
background: var(--orange);
--orange: hsl(255, 72%, var(--lightness));
}
.card:hover {
--lightness: 45%;
}
<div class="card">
Hello world
</div>
Ответ 2
Мне было бы интересно узнать, есть ли что-нибудь более идеальное, чем это решение, но в качестве возможного обходного пути вы можете разбить свои CSS-переменные немного дальше и построить значения в определениях стилей элементов следующим образом:
:root {
--orangeColor: 37,72%;
--redColor: 1,72%;
--blueColor: 215,72%;
--greenColor: 126,72%;
--LumDefault: 68%;
--LumDark: 45%;
--LumLight: 80%;
}
.card {
background: hsl(var(--orangeColor), var(--LumDefault));
}
.card:hover {
background: hsl(var(--orangeColor), var(--LumDark));
}
.card:active {
background: hsl(var(--redColor), var(--LumDark));
color: hsl(var(--greenColor), var(--LumLight));
}
<div class="card">
Hello world
</div>
Ответ 3
Простое решение состоит в том, чтобы поместить переменные CSS в отдельный файл CSS, а затем заменить их по мере необходимости. Например, медиа-запрос для поддержки темного режима может выполнить обмен, или вы можете использовать JavaScript, предварительно запеченную тему и т.д.
Что хорошего в этом, так это обмен CSS файлом с определениями переменных, который изменяет рендеринг CSS в режиме реального времени.
Предположим, вы используете медиа-запросы для светлого/темного режима. Если браузер понимает и запрашивает "темный режим", то загружается только первый файл. Тем не менее, если браузер не понимает эти медиазапросы, по умолчанию используется light.css, поскольку оба CSS файла загружены, но последующие правила переопределяют предыдущие правила.
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="/light.css" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)">
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css">
Внутри этих таблиц стилей вы хотите использовать псевдокласс :root
, так как он в основном такой же, как HTML, но обладает большей специфичностью в большинстве браузеров.
light.css
:root {
--text-color: #333;
--background-color: #fff;
}
dark.css
:root {
--text-color: #dadada;
--background-color: #333;
}
Также обратите внимание, что упрощение переменных и построение полного правила внутри элемента - хорошая идея, как упоминает Трэвис в этом ответе.
style.css (основной документ по стилю)
body {
color: var(--text-color);
background-color: var(--background-color);
}
В качестве дополнительного примечания вы можете прочитать свойство CSS color-scheme
, чтобы получить немного лучшую поддержку с нативными элементами браузера.