Tworzenie miksu Sass z opcjonalnymi argumentami

201

Piszę taki mixin:

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

Po wywołaniu tak naprawdę chcę, aby jeśli żadna $insetwartość nie została przekazana, nic nie jest generowane, zamiast kompilacji do czegoś takiego:

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

Jak przepisać mixin, aby jeśli nie $insetprzekazano żadnej wartości , nic nie zostanie wyświetlone?

Rich Bradshaw
źródło
6
Szkoda, że ​​SASS nie ma wartości blankani nil.
Joshua Pinter
1
Przy okazji, patrząc na inne ograniczenie SASS, znalazłem dobry sposób na pozbycie się cytatów w takich sytuacjach. Dodałem odpowiedź na to.
Joshua Pinter
4
Teraz w 2015 roku możesz po prostu użyć null, aby pominąć attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Upada

Odpowiedzi:

257

DRY'R Way to zrobić

I, ogólnie rzecz biorąc, fajna sztuczka, aby usunąć cytaty.

@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 wersja 3+, możesz użyć 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);
} 

Podniosłem to tutaj: przekaż listę do miksu jako pojedynczy argument z SASS

Joshua Pinter
źródło
6
Jak zauważa Bob Sammers, w nowszej wersji SASS możesz również użyć metody unquote () zamiast # {}, aby usunąć cudzysłowy. Twoje zdrowie.
Joshua Pinter
4
najprostszym sposobem jest użycie nulldomyślnej wartości parametrów opcjonalnych zamiast ""i nie będą one renderowane w wyniku! @mixin box-shadow($top, $left,... , $inset:null) {}
S.Serpooshan,
@ S.Serpooshan Jestem ciekawy, w jakiej wersji został dodany. To z pewnością nie było obsługiwane w 2012 roku.
Joshua Pinter
79

O wiele lepszy SUCHY sposób

ma przejść $args...do @mixin. W ten sposób, bez względu na to, ile $argszdasz. W @inputrozmowie możesz przekazać wszystkie potrzebne argumenty. Tak jak:

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

A teraz możesz ponownie użyć swojego cienia w każdej klasie, przekazując wszystkie potrzebne argumenty:

.my-box-shadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Fabricio
źródło
11
To dobrze wiedzieć, ale często razy jest to bardziej jasne wskazania co argumentami mixinspodziewa się, jak $top, $left, $bluritp Variable argumenty, jakbyś pokazano, świetnie nadają się do ostatecznego elastyczność, choć.
Joshua Pinter
1
Dzięki, stary, bardzo mi to pomaga
Nilesh Sutar,
48

Sass obsługuje @ifoświadczenia. (Zobacz dokumentację .)

Możesz napisać swój mixin w ten sposób:

@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
źródło
Nie jest to tutaj przydatne, tylko insetczęść musi być wykluczona, gdy ma wartość NULL, nie wszystkie właściwości cienia
S.Serpooshan,
@ S.Serpooshan Wystarczy dodać elsei dołączyć wszystkie nie wstawiane właściwości w środku.
mbomb007,
@ mbomb007 Wiem, właśnie zgłosiłem problem z tym rozwiązaniem. Inne odpowiedzi podane powyżej są absolutnie lepsze.
S.Serpooshan
26

Możesz ustawić właściwość z null jako wartość domyślną, a jeśli nie podasz parametru, nie zostanie on zinterpretowany.

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

Oznacza to, że możesz napisać instrukcję include w ten sposób.

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

Zamiast pisać w ten sposób.

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

Jak pokazano w odpowiedzi tutaj

użytkownik1551211
źródło
1
Ta odpowiedź nie oferuje nic nowego w stosunku do istniejących odpowiedzi (patrz: stackoverflow.com/a/23565388/1652962 )
cimmanon
9
@ cimmanon Wręcz przeciwnie, zapewnia to dodatkowe narzędzie, ponieważ można wtedy zapisać import @include box-shadow($top, $left, $blur, $color);zamiast @include box-shadow($top, $left, $blur, $color, null);. Dlatego ta odpowiedź jest o wiele bardziej korzystna.
Dan
1
@ Dan W rzeczywistości tracisz czytelność, robiąc to w ten sposób, więc prawdopodobnie jest to mniej korzystne niż odpowiedź, z której pochodzi.
TylerH,
@TylerH To prawda
Dan
14

Stare pytanie, wiem, ale myślę, że to jest nadal aktualne. Prawdopodobnie wyraźniejszym sposobem na to jest użycie funkcji unquote () (którą SASS ma od wersji 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);
}

Jest to w przybliżeniu odpowiednik odpowiedzi Josha, ale myślę, że wyraźnie nazwana funkcja jest mniej zaciemniona niż składnia interpolacji łańcucha.

Bob Sammers
źródło
12

Wiem, że nie jest to dokładnie odpowiedź, "null"której @include box-shadowszukałeś, ale możesz podać jako ostatni argument podczas miksowania, tak jak @include box-shadow(12px, 14px, 2px, green, null);teraz Teraz, jeśli ten argument jest tylko jeden w tej właściwości niż ta właściwość (a jej (domyślna) wartość) nie zostanie skompilowana . Jeśli w tej „linii” znajdują się dwa lub więcej argumentów, tylko te, które zostały zerowane, nie zostaną skompilowane (twój przypadek).

Wyjście CSS jest dokładnie takie, jak chcesz, ale musisz napisać swoje 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;
Krople
źródło
1
Zdecydowanie mój ulubiony sposób na zrobienie tego sprawia, że ​​wszystko jest łatwe do odczytania i zrozumienia, kiedy trzeba wrócić do skryptu. dzięki Krople.
Plentybinary
7

oto rozwiązanie, którego używam, z notatkami poniżej:

@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);
}
  • wolą przekazywać wartości właściwości jako natywne css, aby pozostać blisko „języka”
  • pozwalają na przekazywanie zmiennej liczby argumentów
  • zdefiniuj domyślną wartość lenistwa
duggi
źródło
Jak to coś dodaje do istniejących odpowiedzi (mianowicie: stackoverflow.com/a/28072864/1652962 )?
cimmanon
Wyjaśnił, jak powiedzieć, czy do funkcji przekazywany jest więcej niż jeden argument, a jeśli tak, to należy zmienić wynik. Druga odpowiedź nie.
TetraDev,
czasami chcesz zdefiniować zachowanie globalne. na przykład przejścia animacji, w których ogólnie chcesz mieć bardzo jednolite wrażenia i nie chcesz ryzykować „kreatywnego uznania twórcy”, jeśli chodzi o podejmowanie decyzji. definiuje to wartość domyślną, którą można zastąpić, ale często nie jest to spowodowane bardziej zwartą składnią, gdy nie przekazuje się argumentów. w ten sposób możesz także zmienić globalne zachowanie w jednym miejscu.
duggi,
3

Z [email protected]:

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

i użyj bez wartości, przycisk będzie niebieski

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

i wartości, przycisk będzie czerwony

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

działa również z hexa

gael
źródło
Jak to coś dodaje do istniejących odpowiedzi?
cimmanon
3

Nawet OSUSZANIE!

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

A teraz możesz ponownie wykorzystać swój cień-pudełko jeszcze mądrzej:

.myShadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Ben Kalsky
źródło
Tylko uwaga - jakkolwiek jest to czytelne i potwierdzam, że w tym miejscu należy wytyczyć granicę między kodem DRY a czytelnością / konserwacją .
Leo Napoleon
Zgadzam się, aby zwiększyć czytelność / konserwację , stworzyłbym „listę przeglądarek” do ponownego użycia w innych miksach. Można to również dość łatwo połączyć z innymi właściwościami css, które można wykonać za pomocą zestawu suchych miksów. Ten artykuł z 2014 roku jest wciąż doskonałym przykładem.
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.
źródło
Jest to prawdopodobnie gorsze niż wszystkie inne odpowiedzi, ze względu na jego gadatliwość. Ponadto jest wystarczająco blisko jednej z pozostałych odpowiedzi, aby uznać ją za duplikat.
cimmanon,
1

Super prosty sposób

Wystarczy dodać wartość domyślną nonedo $ inset - więc

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

Teraz, gdy nie zostanie przekazana żadna wstawka $, nic nie będzie wyświetlane.

fidev
źródło
1

Zawsze możesz przypisać null swoim opcjonalnym argumentom. Oto prosta poprawka

@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;
}
Benzoes
źródło
0

Jestem nowy w kompilatorach css, mam nadzieję, że to pomoże,

        @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
źródło
Jak to coś dodaje do istniejących odpowiedzi?
cimmanon,