Hacer una mezcla de Sass con argumentos opcionales

201

Estoy escribiendo un mixin como este:

@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
    -webkit-box-shadow: $top $left $blur $color $inset;
    -moz-box-shadow: $top $left $blur $color $inset;
    box-shadow: $top $left $blur $color $inset;
}

Cuando se llama lo que realmente quiero es que si no $insetse pasa ningún valor, no se genera nada, en lugar de compilarse en algo como esto:

-webkit-box-shadow: 2px 2px 5px #555555 "";
-moz-box-shadow: 2px 2px 5px #555555 "";
box-shadow: 2px 2px 5px #555555 "";

¿Cómo reescribo el mixin para que si no se pasa ningún valor $inset, no se emite nada?

Rich Bradshaw
fuente
66
Es una pena que SASS no tiene blankni nilvalor.
Joshua Pinter
1
Por cierto, mientras miraba una limitación SASS diferente, me encontré con una buena manera de deshacerme de las citas en estas situaciones. Agregué una respuesta para eso.
Joshua Pinter
44
Ahora en 2015 solo puede usar nullpara omitir attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Gotas

Respuestas:

257

Una manera SECA de hacerlo

Y, en general, un buen truco para eliminar las comillas.

@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
  -webkit-box-shadow: $top $left $blur $color #{$inset};
  -moz-box-shadow:    $top $left $blur $color #{$inset};
  box-shadow:         $top $left $blur $color #{$inset};
}

SASS Versión 3+, puede usar unquote():

@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
  -webkit-box-shadow: $top $left $blur $color unquote($inset);
  -moz-box-shadow:    $top $left $blur $color unquote($inset);
  box-shadow:         $top $left $blur $color unquote($inset);
} 

Recogí esto aquí: pasar una lista a un mixin como argumento único con SASS

Joshua Pinter
fuente
66
Como señala Bob Sammers, en la versión más nueva de SASS también puede usar el método unquote () en lugar de # {} para eliminar las comillas. Salud.
Joshua Pinter
44
¡la forma más simple es usar nullel valor predeterminado de los parámetros opcionales en lugar de "", y no se mostrarán en la salida! @mixin box-shadow($top, $left,... , $inset:null) {}
S.Serpooshan
@ S.Serpooshan Tengo curiosidad por saber en qué versión se agregó. Esto ciertamente no fue compatible en 2012.
Joshua Pinter
79

Una forma SECA mucho mejor

es pasar $args...a la @mixin. De esa manera, no importa cuántos $argspases. En la @inputllamada, puede pasar todos los argumentos necesarios. Al igual que:

@mixin box-shadow($args...) {
  -webkit-box-shadow: $args;
  -moz-box-shadow: $args;
  box-shadow: $args;
}

Y ahora puede reutilizar su sombra de cuadro en cada clase que desee pasando todos los argumentos necesarios:

.my-box-shadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Fabricio
fuente
11
Eso es bueno saberlo, pero muchas veces es más clara para indicar qué argumentos una mixinestá a la espera, como $top, $left, $blur, etc. argumentos variables, como usted ha demostrado, son ideales para la máxima flexibilidad, sin embargo.
Joshua Pinter
1
Gracias, amigo, me ayuda mucho
Nilesh Sutar
48

Sass apoya @ifdeclaraciones. (Ver la documentación ).

Podrías escribir tu mixin así:

@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
  @if $inset != "" {
    -webkit-box-shadow:$top $left $blur $color $inset;
    -moz-box-shadow:$top $left $blur $color $inset;
    box-shadow:$top $left $blur $color $inset;
  }
}
Andrew Vit
fuente
Esto no es útil aquí, solo la insetparte debe excluirse cuando es nula, no todas las propiedades de sombreado de caja
S.Serpooshan
@ S.Serpooshan Simplemente agregue elsee incluya todas las propiedades no insertadas en su interior.
mbomb007
@ mbomb007 lo sé, acabo de informar un problema con esta solución. Y otras respuestas proporcionadas anteriormente son absolutamente mejores.
S.Serpooshan
26

Puede colocar la propiedad con nulo como valor predeterminado y, si no pasa el parámetro, no se interpretará.

@mixin box-shadow($top, $left, $blur, $color, $inset:null) {
  -webkit-box-shadow: $top $left $blur $color $inset;
  -moz-box-shadow:    $top $left $blur $color $inset;
  box-shadow:         $top $left $blur $color $inset;
}

Esto significa que puede escribir la declaración de inclusión de esta manera.

@include box-shadow($top, $left, $blur, $color);

En lugar de escribirlo así.

@include box-shadow($top, $left, $blur, $color, null);

Como se muestra en la respuesta aquí

usuario1551211
fuente
1
Esta respuesta no ofrece nada nuevo sobre las respuestas existentes (ver: stackoverflow.com/a/23565388/1652962 )
cimmanon
9
@cimmanon Por el contrario, esto proporciona una utilidad adicional ya que puede escribir la importación como en @include box-shadow($top, $left, $blur, $color);lugar de @include box-shadow($top, $left, $blur, $color, null);. Por lo tanto, esta respuesta es mucho más benéfica.
Dan
1
@Dan En realidad, pierdes legibilidad haciéndolo de esa manera, por lo que podría decirse que es menos beneficioso que la respuesta de la que deriva.
TylerH
@TylerH Eso es cierto
Dan
14

Antigua pregunta, lo sé, pero creo que esto sigue siendo relevante. Podría decirse que una forma más clara de hacerlo es usar la función unquote () (que SASS ha tenido desde la versión 3.0.0):

@mixin box-shadow($top, $left, $blur, $color, $inset:"") {
  -webkit-box-shadow: $top $left $blur $color unquote($inset);
  -moz-box-shadow: $top $left $blur $color unquote($inset);
  box-shadow: $top $left $blur $color unquote($inset);
}

Esto es más o menos equivalente a la respuesta de Josh, pero creo que la función explícitamente nombrada está menos ofuscada que la sintaxis de interpolación de cadenas.

Bob Sammers
fuente
12

Sé que no es exactamente la respuesta que estabas buscando, pero podrías pasar "null"como último argumento cuando @include box-shadowmezclas, así@include box-shadow(12px, 14px, 2px, green, null); Ahora, si ese argumento es solo uno en esa propiedad que esa propiedad (y su valor (predeterminado)) no se compilará . Si hay dos o más argumentos en esa "línea", solo los que anuló no se compilarán (su caso).

La salida de CSS es exactamente como la quería, pero debe escribir su nulls :)

  @include box-shadow(12px, 14px, 2px, green, null);

  // compiles to ...

  -webkit-box-shadow: 12px 14px 2px green;  
  -moz-box-shadow: 12px 14px 2px green;  
  box-shadow: 12px 14px 2px green;
Gotas
fuente
1
Definitivamente, mi forma favorita de hacer esto hace que todo sea simple de leer y comprender cuando tienes que volver a un guión. Thnx Drops.
Plentybinary
7

Aquí está la solución que uso, con las notas a continuación:

@mixin transition($trans...) {
  @if length($trans) < 1 {
    $trans: all .15s ease-out;
  }
  -moz-transition: $trans;
  -ms-transition: $trans;
  -webkit-transition: $trans;
  transition: $trans;
}

.use-this {
  @include transition;
}

.use-this-2 {
  @include transition(all 1s ease-out, color 2s ease-in);
}
  • prefiero pasar valores de propiedad como CSS nativo para permanecer cerca de "la lengua"
  • permitir pasar un número variable de argumentos
  • definir un valor predeterminado para la pereza
duggi
fuente
¿Cómo agrega esto a las respuestas existentes (a saber: stackoverflow.com/a/28072864/1652962 )?
cimmanon
Explicó cómo saber si se pasa más de un argumento a la función y, de ser así, cambiar la salida. La otra respuesta no lo hizo.
TetraDev
a veces, desea definir un comportamiento global. por ejemplo, las transiciones de animación donde generalmente desea tener una experiencia muy uniforme y no quiere arriesgarse a "discreción creativa del desarrollador" cuando se trata de decidir qué hacer. Esto define un valor predeterminado que se puede anular, pero a menudo no se debe a la sintaxis más compacta cuando no se pasan argumentos. También puede cambiar el comportamiento global en un solo lugar de esta manera.
duggi
3

Con [email protected]:

// declare
@mixin button( $bgcolor:blue ){
    background:$bgcolor;
}

y usar sin valor, el botón será azul

//use
.my_button{
    @include button();
}

y con valor, el botón será rojo

//use
.my_button{
    @include button( red );
}

también funciona con hexa

gaélico
fuente
¿Cómo agrega esto algo sobre las respuestas existentes?
cimmanon
3

Incluso más seco!

@mixin box-shadow($args...) {
  @each $pre in -webkit-, -moz-, -ms-, -o- {
    #{$pre + box-shadow}: $args;
  } 
  #{box-shadow}: #{$args};
}

Y ahora puedes reutilizar tu sombra de caja aún más inteligente:

.myShadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Ben Kalsky
fuente
Solo una nota: tan legible como es y lo reconozco, aquí es donde uno debe trazar la línea entre el código DRY y la legibilidad / mantenibilidad .
Leo Napoleón
Estoy de acuerdo, para aumentar la legibilidad / mantenibilidad crearía una "lista de navegador" para reutilizar en otros mixins. Esto también podría ensamblarse fácilmente con otras propiedades css, que se pueden ejecutar con un conjunto de mixins secos. Este artículo de 2014 sigue siendo un gran ejemplo.
Ben Kalsky
1
@mixin box-shadow($left: 0, $top: 0, $blur: 6px, $color: hsla(0,0%,0%,0.25), $inset: false) {
    @if $inset {
        -webkit-box-shadow: inset $left $top $blur $color;
        -moz-box-shadow: inset $left $top $blur $color;
        box-shadow: inset $left $top $blur $color;
    } @else {
        -webkit-box-shadow: $left $top $blur $color;
        -moz-box-shadow: $left $top $blur $color;
        box-shadow: $left $top $blur $color;
    }
}
Adam C
fuente
Esto es posiblemente peor que todas las otras respuestas, debido a su verbosidad. Además, está lo suficientemente cerca de una de las otras respuestas para contar como duplicado.
cimmanon
1

Manera super simple

Simplemente agregue un valor predeterminado de none$ inset, así que

@mixin box-shadow($top, $left, $blur, $color, $inset: none) { ....

Ahora, cuando no se pasa $ inset, no se mostrará nada.

fidev
fuente
1

Siempre puede asignar nulo a sus argumentos opcionales. Aquí hay una solución simple

@mixin box-shadow($top, $left, $blur, $color, $inset:null) { //assigning null to inset value makes it optional
    -webkit-box-shadow: $top $left $blur $color $inset;
    -moz-box-shadow: $top $left $blur $color $inset;
    box-shadow: $top $left $blur $color $inset;
}
Benjamín
fuente
0

Soy nuevo en compiladores CSS, espero que esto ayude,

        @mixin positionStyle($params...){

            $temp:nth($params,1);
            @if $temp != null{
            position:$temp;
            }

             $temp:nth($params,2);
            @if $temp != null{
            top:$temp;
            }

             $temp:nth($params,3);
            @if $temp != null{
            right:$temp;
            }

             $temp:nth($params,4);
            @if $temp != null{
            bottom:$temp;
            }

            $temp:nth($params,5);
            @if $temp != null{
            left:$temp;
            }

    .someClass{
    @include positionStyle(absolute,30px,5px,null,null);
    }

//output

.someClass{
position:absolute;
 top: 30px;
 right: 5px;
}
mike tracker
fuente
¿Cómo agrega esto algo sobre las respuestas existentes?
cimmanon