Estou usando new CSSStyleSheet()
para criar uma folha de estilo personalizada para um documento específico onde os estilos dependem do conteúdo.
Dentro dessa folha de estilo, adiciono variáveis CSS com o seletor raiz. Os elementos do projeto serão então selecionados por um ID e receberão regras específicas que utilizam essas variáveis. A questão é que eu não conheço os IDs antes e, como tal, os estilos e os seletores devem ser criados dinamicamente.
Até agora funciona perfeitamente.
O problema que enfrento agora é que durante alguns eventos específicos, o valor das variáveis CSS deve mudar. Tentei alterá-lo usando insertRule()
com e sem índice. Eu também tentei replace()
e replaceSync()
. Nada alcançou o resultado desejado.
A questão agora é: como posso alterar o root
estilo desta folha de estilo?
const CSS = new CSSStyleSheet();
const rootRule = `:root{
--background: red;
}`;
CSS.insertRule(rootRule, 0);
const bodyRule = `body {
background: var(--background);
}`
CSS.insertRule(bodyRule, 1);
document.adoptedStyleSheets = [CSS];
// change color
BUTTON.addEventListener('click', function() {
console.log('button clicked');
const newRule = `:root {
--background: blue;
}`
CSS.insertRule(newRule, 0);
})
<button id="BUTTON">Change background-color</button>
O problema se deve à especificidade. A nova
--background: blue
regra está sendo aplicada, mas foi substituída pela regra existente:A solução rápida e suja para isso seria usar
!important
, embora isso não seja o ideal:Uma abordagem melhor seria remover a regra original antes de adicionar a nova. Isso pode ser feito usando
deleteRule()
. Aqui está um exemplo prático:Você está inserindo a regra no CSSStyleSheet corretamente (você pode saber adicionando
console.log(CSS.cssRules[0].cssText);
ao botão clique para verificar se ela está inserida). O problema que você está tendo é que seu código está sendo inserido no index0
, ou seja, antes do seurootRule
. Esta é a posição padrão, mas você também a especifica comCSS.insertRule(newRule, 0);
. E como as regras para seletores específicos em CSS são substituídas por regras posteriores dos mesmos seletores,rootRule
ainda é aquela que está sendo aplicada.Mude para
CSS.insertRule(newRule, 2);
e você verá que funciona: