Less.js: Propriedades personalizadas dentro de funções embutidas como `rgba ()` lançam erro

Criado em 13 nov. 2016  ·  14Comentários  ·  Fonte: less/less.js

A sintaxe do conteúdo das propriedades personalizadas CSS é muito permissiva, mas isso causa problemas ao usar tais propriedades dentro de funções embutidas como rgba()

Exemplo:
Meu projeto permite que o usuário defina a cor de destaque na qual toda a IU do aplicativo e vários componentes personalizados são baseados. E estou usando o formato rgb por causa da necessidade de fade em certos lugares e o CSS não fornece nada como fade(<strong i="8">@color</strong>, 50%) em menos. Dessa forma, posso fazer rgba( var(--color), 0.5 ) . Isso funciona no Chrome e é compatível com o padrão. No entanto, menos gera o seguinte erro error evaluation function 'rgba': color functions take numbers as parameters .

Código de exemplo:

:root {
    --color-accent: 169,57,255;
}
button:hover {
    background-color: rgba(var(--color-accent), 0.2);
    color: rgb(var(--color-accent));
}

Nota: Esta é uma biblioteca drop-in e não quero forçar os usuários a adicionar outra etapa de construção em seu fluxo de trabalho apenas para construir minha biblioteca menos com suas cores. É por isso que estou usando as novas e brilhantes propriedades personalizadas (e também por causa de sua capacidade de escopo).

BTW: Existe alguma solução temporária que iria ignorar esse manuseio estrito e construí-lo de qualquer maneira? Não é como se eu estivesse perdendo um colchete em regras aninhadas.

feature request high priority

Comentários muito úteis

A sintaxe do conteúdo das propriedades personalizadas CSS é muito permissiva, mas isso causa problemas ao usar tais propriedades dentro de funções embutidas como rgba()

Exemplo:
Meu projeto permite que o usuário defina a cor de destaque na qual toda a IU do aplicativo e vários componentes personalizados são baseados. E estou usando o formato rgb por causa da necessidade de fade em certos lugares e o CSS não fornece nada como fade(<strong i="9">@color</strong>, 50%) em menos. Dessa forma, posso fazer rgba( var(--color), 0.5 ) . Isso funciona no Chrome e é compatível com o padrão. No entanto, menos gera o seguinte erro error evaluation function 'rgba': color functions take numbers as parameters .

Código de exemplo:

:root {
  --color-accent: 169,57,255;
}
button:hover {
  background-color: rgba(var(--color-accent), 0.2);
  color: rgb(var(--color-accent));
}

Nota: Esta é uma biblioteca drop-in e não quero forçar os usuários a adicionar outra etapa de construção em seu fluxo de trabalho apenas para construir minha biblioteca menos com suas cores. É por isso que estou usando as novas e brilhantes propriedades personalizadas (e também por causa de sua capacidade de escopo).

BTW: Existe alguma solução temporária que iria ignorar esse manuseio estrito e construí-lo de qualquer maneira? Não é como se eu estivesse perdendo um colchete em regras aninhadas.

escreva assim ~

:root {
    --color-accent: 169,57,255;
}
button:hover {
    background-color: ~"rgba(var(--color-accent), 0.2)";
    color: ~"rgb(var(--color-accent))";
}

Todos 14 comentários

Apenas escape .


Coloquei o rótulo "Solicitação de recurso", pois definitivamente se torna um problema quando as propriedades personalizadas estão em TR. É fácil de consertar desabilitando qualquer detecção de erro para as funções CSS args (embora seja muito triste, pois elimina uma parte importante da linguagem - isto é, nunca mais encontraremos um erro até a depuração em um navegador).

As propriedades personalizadas têm suporte para todos os navegadores, exceto o IE11. Eles provavelmente chegarão ao mercado no próximo ano, então acho que o suporte deve ser implementado em breve.

Less, AFAIK, também não tem testes para a natureza extremamente permissiva dos valores de propriedade customizada. Eles podem conter praticamente qualquer coisa, até ponto e vírgula, contanto que não sejam tokens de nível superior (não contidos entre colchetes ou pares de chaves). Veja: https://www.w3.org/TR/css-variables/#syntax

Uma vez que esta mudança requer uma verificação n-of-args de qualquer maneira (para manter pelo menos alguma validação de erro dentro das funções), também é assumido que a implementação rgba mais recente também suporta a forma de dois argumentos para valores de cores ordinais, por exemplo :

rgba(var(--some), .42); // -> rgba(var(--some), .42)
rgba(#010101, .42); // -> rgba(1, 1, 1, .42)

Como devemos lidar com propriedades personalizadas em args em geral? Tecnicamente, você pode usar var(--some-property) em qualquer lugar, e se Less está tentando interpretar args para funções CSS integradas como rgba() , isso é um problema. Embora eu não saiba por que Less está lançando erros de valor estrito para uma função CSS integrada? Apenas para apoiar expressões?

Eu vejo um monte de funções CSS integradas em https://github.com/less/less.js/blob/master/lib/less/functions/color.js#L34 , e IMO a maioria delas não deveria estar lá. Less não é um linter e essas não são funções Less. Se o analisador tentar ser superinteligente nas funções CSS, ele falhará. Então eu acho que essa é a fonte do problema, que Less atualmente está corrigindo funções regulares de cores CSS em vez de deixá-las passar.

Não tenho certeza se isso foi adicionado para navegadores que ainda não suportavam rgb() rgba() ? Parece que foi adicionado há 4 anos. Talvez o motivo fosse adicionar equilíbrio às funções de cores mais recentes que ainda não são suportadas nos navegadores? 🤔 @lukeapage você ainda está por aqui para responder?

Considerando meu comentário em # 3214, para esse problema a solução rápida seria apenas: "if (nargs <3/4) fallback para css string (por não retornar nada)" nas implementações de funções correspondentes.

(E uma correção mais rígida é colocar verificações para cada arg em cada função para decidir se é avaliável e retornar um objeto de cor ou um fallback de string CSS).

Considerando meu comentário em # 3214, para esse problema, a solução rápida seria apenas: "if (nargs <3/4) fallback para css string (não retornando nada)" nas implementações de funções correspondentes.

E um cheque semelhante para var() ?

darken(rgba(var(--red-value), 2, 3, .4), 5%)

Ou seja: devemos fazer o seguinte:

  1. Permitir passagem de funções se elas não corresponderem a n-args? Presumo que precisaríamos sinalizar funções especialmente, já que não há nada de especial sobre o registro de função (a menos que façamos algo maluco como toString() a função e literalmente contemos args com regex - AFAIK é o único tipo de reflexão em JS; você pode ser capaz de fazer isso com TypeScript, mas isso não nos ajuda)
  2. Lance um erro se a função não correspondente for usada em outra avaliação da função Less.

Este é um problema interessante porque a introdução de propriedades personalizadas tornou as funções CSS impossíveis de resolver em tempo de compilação. Até certo ponto, podemos estar no fim de uma era de pré-processamento estático. Mas essa é uma discussão totalmente diferente.

Este é um problema interessante porque a introdução de propriedades personalizadas tornou as funções CSS impossíveis de resolver em tempo de compilação.

Nada realmente novo. Todas as facilidades necessárias para lidar com isso com o Less estão lá desde sua v1.x - veja abaixo. O único desafio é codificá-lo de forma que não inche.

Presumo que precisaríamos sinalizar funções especialmente, pois não há nada de especial no registro de função

Não, as funções devem retornar undefined (ou null ) se acharem que não podem avaliar seus argumentos: assim (a menos que também detectem que os argumentos são 100% erráticos e é melhor acionar um erro). .
E o valor de retorno indefinido faz com que o avaliador da função retorne à representação inicial da string: Demo .

E um cheque semelhante para var()

Também não, não há necessidade de verificar var ou qualquer coisa específica (basicamente coisas desconhecidas de um futuro CSS). Essa é a questão. O código deve verificar o que é possível avaliar (coisas conhecidas) em vez do que não é possível avaliar (coisas desconhecidas).
(embora os detalhes possam variar dependendo da função específica - isso não é tão importante).


A propósito, observe que --var também é uma função Less embutida (assim como qualquer ident(...) coisa) que simplesmente não é implementada explicitamente (portanto, simplesmente retorna à auto-representação de string ) porque não há necessidade de ser. Mas um plugin (por exemplo) pode substituí-lo por sua própria implementação, que pode retornar um valor potencialmente avaliável.

@ seven-phase-max Oh ok, então você acha que a solução simples é essas funções CSS / Less retornarem indefinidas em vez de gerar um erro (para renderizar no estado em que se encontram)? Isso parece razoável, então se a função não. 2 (como darken() ) não pode interpretar um arg (que neste ponto seria avaliado como um valor anônimo rgba() ?), Ele ainda deve lançar?

Discutindo comigo mesmo:

Também não, não há necessidade de verificar var() ou qualquer coisa específica (basicamente coisas desconhecidas de um futuro CSS).

Por outro lado, não seria um problema (e até mesmo tentador) detectar var especificamente para que a função pudesse distinguir entre rgba(var(...), ...) e rgba(foo, ...) e ainda acionar um erro para o último, mas isso significaria um problema semelhante a ser levantado cada vez que eles adicionam algo novo ao CSS.
(As duas variantes são boas, eu acho, e é mais sobre como encontrar o equilíbrio e / ou prever menos carga para os mantenedores ...).

@ matthew-dean

Isso parece razoável, então se a função não. 2 (como darken ()) não consegue interpretar um arg (que neste ponto seria avaliado como um valor anônimo rgba ()?), Ele ainda deve lançar?

Sim, exatamente - nem mesmo precisamos de nenhum código novo para isso (embora idealmente (funções como darken ) devam ter mensagens de erro mais amigáveis ​​neste caso porque as mensagens atuais do tipo "a.toHSL is not a function" são bastante confuso).

Bem, a outra coisa não mencionada é que algo como rgba(calc(1),1,1) é tratado pelos navegadores como válido (observe os argumentos calc e 3 contra 4), então provavelmente não devemos ser muito espertos sobre isso. Gosto da ideia de apenas enviar como regra geral, se possível.

Sim, é isso que quero dizer com

O código deve verificar o que é possível avaliar (coisas conhecidas) em vez do que não é possível avaliar (coisas desconhecidas).

Os únicos argumentos válidos para Less rgba são um número ou um objeto de cor (se também considerarmos as formas "neo" - "CSS4" como rgba(#123, .42) ).
Qualquer outra coisa é um erro ou um valor CSS (desconhecido, mas potencialmente válido).

A sintaxe do conteúdo das propriedades personalizadas CSS é muito permissiva, mas isso causa problemas ao usar tais propriedades dentro de funções embutidas como rgba()

Exemplo:
Meu projeto permite que o usuário defina a cor de destaque na qual toda a IU do aplicativo e vários componentes personalizados são baseados. E estou usando o formato rgb por causa da necessidade de fade em certos lugares e o CSS não fornece nada como fade(<strong i="9">@color</strong>, 50%) em menos. Dessa forma, posso fazer rgba( var(--color), 0.5 ) . Isso funciona no Chrome e é compatível com o padrão. No entanto, menos gera o seguinte erro error evaluation function 'rgba': color functions take numbers as parameters .

Código de exemplo:

:root {
  --color-accent: 169,57,255;
}
button:hover {
  background-color: rgba(var(--color-accent), 0.2);
  color: rgb(var(--color-accent));
}

Nota: Esta é uma biblioteca drop-in e não quero forçar os usuários a adicionar outra etapa de construção em seu fluxo de trabalho apenas para construir minha biblioteca menos com suas cores. É por isso que estou usando as novas e brilhantes propriedades personalizadas (e também por causa de sua capacidade de escopo).

BTW: Existe alguma solução temporária que iria ignorar esse manuseio estrito e construí-lo de qualquer maneira? Não é como se eu estivesse perdendo um colchete em regras aninhadas.

escreva assim ~

:root {
    --color-accent: 169,57,255;
}
button:hover {
    background-color: ~"rgba(var(--color-accent), 0.2)";
    color: ~"rgb(var(--color-accent))";
}

@weivea Na versão mais recente do Less 3.x, isso não é necessário, basta escrever rgba(var(--color-accent))

Esta página foi útil?
0 / 5 - 0 avaliações