Можно ли добавить имя класса в переменную CSS или есть какой-то другой способ настроить его так, чтобы мне не приходилось манипулировать каждой отдельной переменной напрямую через javascript? Я хотел бы сохранить все свои стили в CSS и просто включить соответствующие классы с помощью JS. Например, если что-то подобное было возможно в CSS:
:root.white{ --bgcol:#FFF; --col:#000; }
:root.black{ --bgcol:#000; --col:#FFF; }
Затем я мог бы просто переключить .black
или .white
из javascript, чтобы вызвать изменение всех переменных. Каков наилучший подход для этого типа установки?
Ответ 1
Это, откровенно говоря, лучший (как и в большинстве идиоматических) подход - использование имен классов, если не вообще отдельных таблиц стилей (как это было уже много-много лет), для оформления целых макетов с помощью пользовательских свойств. Это наиболее "фундаментально CSS" подход с JavaScript, просто являющийся клеем, который заставляет переключение темы работать. Вы действительно не можете сделать намного лучше, чем это.
Для тех, кто не знает, что означает :root
и интересуется, где именно применяются имена классов, это html
элемент (родительский элемент body
). Так что здесь ничего особенного не происходит - вы просто переключаете имена классов в элементе html
. Просто бывает, что глобальные пользовательские свойства традиционно определены для корневого элемента документа, поскольку он находится на верхнем уровне цепочки наследования.
Если у вас есть какие-либо не зависящие от темы пользовательские свойства, а также свойства стиля (т.е. Не настраиваемые свойства), которые применяются к корневому элементу, оставьте их в своем собственном неквалифицированном :root
правило, отделенное от ваших тематических настраиваемых свойств, чтобы они не быть затронутым переключением темы. Вот пример:
const root = document.documentElement;
// Default theme - should assign declaratively in markup, not JS
// For a classless default theme, move its custom properties to unqualified :root
// Again, keep it separate from the other :root rule that contains non-theme props
// Remember, the cascade is your friend, not the enemy
root.classList.add('white');
document.querySelector('button').addEventListener('click', function() {
root.classList.toggle('white');
root.classList.toggle('black');
});
:root {
--spacing: 1rem;
color: var(--col);
background-color: var(--bgcol);
}
:root.white {
--bgcol: #FFF;
--col: #000;
}
:root.black {
--bgcol: #000;
--col: #FFF;
}
p {
margin: var(--spacing);
border: thin dashed;
padding: var(--spacing);
}
<button>Switch themes</button>
<p>Hello world!
Ответ 2
Использование :root
селектор идентично использованию html
, за исключением того, что его специфика выше, поэтому нет проблем с использованием этого подхода.
Например:
:root {
--bg: red;
}
:root.blue {
--bg: blue;
}
// ...
div {
background: var(--bg);
}
Позже вы должны просто изменить html
класс и переменные будут меняться.
Вы можете увидеть пример в этой скрипке.