Erros
Se você está experimentando com CSS-características
min()
e max()
, em seguida, usando diferentes unidades de medida, podemos ser confrontados com mensagens de erro como este: Incompatible units: vh and em
.
Mensagem de erro ao usar unidades diferentes nas funções min () e max ()
Esta mensagem é exibida porque o Sass tem sua própria função
min()
. A função CSS émin()
ignorada como resultado. Além disso, o Sass não pode realizar cálculos usando unidades que não tenham uma relação clara entre elas.
Por exemplo, a relação entre as unidades é
cm
bemin
definida, então o Sass pode encontrar o resultado de uma funçãomin(20in, 50cm)
e não lançará um erro se você usar algo assim em seu código.
A mesma coisa acontece com outras unidades de medida. Por exemplo, todas as unidades de canto estão interligados:
1turn
,1rad
ou1grad
são sempre convertidos para os mesmos valores expressos em unidades deg
. O mesmo é verdade, por exemplo, no caso em 1s
que é sempre igual 1000ms
. 1kHz
sempre igual 1000Hz
, 1dppx
sempre igual 96dpi
, 1in
sempre igual 96px
. É por isso que o Sass pode converter valores expressos nessas unidades entre si e misturá-los em cálculos usados em várias funções, como sua própria função min()
.
Mas tudo dá errado quando não há uma relação clara entre as unidades de medida (como, por exemplo, acima, y
em
e vh
).
E isso não acontece apenas ao usar valores expressos em diferentes unidades de medida. Tentando usar uma função
calc()
internamentemin()
também resulta em um erro. Se você tentar min()
, colocar algo como calc(20em + 7px)
, ele exibe este erro: calc(20em + 7px) is not a number for min
.
Mensagem de erro ocorre quando você tenta usar calc () in min ()
Outro problema ocorre em uma situação ao tentar usar o CSS-variável ou a saída de funções CSS-matemática (tais como
calc()
,min()
,max()
) em CSS-like filtrosinvert()
.
Esta é a mensagem de erro que você pode ver em circunstâncias semelhantes:
$color: 'var(--p, 0.85) is not a color for invert
Usando var () no filtro: invert () resulta em um erro
A mesma coisa acontece com
grayscale()
:$color: ‘calc(.2 + var(--d, .3))‘ is not a color for grayscale
.
Usando o calc () no filtro: tons de cinza () resulta em um erro
de design
filter: opacity()
também está sujeito a problemas semelhantes:$color: ‘var(--p, 0.8)‘ is not a color for opacity
.
Usando var () no filtro: opacidade () resulta em um erro
, mas outras funções utilizadas
filter
, incluindosepia()
,blur()
,drop-shadow()
,brightness()
,contrast()
ehue-rotate()
, trabalhando com as CSS-variáveis é perfeitamente normal!
Descobriu-se que a causa deste problema é semelhante à que afeta as funções
min()
emax()
. O Sass não é built-in funçõessepia()
,blur()
,drop-shadow()
,brightness()
,contrast()
,hue-rotate()
. Mas ele tem suas próprias funções grayscale () , invert () e opacity () . O primeiro argumento para essas funções é o valor$color
. O erro aparece devido ao fato de que, ao usar construções problemáticas, Sass não encontra tal argumento.
Pelo mesmo motivo, surgem problemas ao usar variáveis CSS que representam pelo menos dois
hsl()
ou hsla()
-valores.
Erro ao usar var () em cores: hsl ()
Por outro lado, sem usar Sass, uma construção
color: hsl(9, var(--sl, 95%, 65%))
é perfeitamente correta e CSS funcionando perfeitamente.
O mesmo é verdadeiro para funções como
rgb()
ergba()
:
Erro ao usar var () na cor: rgba ()
Além disso, se você importar o Compass e tentar usar uma variável CSS dentro do
linear-gradient()
ouradial-gradient()
, poderá encontrar outro erro. Mas, ao mesmo tempo,conic-gradient()
você pode usar variáveisemvariáveis sem problemas (é claro, se o navegador suportar essa função).
Erro ao usar var () em segundo plano: gradiente linear ()
O motivo do problema reside no fato de que o Compass tem seu próprio gradiente linear () e
radial-gradient()
funções, mas a funçãoconic-gradient()
nunca existiu.
Em geral, todos esses problemas decorrem do fato de que Sass ou Compass têm funções próprias, cujos nomes são iguais aos do CSS. Tanto o Sass quanto o Compass, ao atender a essas funções, acreditam que vamos usar suas próprias implementações dessas funções, e não as padrão.
Aqui está uma emboscada!
Solução
Esse problema pode ser resolvido lembrando que o Sass diferencia maiúsculas de minúsculas, mas o CSS não.
Isso significa que você pode escrever algo assim
Min(20em, 50vh)
e o Sass não reconhece sua própria função nessa construção min()
. Nenhum erro será gerado. Essa construção será um CSS bem formado que funciona exatamente como esperado. Da mesma forma, para se livrar de problemas com outras funções podem ser, forma não-padrão, escrevendo seus nomes: HSL()
, HSLA()
, RGB()
, RGBA()
, Invert()
.
Quando se trata de gradientes, geralmente uso esta forma:
linear-Gradient()
e radial-Gradient()
. Faço isso porque essa notação é semelhante aos nomes usados em SVG, mas nesta situação, qualquer outro nome semelhante que inclua pelo menos uma letra maiúscula funcionará.
Por que todas essas complicações?
Quase toda vez que eu tuíto algo sobre o Sass, recebo palestras sobre como, agora que você tem variáveis CSS, não precisa mais usar o Sass. Decidi que deveria responder e explicar o motivo de minha discordância com essa ideia.
Em primeiro lugar, observarei que considero as Variáveis CSS extremamente úteis e que as usei para uma variedade de tarefas nos últimos três anos. Mas suponho que você precise se lembrar que usá-los tem um impacto no desempenho. E a busca por um problema no labirinto de chamadas
calc()
pode ser a experiência mais desagradável. As ferramentas de desenvolvedor de navegador padrão ainda não são muito boas nisso. Procuro não me empolgar com o uso de variáveis CSS, para não entrar em situações em que suas desvantagens se mostrem mais do que vantagens.
Não é fácil entender quais serão os resultados da avaliação dessas expressões calc (). Em
geral, se uma variável é usada como uma constante, ela não muda de elemento para elemento, ou de estado para estado (e em tais casos, as variáveis CSS devem definitivamente usar necessário ), ou se a variável não reduzir a quantidade de CSS compilado (resolvendo o problema de repetição criado por prefixos), então usarei uma variável Sass.
Em segundo lugar, o suporte a variáveis sempre foi um motivo muito menor entre os motivos pelos quais uso o Sass. Quando comecei a usar o Sass no segundo semestre de 2012, usei principalmente para loops. Para um recurso que ainda está faltando no CSS. Embora eu tenha movido parte da lógica de loop para o pré-processador HTML (já que isso reduz a quantidade de código gerado e evita a necessidade de modificar HTML e CSS), ainda uso loops Sass em muitos casos. Isso inclui a geração de listas de valores, criação de valores para ajustar gradientes, criação de listas de pontos ao trabalhar com uma função
polygon()
, criação de listas de transformações e assim por diante.
Abaixo está um exemplo do que eu teria feito antes ao criar alguns elementos HTML usando o pré-processador. Não importa qual pré-processador, mas escolhi Pug:
- let n = 12;
while n--
.item
Então, eu criaria uma variável
$n
no Sass (e essa variável deve ter o mesmo valor que no HTML) e iniciaria um loop usando-a, no qual geraria as transformações usadas para posicionar cada um dos elementos:
$n: 12;
$ba: 360deg/$n;
$d: 2em;
.item {
position: absolute;
top: 50%; left: 50%;
margin: -.5*$d;
width: $d; height: $d;
/* */
@for $i from 0 to $n {
&:nth-child(#{$i + 1}) {
transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
&::before { content: '#{$i}' }
}
}
}
A desvantagem disso é que eu teria que alterar os valores no código Pug e no código Sass caso o número de elementos mudasse. Além disso, há muita repetição no código.
Código CSS gerado a partir do código acima
Agora, usei uma abordagem diferente. Ou seja, usando Pug, eu gero índices como propriedades personalizadas e os uso na declaração
transform
.
Este é o código que Pug está planejando fazer:
- let n = 12;
body(style=`--n: ${n}`)
- for(let i = 0; i < n; i++)
.item(style=`--i: ${i}`)
Aqui está o código Sass:
$d: 2em;
.item {
position: absolute;
top: 50%;
left: 50%;
margin: -.5*$d;
width: $d;
height: $d;
/* */
--az: calc(var(--i)*1turn/var(--n));
transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
counter-reset: i var(--i);
&::before { content: counter(i) }
}
Você pode experimentar este código aqui.
Elementos gerados e estilizados usando loops O
uso dessa abordagem reduziu significativamente a quantidade de CSS gerado automaticamente.
CSS gerado a partir do código acima
Mas se você deseja criar algo como um arco-íris, você não pode fazer sem loops Sass.
@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
$unit: 360/$n;
$s-list: ();
@for $i from 0 through $n {
$s-list: $s-list, hsl($i*$unit, $sat, $lum)
}
@return $s-list
}
html { background: linear-gradient(90deg, get-rainbow()) }
Aqui está uma versão funcional deste exemplo.
Plano de fundo multicolorido
Claro, isso pode ser gerado usando variáveis Pug, mas essa abordagem não tem nenhuma vantagem sobre a natureza dinâmica das variáveis CSS e não vai reduzir a quantidade de código passado para o navegador. Como resultado, não faz sentido para mim desistir do que estou acostumado.
Eu uso muito as funções matemáticas integradas do Sass (e do Compass), como funções trigonométricas. Atualmente, esses recursos fazem parte da especificação CSS , mas nem todos os navegadores os suportam ainda. O Sass não tem essas funções, mas o Compass tem, e é por isso que eu costumo usar o Compass.
E, claro, posso escrever minhas próprias funções desse tipo no Sass. Eu fiz isso bem no início, antes que o Compass tivesse suporte para funções trigonométricas inversas. Eu realmente preciso dessas funções, então eu mesmo as escrevi usando a série Taylor . Mas atualmente, esses recursos estão no Compass. Eles são melhores e mais produtivos do que aqueles que eu mesmo escrevi.
As funções matemáticas são muito importantes para mim porque sou um programador, não um artista. Os valores em meu CSS geralmente são gerados a partir de cálculos matemáticos. Estes não são alguns "números mágicos" ou algo que desempenha um papel puramente estético. Um exemplo de seu uso é a geração de uma lista de polígonos regulares ou quase regulares para
clip-path
... Isso é usado, por exemplo, ao criar algo como avatares ou adesivos, cuja forma é diferente de retangular.
Considere um polígono regular cujos vértices estão em um círculo. Arrastar o controle deslizante no exemplo a seguir, que podemos experimentar aqui , nos permite ver onde os pontos são colocados para formas com diferentes números de vértices.
Uma forma com três vértices
Esta é a aparência do código Sass correspondente:
@mixin reg-poly($n: 3) {
$ba: 360deg/$n; //
$p: (); // ,
@for $i from 0 to $n {
$ca: $i*$ba; //
$x: 50%*(1 + cos($ca)); // x
$y: 50%*(1 + sin($ca)); // y
$p: $p, $x $y //
}
clip-path: polygon($p) // clip-path
}
Observe que estamos usando loops e outras construções aqui, que são muito inconvenientes para usar com CSS puro.
Uma versão um pouco mais avançada deste exemplo pode envolver girar o polígono adicionando o mesmo offset (
$oa
) ao canto correspondente a cada vértice. Isso pode ser visto no exemplo a seguir . As estrelas são geradas aqui, que são organizadas de maneira semelhante, mas sempre têm um número par de vértices. Neste caso, cada vértice com índice ímpar está localizado em um círculo cujo raio é menor que o círculo principal ( $f*50%
).
Estrela
Você pode fazerestrelas tão interessantes.
Estrelas
Você pode criar adesivos com bordas (
border
) criados usando modelos incomuns. No presente exemplo, a etiqueta é criado a partir de um único elemento HTML, e o modelo usado para personalizaçãoborder
é criado usandoclip-path
loops de Sass e matemática. Na verdade, existem muitos cálculos aqui.
Adesivos com bordas complexas
Outro exemplo é como criar um fundo para cartões. Aqui, em um loop, usando o operador de módulo e funções exponenciais, um plano de fundo é criado com uma imitação do efeito de pontilhamento.
Efeito dithering
Aqui, também, as variáveis CSS são muito usadas.
Em seguida, você pode pensar em usar mixins para evitar ter que escrever a mesma declaração repetidamente ao estilizar algo como controles deslizantes . Navegadores diferentes usam pseudoelementos diferentes para estilizar os componentes internos de tais controles, portanto, para cada componente, você precisa definir estilos que controlam sua aparência usando diferentes pseudoelementos.
Infelizmente, em CSS, por mais tentador que pareça, você não pode colocar algo como o seguinte código:
input::-webkit-slider-runnable-track,
input::-moz-range-track,
input::-ms-track { /* */ }
Não vai funcionar. Todo este conjunto de regras é ignorado se pelo menos um seletor não for reconhecido. E, como nenhum navegador sabe da existência de todos os três seletores neste exemplo, esses estilos não serão aplicados em nenhum navegador.
Se você deseja que o estilo funcione, você precisará fazer algo assim:
input::-webkit-slider-runnable-track { /* */ }
input::-moz-range-track { /* */ }
input::-ms-track { /* */ }
Mas isso pode fazer com que os mesmos estilos apareçam três vezes no código. E se você precisar, digamos, alterar uma
track
propriedade background
, isso significará que você terá que editar os estilos em ::-webkit-slider-runnable-track
, em ::-moz-range-track
e em ::-ms-track
.
A única solução sensata para este problema é usar mixins. Os estilos se repetem no código compilado, já que não podemos prescindir dele, mas agora, pelo menos, não precisamos inserir o mesmo código três vezes no editor.
@mixin track() { /* */ }
input {
&::-webkit-slider-runnable-track { @include track }
&::-moz-range-track { @include track }
&::-ms-track { @include track }
}
Resultado
A principal conclusão que posso tirar é esta: Sass in é algo que não podemos fazer sem ainda.
Você usa Sass?