Faire un mixin Sass avec des arguments optionnels


202

J'écris un mixin comme celui-ci:

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

Quand on appelle ce que je veux vraiment, c'est que si aucune $insetvaleur n'est transmise, rien n'est généré, plutôt que de compiler quelque chose comme ceci:

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

Comment réécrire le mixage pour que s'il n'y a pas de valeur $insetpassée, rien ne soit sorti?


6
C'est dommage que SASS n'ait pas de valeur blankou nil.
Joshua Pinter

1
Btw, tout en regardant une limitation SASS différente, je suis tombé sur une belle façon de se débarrasser des citations dans ces situations. J'ai ajouté une réponse pour cela.
Joshua Pinter

4
Maintenant, en 2015, vous pouvez simplement l'utiliser nullpour ignorer attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Dépose

Réponses:


257

Une façon DRY'r de le faire

Et, généralement, une astuce intéressante pour supprimer les guillemets.

@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 version 3+, vous pouvez utiliser 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);
} 

Je l'ai récupéré ici: passez une liste à un mixin comme argument unique avec SASS


6
Comme le souligne Bob Sammers, dans une version plus récente de SASS, vous pouvez également utiliser la méthode unquote () au lieu de # {} pour supprimer les guillemets. À votre santé.
Joshua Pinter

4
la manière la plus simple est d'utiliser nullpour la valeur par défaut des paramètres optionnels au lieu de "", et ils ne seront pas rendus en sortie! @mixin box-shadow($top, $left,... , $inset:null) {}
S.Serpooshan

@ S.Serpooshan Je suis curieux de savoir dans quelle version cela a été ajouté. Cela n'a certainement pas été pris en charge en 2012.
Joshua Pinter

79

Une bien meilleure façon SEC

est de passer $args...au @mixin. De cette façon, peu importe combien $argsvous passerez. Dans l' @inputappel, vous pouvez passer tous les arguments nécessaires. Ainsi:

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

Et maintenant, vous pouvez réutiliser votre shadow dans toutes les classes de votre choix en passant tous les arguments nécessaires:

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

11
C'est bon de savoir , mais souvent il est plus clair pour indiquer quels arguments un mixinATTEND, comme $top, $left, $blur, etc. arguments variables, comme vous avez montré, sont parfaits pour une flexibilité maximale, cependant.
Joshua Pinter

1
Merci, mec, ça m'aide beaucoup
Nilesh Sutar

48

Sass soutient les @ifdéclarations. (Voir la documentation .)

Vous pouvez écrire votre mixin comme ceci:

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

Ce n'est pas utile ici, seule la insetpartie doit être exclue quand elle est nulle, pas toutes les propriétés d'ombre de boîte
S.Serpooshan

@ S.Serpooshan Il suffit d'ajouter un elseet d'inclure toutes les propriétés non insérées à l'intérieur.
mbomb007

@ mbomb007 je sais, je viens de signaler un problème avec cette solution. Et les autres réponses fournies ci-dessus sont absolument meilleures.
S.Serpooshan

26

Vous pouvez mettre la propriété avec null comme valeur par défaut et si vous ne passez pas le paramètre, il ne sera pas interprété.

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

Cela signifie que vous pouvez écrire l'instruction include comme ceci.

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

Au lieu de l'écrire comme ça.

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

Comme indiqué dans la réponse ici


1
Cette réponse n'offre rien de nouveau par rapport aux réponses existantes (voir: stackoverflow.com/a/23565388/1652962 )
cimmanon

9
@cimmanon Au contraire, cela fournit un utilitaire supplémentaire car vous pouvez ensuite écrire l'importation au @include box-shadow($top, $left, $blur, $color);lieu de @include box-shadow($top, $left, $blur, $color, null);. Par conséquent, cette réponse est beaucoup plus bénéfique.
Dan

1
@Dan En fait, vous perdez la lisibilité en procédant de cette façon, donc c'est sans doute moins bénéfique que la réponse dont il est dérivé.
TylerH du

@TylerH C'est vrai
Dan

14

Vieille question, je sais, mais je pense que c'est toujours d'actualité. Sans doute, une façon plus claire de le faire est d'utiliser la fonction unquote () (que SASS possède depuis la version 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);
}

C'est à peu près équivalent à la réponse de Josh, mais je pense que la fonction explicitement nommée est moins obscurcie que la syntaxe d'interpolation de chaîne.


12

Je sais que ce n'est pas exactement la réponse que vous cherchiez mais vous pouvez passer "null"comme dernier argument lors du @include box-shadowmixage, comme ceci@include box-shadow(12px, 14px, 2px, green, null); maintenant, si cet argument n'est qu'un dans cette propriété que cette propriété (et sa valeur (par défaut)) ne sera pas compilée . S'il y a deux arguments ou plus sur cette "ligne", seuls ceux que vous avez annulés ne seront pas compilés (votre cas).

La sortie CSS est exactement comme vous le vouliez, mais vous devez écrire votre 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;

1
Assurément, ma façon préférée de le faire garde tout simple à lire et à comprendre lorsque vous devez revenir à un script. thnx Drops.
Plentybinary

7

voici la solution que j'utilise, avec les notes ci-dessous:

@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);
}
  • préfère passer les valeurs de propriété en tant que CSS natif pour rester proche de "la langue"
  • permettre de passer un nombre variable d'arguments
  • définir une valeur par défaut pour la paresse

Comment cela ajoute-t-il quelque chose aux réponses existantes (à savoir: stackoverflow.com/a/28072864/1652962 )?
cimmanon

Il a expliqué comment savoir si plusieurs arguments sont passés à la fonction et, dans l'affirmative, modifier la sortie. L'autre réponse ne l'a pas fait.
TetraDev

parfois, vous voulez définir un comportement global. par exemple, les transitions d'animation où vous voulez généralement avoir une expérience très uniforme et ne voulez pas risquer la "discrétion du développeur créatif" quand il s'agit de décider quoi faire. cela définit une valeur par défaut qui peut être remplacée mais ne le sera souvent pas en raison de la syntaxe plus compacte lors de la non-transmission d'arguments. vous pouvez également modifier le comportement global en un seul endroit de cette façon.
duggi

3

Avec sass@3.4.9:

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

et utiliser sans valeur, le bouton sera bleu

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

et avec la valeur, le bouton sera rouge

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

fonctionne aussi avec hexa


Comment cela ajoute-t-il quelque chose aux réponses existantes?
cimmanon

3

Encore plus sec!

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

Et maintenant, vous pouvez réutiliser votre box-shadow encore plus intelligemment:

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

Juste une note - aussi lisible que cela soit et je reconnais que c'est là que l'on doit tracer la ligne entre le code DRY et la lisibilité / maintenabilité .
Leo Napoleon

J'accepte, pour augmenter la lisibilité / maintenabilité, je créerais une "liste de navigateurs" à réutiliser dans d'autres mixins. Cela pourrait également être assez facilement assemblé à d'autres propriétés CSS, qui peuvent être exécutées avec un ensemble de mixins secs. Cet article de 2014 en est toujours un bon exemple.
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;
    }
}

C'est sans doute pire que toutes les autres réponses, en raison de sa verbosité. De plus, c'est assez proche de l' une des autres réponses pour compter comme un doublon.
cimmanon

1

Manière super simple

Ajoutez simplement une valeur par défaut noneà $ inset - donc

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

Maintenant, quand aucun $ inset n'est passé, rien ne sera affiché.


1

Vous pouvez toujours attribuer null à vos arguments facultatifs. Voici une solution 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;
}

0

Je suis nouveau sur les compilateurs CSS, j'espère que cela aide,

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

Comment cela ajoute-t-il quelque chose aux réponses existantes?
cimmanon
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.