define - Menos CSS: Mixins con número variable de argumentos
sass and bem (6)
LESS permite mixins paramétricos, tales como:
.transition(@property, @duration){
transition: @property @duration;
-moz-transition: @property @duration; /* Firefox 4 */
-webkit-transition: @property @duration; /* Safari and Chrome */
-o-transition: @property @duration; /* Opera */
}
Sin embargo, esto no siempre funciona con propiedades como las transiciones. Si está intentando tener varias transiciones e intenta llamar a la mezcla varias veces, la última mezcla anula todas las transiciones definidas previamente. Esto se debe a que la sintaxis CSS3 adecuada para definir múltiples transiciones es:
... {
transition: @property1 @duration1, @property2 @duration2, ...;
}
La única manera en que puedo pensar para definir múltiples transiciones como mixins es sobrecargar la mixin:
.transition(@property, @duration){...}
.transition(@property, @duration, @prop2, @dur2){...}
.transition(@property, @duration, @prop2, @dur2, @prop3, @dur3){...}
¿Existe una forma más robusta y concisa de definir la mezcla de transición para tomar un número variable de argumentos y construir el CSS de transición apropiado?
Contexto: A veces me gustaría hacer la transición en múltiples propiedades; por ejemplo, a :hover
podría desencadenar transiciones en el color de fondo, la sombra de la caja, el color del texto, etc.
Nota: Esta respuesta no se agrega con la intención de decir que las respuestas existentes son incorrectas u obsoletas. Todas las respuestas son válidas y seguirían funcionando. Este solo proporciona un método diferente que, en mi opinión, es un poco más complejo pero también más flexible en términos de cómo cada argumento puede mencionarse como pares clave-valor.
Ventajas de usar este método: este método sería más útil cuando sea necesario realizar alguna operación adicional en los valores (por ejemplo, agregar una unit
como deg
, px
o realizar cualquier operación matemática adicional, etc.) o agregar dinámicamente los prefijos del proveedor para el @property
también. Por ejemplo, hay ocasiones en las que es posible que desee pasar solo la transform
como una propiedad de entrada a la mezcla, pero desea agregar -webkit-transform
-webkit-transition
para la -webkit-transition
-webkit-transform
-webkit-transition
para la -webkit-transition
etc.
En este método, utilizamos la función ...
que nos permite pasar un número variable de argumentos a un mixin, repite cada argumento que se pasa, extract
el nombre de la propiedad junto con los parámetros adicionales (como duración, grado de rotación, etc.) y luego use la función de combinación que proporciona Less para concatenar los valores especificados para la propiedad.
- El
+:
concatena los valores de propiedad con una coma y se introdujo en Less v1.5.0 - El
+_:
concatena los valores de propiedad con un espacio y se introdujo en Less v1.7.0.
.transition(@args...){
.loop-args(@argCount) when (@argCount > 0) {
.loop-args(@argCount - 1);
@arg: extract(@args, @argCount);
@property: extract(@arg,1);
@duration: extract(@arg,2);
-webkit-transition+: @property @duration;
-moz-transition+: @property @duration;
-o-transition+: @property @duration;
transition+: @property @duration;
}
.loop-args(length(@args));
}
div{
.transition(background, 1s; border-color, 2s; color, 2s);
}
.transform(@args...){
.loop-args(@argCount) when (@argCount > 0) {
.loop-args(@argCount - 1);
@arg: extract(@args, @argCount);
@property: extract(@arg,1);
@param: extract(@arg,2);
-webkit-transform+_: ~"@{property}(@{param})";
-moz-transform+_: ~"@{property}(@{param})";
-o-transform+_: ~"@{property}(@{param})";
transform+_: ~"@{property}(@{param})";
}
.loop-args(length(@args));
}
div#div2{
.transform(rotate, 20deg; scale, 1.5; translateX, 10px);
}
El código anterior cuando se compila produciría la siguiente salida:
div {
-webkit-transition: background 1s, border-color 2s, color 2s;
-moz-transition: background 1s, border-color 2s, color 2s;
-o-transition: background 1s, border-color 2s, color 2s;
transition: background 1s, border-color 2s, color 2s;
}
div#div2 {
-webkit-transform: rotate(20deg) scale(1.5) translateX(10px);
-moz-transform: rotate(20deg) scale(1.5) translateX(10px);
-o-transform: rotate(20deg) scale(1.5) translateX(10px);
transform: rotate(20deg) scale(1.5) translateX(10px);
}
Respuesta relacionada:
- Here hay una respuesta de seven-phases-max Que explica más sobre cómo este método podría usarse para agregar automáticamente los prefijos de proveedores, como he mencionado en el párrafo de ventajas.
ACTUALIZACIÓN para MENOS 1.3.3+
La salida es la misma, pero tenga en cuenta la diferencia en cómo se pueden pasar las propiedades en las versiones más recientes de LESS utilizando el punto y coma en lugar de hacer una cadena de escape:
@prop1: color;
@prop2: opacity;
@dur1: 3s;
@dur2: 4s;
.transition(@transString: 0) when not (@transString = 0) {
transition: @transString;
-moz-transition: @transString; /* Firefox 4 */
-webkit-transition: @transString; /* Safari and Chrome */
-o-transition: @transString; /* Opera */
}
.class1 {.transition();}
.class2 {.transition(width 2s, height 2s;);}
^
semicolon here
.class3 {.transition(@prop1 @dur1, @prop2 @dur2;);}
^
semicolon here
El punto y coma hace que las comas se evalúen como separadores de lista en lugar de separadores de parámetros.
Una solución para MENOS pre 1.3.3
Construimos los argumentos de propiedad correctos como una cadena para la transition
, luego usamos el operador del valor de escape ( ~
) para traducir eso a la sintaxis propietaria necesaria. Mediante el uso de la interpolación de cadenas ( @{variableName}
) podemos incluso incrustar variables en el proceso, pero la entrada real debe tener la forma de una cadena de escape.
Código MENOS
@prop1: color;
@prop2: opacity;
@dur1: 3s;
@dur2: 4s;
.transition(@transString: 0) when not (@transString = 0) {
transition: @transString;
-moz-transition: @transString; /* Firefox 4 */
-webkit-transition: @transString; /* Safari and Chrome */
-o-transition: @transString; /* Opera */
}
.class1 {.transition();}
.class2 {.transition(~" width 2s, height 2s");}
.class3 {.transition(~" @{prop1} @{dur1}, @{prop2} @{dur2}");}
Salida CSS
Nota: no se .class1
porque la expresión de guarda asegura que algo sea ingresado (aunque no .class1
contra una entrada incorrecta).
.class2 {
transition: width 2s, height 2s;
-moz-transition: width 2s, height 2s;
-webkit-transition: width 2s, height 2s;
-o-transition: width 2s, height 2s;
}
.class3 {
transition: color 3s, opacity 4s;
-moz-transition: color 3s, opacity 4s;
-webkit-transition: color 3s, opacity 4s;
-o-transition: color 3s, opacity 4s;
}
Con fecha actual de MENOS 1.4, la documentación ( http://lesscss.org/features/#mixins-parametric-feature-mixins-with-multiple-parameters ) sugiere la forma correcta de manejar esto:
Usar comas como separador de mezcla hace que sea imposible crear listas separadas por comas como un argumento. Por otro lado, si el compilador ve al menos un punto y coma dentro de la llamada o declaración mixin, asume que los argumentos están separados por punto y coma y todas las comas pertenecen a listas css:
Concretamente, mezclando :
.transition(@prop-or-props) {
-webkit-transition: @prop-or-props;
-moz-transition: @prop-or-props;
-o-transition: @prop-or-props;
transition: @prop-or-props;
}
uso :
.transition(opacity .2s, transform .3s, -webkit-transform .3s;);
Tenga en cuenta que las múltiples propiedades están separadas por comas y el punto y coma final hace que la lista separada por comas se trate como un único parámetro en la mezcla.
Sería mejor definir la mezcla con un parámetro de rest...
y poder extraer cada elemento de los argumentos de longitud arbitraria para un manejo separado, pero el caso de uso que estoy pensando es agregar prefijos de proveedores para transformar las transiciones ( así que podría llamarlo simplemente con .transition(opacity .2s, transform .3s)
y tener el -webkit-transform
agregado automáticamente) y tal vez esto sea mejor manejado por una utilidad diferente de todos modos (gulp-autoprefixer, por ejemplo).
En MENOS, puedes separar los argumentos usando comas O punto y coma. Para valores únicos que incluyen comas, puede terminar ese valor único con un punto y coma para enviar la lista como un solo valor, como esto:
.class {
.background-size(100%, auto;);
}
Para valores múltiples, solo use esta sintaxis:
/* Example mixin */
.set-font-properties(@font-family, @size) {
font-family: @font-family;
font-size: @size;
}
/* Usage with comma-separated values */
.class {
.set-font-properties(Arial, sans-serif; 16px);
}
/* Output */
.class {
font-family: Arial, sans-serif;
font-size: 16px;
}
¡Pan comido!
Esto debería funcionar, creo:
.transition(...) {
transition: @arguments;
-moz-transition: @arguments; /* Firefox 4 */
-webkit-transition: @arguments; /* Safari and Chrome */
-o-transition: @arguments; /* Opera */
}
...
- es una sintaxis válida menos, no es algo para ser reemplazado.
Vea mi respuesta aquí: varias propiedades se tratan como argumentos separados en mixins
Resumen: use esta combinación para el número variable de argumentos:
.transition (@value1,@value2:X,...)
{
@value: ~`"@{arguments}".replace(/[/[/]]|/,/sX/g, '''')`;
-webkit-transition: @value;
-moz-transition: @value;
-ms-transition: @value;
-o-transition: @value;
transition: @value;
}