Haciendo matemáticas con argumentos variables Sass mixins

26

Me gusta usar unidades rem con retrocesos de píxeles para el tamaño de mi CSS y estoy tratando de hacer mixins para ayudar con eso. Para el tamaño de fuente, esto es fácil:

@mixin font-size($size) {
  font-size: $size + px;
  font-size: ($size / 10) + rem;
}

Pero para el relleno, el margen, etc., el mixin debe aceptar argumentos variables, lo cual es posible según la documentación de Sass http://sass-lang.com/documentation/file.SASS_REFERENCE.html#variable_arguments

Sin embargo, con el siguiente mixin, en lugar de dividir por 10, el mixin solo agrega una barra entre los números. Eso es esto:

@mixin padding($padding...) {
    padding: $padding + px;
    padding: ($padding / 10) + rem;
}
.class {
    @include padding(24);
}

Produce esto:

.class {
    padding: 24px;
    padding: 24/10rem;
}

En lugar de esto, como esperaba:

.class {
    padding: 24px;
    padding: 2.4rem;
}

¿Hay alguna manera de asegurarse de que Sass reconozca las variables como números y, por lo tanto, use el operador de división en ellas correctamente?

Además, después de probar esto más, me di cuenta de que la concatenación solo tiene lugar en la última variable.

1
27

Prueba esto:

padding: #{$padding / 10}rem;

La concatenación en SASS / SCSS usa la sintaxis ruby, y estaba mezclando una ecuación matemática seguida de una concatenación, que es una mezcla de tipos variables, por lo que no me sorprende que no haya funcionado.

Las expresiones y variables incluidas dentro de # {aquí} se evalúan como si estuvieran separadas del resto de la línea y, por lo tanto, no encasillan el resto de la línea. También es útil si su salida se cotiza cuando no lo esperaba (al igual que la función unquote ())

3
  • ¡Esto es muy útil! ¡Gracias! 28/08/19 a las 13:32
  • ¿Qué pasa si necesito hacer algo como esto? 25/06/20 a las 13:16
  • Tenga en cuenta que # {$ padding / 10} rem; lanza el valor como una cadena. Una mejor forma de escribirlo es $ padding / 10 + 0rem; que lo mantiene como un número si necesita realizar operaciones matemáticas adicionales.
    koga73
    1 sep.2020 a las 17:09
21

Parece que lo que realmente necesitaba usar aquí era una lista en lugar de un argumento variable para manipular cada valor por separado.

Primero intenté hacer esto con la directiva @each, pero no pude averiguar cómo usarlo dentro de una declaración. Esto arroja un error:

@mixin padding($padding) {
   padding: @each $value in $padding { $value + px };
   padding: @each $value in $padding { ($value / 10) + rem };
}

Así que terminé escribiendo algo mucho más detallado que maneja cada uno de los cuatro casos posibles por separado (es decir, pasa 1, 2, 3 o 4 argumentos). Eso se ve así y funciona como quería:

@mixin padding($padding) {
    @if length($padding) == 1 {
        padding: $padding+px;
        padding: $padding/10+rem;
    }
    @if length($padding) == 2 {
        padding: nth($padding, 1)+px nth($padding, 2)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem;
    }
    @if length($padding) == 3 {
        padding: nth($padding, 1)+px nth($padding, 2)+px nth($padding, 3)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem nth($padding, 3)*0.1+rem;
    }
    @if length($padding) == 4 {
        padding: nth($padding, 1)+px nth($padding, 2)+px nth($padding, 3)+px nth($padding, 4)+px;
        padding: nth($padding, 1)*0.1+rem nth($padding, 2)*0.1+rem nth($padding, 3)*0.1+rem nth($padding, 4)*0.1+rem;
    }
}

Hice una colección de rem mixins, incluido este como Gist aquí https://gist.github.com/doughamlin/7103259

0

Una cosa que podría ayudar es usar calcjunto con interpolation(también conocido como #{}). Por ejemplo.

$height: 10px;
$padding: 2px;

height: calc(#{$height} + #{$padding * 2}); // calc(10px + 4px)

Esto NO es lo mismo que ...

height: calc($height + #{$padding * 2});
// resolves to...
height: calc($height + 4px); // ERROR

height: #{$height + $padding * 2};
// resolves to...
height: 10px + 4px; // ERROR