В экосистеме JS-фреймворков распространён подход CSS-in-JS, когда стили пишутся в JS-файлах. В современных браузерах есть встроенный механизм для работы со стилями в JS — Constructable Stylesheets. С его помощью можно создавать таблицы стилей и применять их глобально к документу или Shadow Root.
Таблица стилей создаётся через конструктор
CSSStyleSheet. Методы replace и replaceSync формируют стилевые правила из строки. В массиве adoptedStyleSheets у document или Shadow Root хранятся текущие таблицы стилей, туда же можно добавить созданную через API:const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync(`
.element {
color: #4e4e4e;
text-decoration: underline;
}
`);
/* применение к документу */
document.adoptedStyleSheets.push(stylesheet);
const div = document.createElement('div');
div.attachShadow({ mode: 'open' });
/* применение к Shadow Root */
div.shadowRoot.adoptedStyleSheets.push(stylesheet);
Из объекта
CSSStyleSheet можно получить информацию о стилях: список правил и медиа-запросов, родительскую таблицу стилей (при использовании @import) и т.д. Интерес представляет список правил, с которым можно работать:const firstRule = stylesheet.cssRules[0];
console.log(firstRule.cssText);
// '.element { color: #4e4e4e; text-decoration: underline; }'
console.log(firstRule.selectorText);
// '.element'
console.log(firstRule.style.color);
// '#4e4e4e'
console.log(firstRule.style.textDecoration);
// 'underline'
console.log(firstRule.style.cssText);
// 'color: red; text-decoration: underline;'
А ещё в JS появились Import Attributes. Можно импортировать стили как ES-модуль, указав тип
css через оператор with. При импорте таким образом создаётся экземпляр CSSStyleSheet. Поэтому можно писать стили во внешних файлах и импортировать их в JS:/* styles.css */
.element {
color: #4e4e4e;
text-decoration: underline;
}
import syncStylesheet from '/styles.css' with { type: 'css' };
console.log(syncStylesheet.cssRules[0].cssText);
// '.element { color: #4e4e4e; text-decoration: underline; }'
/* или через динамический импорт */
const dynamicStylesheet = await import('/styles.css', { with: { type: 'css'} });Написав небольшую обвязку вокруг этих API, можно получить что-то вроде CSS Modules или Styled Components.