Eai tudo bem? Depois de alguns meses sem postar algo aqui, finalmente chegou a hora de esclarecer algo sobre o tailwindcss.
Abri um tópico no frontendbr/forum#2248 sobre o assunto e até consegui uma breve explicação do criador do tailwindcss.
Mas ficou no ar a tarefa de testar o que Adam disse para ver como realmente funciona e é isso que vou fazer abaixo.
Como o tailwindcss define custom properties
Ao abrir o código final do tailwindcss você verá as custom properties definidas no seletor * asterisco, que tem uma especifidade baixa, mas maior que :root e tem efeito sobre todos os elementos de uma página.
*,:after,:before { /* <-- por que não usam :root aqui? */
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: #3b82f680;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
O que me chamou a atenção foi o seletor usado *,:after,:before porque não usar :root?
A natureza das propriedades definidas
Notei que todas as propriedades como --tw-scale-x, --tw-rotate, --tw-translate-x são usadas em propriedades de CSS que tem multiplos valores ou funções aplicáveis em uma só propriedade.
Por exemplo, a propriedade transform é usada com 1 ou mais funções como valor:
.transform {
transform: scale(1.5) rotate(45deg) translateX(10px);
}
Veja abaixo, como a classe .rotate-45 é definida no tailwindcss:
.rotate-45
--tw-rotate: 45deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
rotate(var(--tw-rotate))
skewX(var(--tw-skew-x))
skewY(var(--tw-skew-y))
scaleX(var(--tw-scale-x))
scaleY(var(--tw-scale-y));
}
Separei o valor do transform linha a linha para ficar mais fácil de ver.
Pois essa funcionalidade do CSS de aceitar multiplas funções como
valor de uma só propriedade é a razão pela qual o tailwindcss decidiu
usar o seletor *,*:before,*:after para como o author
explicou no tweet
para garantir que a custom property seja redefinida em cada
elemento e que não sejam herdadas
.
Reproduzindo o problema que ele resolve
Como a classe .rotate-45 altera o valor da custom property --rotate e no CSS as variáveis são herdadas pelos elementos filhos, o exemplo abaixo pode ser um cenário válido para reproduzir o problema que o tailwindcss resolveu.
:root { /*<-- note que usei :root e não * */
--rotate: 0;
}
.rotate-45 {
--rotate: 45deg;
transform: rotate(var(--rotate));
}
.rotate {
transform: rotate(var(--rotate));
}
<div class="rotate-45">
........45deg
<div class="rotate">
........90deg
<div class="rotate">
........135deg
</div>
</div>
</div>
Demonstração abaixo:
Qual é o problema?
Faz sentido que cada elemento rode 45 graus, porém como cada classe do tailwindcss irá aplicar todas as variáveis de transform, os valores das custom properties precisam ser redefinidas.
Caso contrário, o elemento pai tem um rotate de 45 graus um dentro do outro indo para 90 graus e 135 graus.
Porém, se o elemento filho tiver apenas um scale de 1.5 sem rotação, por causa que a classe rotate-45 muda o valor da custom property que será herdada pelos filhos, o elemento filho também terá uma rotação de 45 graus "indesejada" junto com o scale desejado.
Solucionando o problema
Usar o seletor asterisco para redefinir o valor da custom property em cada elemento filho.
Usando o mesmo HTML anterior, porém com este CSS:
* { /*<-- note que usei * e não :root*/
--rotate: 0;
}
.rotate-45 {
--rotate: 45deg;
transform: rotate(var(--rotate));
}
.rotate {
transform: rotate(var(--rotate));
}
Temos a demonstração abaixo: