Создание Sass Mixin с необязательными аргументами

202

Я пишу миксин так:

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

Когда я вызываю, я действительно хочу, чтобы при отсутствии $insetзначения ничего не выводилось, а компилировалось в нечто вроде этого:

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

Как мне переписать миксин, чтобы при отсутствии $insetпереданного значения ничего не выводилось?

Рич Брэдшоу
источник
6
Обидно, что SASS не имеет blankили не имеет nilзначения.
Джошуа Пинтер
1
Кстати, глядя на другое ограничение SASS, я нашел хороший способ избавиться от кавычек в этих ситуациях. Я добавил ответ за это.
Джошуа Пинтер
4
Теперь в 2015 году вы можете просто использовать null, чтобы пропустить attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Капли

Ответы:

257

СУХОЙ способ сделать это

И, вообще, аккуратный трюк для удаления цитат.

@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 версии 3+, вы можете использовать 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);
} 

Подобрал это здесь: передайте список в mixin как один аргумент с SASS

Джошуа Пинтер
источник
6
Как указывает Боб Сэммерс, в более новой версии SASS вы также можете использовать метод unquote () вместо # {} для удаления кавычек. Приветствия.
Джошуа Пинтер
4
самый простой способ - использовать nullвместо значения по умолчанию дополнительные параметры вместо "", и они не будут отображаться при выводе! @mixin box-shadow($top, $left,... , $inset:null) {}
С.Серпушан
@ S.Serpooshan Мне интересно, в какой версии это было добавлено. Это, конечно, не было поддержано еще в 2012 году.
Джошуа Пинтер
79

Намного лучше сухой способ

это перейти $args...к @mixin. Таким образом, независимо от того, сколько $argsвы пройдете. В @inputвызове вы можете передать все необходимые аргументы. Вот так:

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

И теперь вы можете повторно использовать box-shadow в каждом классе, который хотите, передав все необходимые аргументы:

.my-box-shadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Фабрисио
источник
11
Это хорошо знать , но зачастую это более ясно указать , какие аргументы mixinожидает, как $top, $left, $blurи т.д. Переменные аргументы, как вы показали, являются большими для максимальной гибкости, однако.
Джошуа Пинтер
1
Спасибо, чувак, это мне очень помогает
Nilesh Sutar
48

Sass поддерживает @ifзаявления. (См. Документацию .)

Вы можете написать свой миксин так:

@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;
  }
}
Андрей Вит
источник
Здесь это бесполезно, только insetчасть должна быть исключена, когда она нулевая, а не все свойства box-shadow
S.Serpooshan
@ S.Serpooshan Просто добавьте elseи включите все не вставленные свойства внутри.
mbomb007
@ mbomb007 я знаю, я просто сообщаю о проблеме с этим решением. И другие ответы, представленные выше, абсолютно лучше.
С.Серпушан
26

Вы можете поместить свойство со значением null в качестве значения по умолчанию, и если вы не передадите параметр, оно не будет интерпретироваться.

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

Это означает, что вы можете написать оператор включения следующим образом.

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

Вместо того, чтобы писать это так.

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

Как показано в ответе здесь

user1551211
источник
1
В этом ответе нет ничего нового по сравнению с существующими ответами (см .: stackoverflow.com/a/23565388/1652962 )
cimmanon
9
@cimmanon Напротив, это обеспечивает дополнительную полезность, поскольку вы можете записать импорт @include box-shadow($top, $left, $blur, $color);вместо @include box-shadow($top, $left, $blur, $color, null);. Поэтому этот ответ намного более благотворен.
Дан
1
@Dan На самом деле вы теряете читабельность, делая это таким образом, поэтому, возможно, это менее полезно, чем ответ, из которого он получен.
TylerH
@TylerH Это правда
Дан
14

Старый вопрос, я знаю, но я думаю, что это все еще актуально. Возможно, более ясный способ сделать это - использовать функцию unquote () (которая была в SASS начиная с версии 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);
}

Это примерно эквивалентно ответу Джоша, но я думаю, что явно названная функция менее запутана, чем синтаксис строковой интерполяции.

Боб Саммерс
источник
12

Я знаю, что это не совсем тот ответ, который вы искали, но вы можете передать его в "null"качестве последнего аргумента при @include box-shadowмиксине, например@include box-shadow(12px, 14px, 2px, green, null); сейчас. Если этот аргумент только один в этом свойстве, то это свойство (и его значение (по умолчанию)) не будет скомпилировано , Если в этой «строке» есть два или более аргументов, только те, которые вы обнулили, не будут скомпилированы (ваш случай).

Вывод CSS точно такой, как вы хотели, но вы должны написать свой 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
Определенно, мой любимый способ сделать так, чтобы все было легко читать и понимать, когда нужно возвращаться к сценарию. Thnx Drops.
Plentybinary
7

Вот решение, которое я использую, с примечаниями ниже:

@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);
}
  • предпочитаю передавать значения свойств как нативные css, чтобы оставаться близко к «языку»
  • разрешить передачу переменного числа аргументов
  • определить значение по умолчанию для лени
duggi
источник
Как это добавляет что-либо поверх существующих ответов (а именно: stackoverflow.com/a/28072864/1652962 )?
Цимманон
Он объяснил, как определить, передано ли более одного аргумента функции, и если да, измените вывод. Другой ответ не сделал.
TetraDev
иногда вы хотите определить глобальное поведение. например, анимационные переходы, когда вы, как правило, хотите иметь очень единообразный опыт и не хотите рисковать «творческим усмотрением разработчика», когда дело доходит до решения, что делать. это определяет значение по умолчанию, которое может быть переопределено, но часто не будет из-за более компактного синтаксиса, когда не передаются аргументы. Вы также можете изменить глобальное поведение в одном месте.
Duggi
3

С sass@3.4.9:

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

и использовать без значения, кнопка будет синей

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

и со значением кнопка будет красной

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

работает с гекса тоже

гэл
источник
Как это добавляет что-то поверх существующих ответов?
Цимманон
3

Даже более сухой путь!

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

И теперь вы можете использовать вашу box-shadow еще умнее:

.myShadow {
  @include box-shadow(2px 2px 5px #555, inset 0 0 0);
}
Бен Кальский
источник
Просто примечание - как бы читабельно оно ни было, и я признаю, что именно здесь следует провести грань между СУХИМЫМ кодом и удобочитаемостью / ремонтопригодностью .
Лев Наполеон
Я согласен, чтобы повысить удобочитаемость и удобство обслуживания, я бы создал «список браузеров» для повторного использования в других миксинах. Это также может быть легко собрано с другими свойствами CSS, которые могут быть выполнены с набором сухих смесей. Эта статья 2014 года по-прежнему отличный пример.
Бен Кальский
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;
    }
}
Адам С
источник
Это, возможно, хуже, чем все остальные ответы, из-за его многословия. Кроме того, это достаточно близко к одному из других ответов, чтобы считаться дубликатом.
cimmanon
1

Супер простой способ

Просто добавьте значение по умолчанию noneв $ inset - так

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

Теперь, когда $ inset не передается, ничего не будет отображаться.

fidev
источник
1

Вы всегда можете присвоить null вашим необязательным аргументам. Вот простое исправление

@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

Я новичок в компиляторах CSS, надеюсь, это поможет,

        @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;
}
майкер трекер
источник
Как это добавляет что-то поверх существующих ответов?
Цимманон