Creare un mix Sass con argomenti opzionali


201

Sto scrivendo un mixin come questo:

@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;
}

Quando viene chiamato, ciò che voglio veramente è che se non $insetviene passato alcun valore, non viene emesso nulla, anziché compilare in qualcosa del genere:

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

Come riscrivo il mixin in modo che se non c'è valore di $insetpassato, non viene emesso nulla?


6
È un peccato che SASS non abbia valore blanko nil.
Joshua Pinter

1
A proposito, mentre guardavo una diversa limitazione SASS, mi sono imbattuto in un bel modo per sbarazzarsi delle virgolette in queste situazioni. Ho aggiunto una risposta per questo.
Joshua Pinter

4
Ora nel 2015 puoi semplicemente usare nullper saltare attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Scade

Risposte:


257

Un modo secco di farlo

E, generalmente, un trucco per rimuovere le virgolette.

@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 versione 3+, è possibile utilizzare 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);
} 

L'ho preso qui: passa un elenco a un mixin come singolo argomento con SASS


6
Come sottolinea Bob Sammers, nella versione più recente di SASS puoi anche usare il metodo unquote () invece di # {} per rimuovere le virgolette. Saluti.
Joshua Pinter,

4
il modo più semplice è quello di utilizzare nullil valore predefinito dei parametri opzionali invece di "", e non saranno resi in output! @mixin box-shadow($top, $left,... , $inset:null) {}
S. Serpooshan,

@ S.Serpooshan Sono curioso di sapere quale versione è stata aggiunta. Questo sicuramente non è stato supportato nel 2012.
Joshua Pinter

79

Un modo DRY molto migliore

è passare $args...al @mixin. In questo modo, non importa quanti $argsne passerai. Nella @inputchiamata, puoi passare tutti gli argomenti necessari. Così:

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

E ora puoi riutilizzare il box-shadow in ogni classe che desideri passando tutti gli argomenti necessari:

.my-box-shadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}

11
Che è bene sapere, ma spesso è più chiaro per indicare quali argomenti un mixinsi aspetta, come $top, $left, $blur, ecc argomenti variabili, come hai dimostrato, sono grandi per la massima flessibilità, però.
Joshua Pinter,

1
Grazie, amico, mi aiuta molto
Nilesh Sutar,

48

Sass supporta le @ifdichiarazioni. (Vedi la documentazione .)

Puoi scrivere il tuo mixin in questo modo:

@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;
  }
}

Questo non è utile qui, solo la insetparte deve essere esclusa quando è nulla, non tutte le proprietà box-shadow
S.Serpooshan

@ S.Serpooshan Basta aggiungere un elsee includere tutte le proprietà non inserite all'interno.
mbomb007,

@ mbomb007 Lo so, ho appena segnalato un problema con questa soluzione. E le altre risposte fornite sopra sono assolutamente migliori.
S. Serpooshan il

26

Puoi mettere la proprietà con null come valore predefinito e se non passi il parametro non verrà interpretata.

@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;
}

Ciò significa che puoi scrivere l'istruzione include in questo modo.

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

Invece di scriverlo in questo modo.

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

Come mostrato nella risposta qui


1
Questa risposta offre nulla di nuovo sopra le risposte esistenti (vedi: stackoverflow.com/a/23565388/1652962 )
cimmanon

9
@cimmanon Al contrario, questo fornisce un'utilità extra in quanto è possibile scrivere l'importazione come @include box-shadow($top, $left, $blur, $color);anziché @include box-shadow($top, $left, $blur, $color, null);. Pertanto questa risposta è molto più benevola.
Dan

1
@ Dan In realtà si perde la leggibilità facendo in questo modo, quindi forse è meno vantaggioso rispetto la risposta è derivato da.
TylerH,

@TylerH Questo è vero
Dan,

14

Vecchia domanda, lo so, ma penso che sia ancora rilevante. Probabilmente, un modo più chiaro per farlo è usare la funzione unquote () (che SASS ha avuto dalla versione 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);
}

Ciò equivale all'incirca alla risposta di Josh, ma penso che la funzione chiamata esplicitamente sia meno offuscata della sintassi di interpolazione delle stringhe.


12

So che non è esattamente la risposta che stavi cercando, ma potresti passare "null"come ultimo argomento quando @include box-shadowmixin, come questo @include box-shadow(12px, 14px, 2px, green, null);Ora, se quell'argomento è solo uno in quella proprietà rispetto a quella proprietà (e il suo valore (predefinito)) non verrà compilato . Se ci sono due o più argomenti su quella "linea", solo quelli che hai annullato non verranno compilati (il tuo caso).

L'output CSS è esattamente come lo volevi, ma devi scrivere i tuoi null:)

  @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;

1
Sicuramente il mio modo preferito per farlo mantiene tutto semplice da leggere e capire per quando devi tornare a una sceneggiatura. thnx Drops.
Plentybinary

7

ecco la soluzione che uso, con le note di seguito:

@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);
}
  • preferire passare valori di proprietà come CSS nativo per stare vicino a "la lingua"
  • consentire il passaggio di un numero variabile di argomenti
  • definire un valore predefinito per la pigrizia

In che modo questo aggiunge qualcosa rispetto alle risposte esistenti (vale a dire: stackoverflow.com/a/28072864/1652962 )?
cimmanon,

Ha spiegato come stabilire se più di un argomento viene passato alla funzione e, in tal caso, modificare l'output. L'altra risposta no.
TetraDev,

a volte, vuoi definire un comportamento globale. ad esempio, transizioni di animazione in cui generalmente si desidera avere un'esperienza molto uniforme e non si vuole rischiare la "discrezione degli sviluppatori creativi" quando si tratta di decidere cosa fare. questo definisce un valore predefinito che può essere sovrascritto ma spesso non lo sarà a causa della sintassi più compatta quando non si passano argomenti. puoi anche cambiare il comportamento globale in un unico posto in questo modo.
duggi,

3

Con sass@3.4.9:

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

e utilizzare senza valore, il pulsante sarà blu

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

e con valore, il pulsante sarà rosso

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

funziona anche con hexa


In che modo questo aggiunge qualcosa rispetto alle risposte esistenti?
cimmanon,

3

Modo ancora più ASCIUTTO!

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

E ora puoi riutilizzare la tua ombra ancora più intelligente:

.myShadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}

Solo una nota - leggibile come questo e lo riconosco, è qui che si dovrebbe tracciare la linea tra il codice DRY e la leggibilità / manutenibilità .
Leo Napoleon,

Sono d'accordo, per aumentare la leggibilità / manutenibilità vorrei creare un "elenco di browser" da riutilizzare in altri mixin. Questo potrebbe anche essere facilmente assemblato con altre proprietà CSS, che possono essere eseguite con un set di mixin a secco. Questo articolo del 2014 è ancora un ottimo esempio.
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;
    }
}

Questo è probabilmente peggiore di tutte le altre risposte, a causa della sua verbosità. Inoltre, è abbastanza vicino a una delle altre risposte per essere considerato un duplicato.
cimmanon,

1

Modo super semplice

Basta aggiungere un valore predefinito di nonea $ inset - così

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

Ora quando non viene passato $ inset non verrà visualizzato nulla.


1

Puoi sempre assegnare null ai tuoi argomenti opzionali. Ecco una soluzione semplice

@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;
}

0

Sono nuovo ai compilatori CSS, spero che questo aiuti,

        @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;
}

In che modo questo aggiunge qualcosa rispetto alle risposte esistenti?
cimmanon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.