Створення Sass mixin з необов'язковими аргументами


201

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

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

Зібрано це тут: передайте список до міксину як єдиний аргумент із SASS


6
Як зазначає Боб Саммерс, у новій версії SASS ви можете також використовувати метод unvootete () замість # {} для видалення лапок. Ура.
Джошуа Пінтер

4
найпростіший спосіб - використовувати nullза замовчуванням значення необов'язкових параметрів замість "", і вони не будуть виведені у висновку! @mixin box-shadow($top, $left,... , $inset:null) {}
S.Serpooshan

@ S.Serpooshan Мені цікаво, в яку версію додано це. Це, звичайно, не підтримувалося ще у 2012 році.
Джошуа Пінтер

79

Настільки кращий DRY спосіб

це перейти $args...до @mixin. Таким чином, скільки б $argsви не пройшли. У @inputдзвінку ви можете передавати всі необхідні аргументи. Так:

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

Тепер ви можете використовувати свою тінь-коробку в кожному класі, передаючи всі необхідні аргументи:

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

11
Це добре знати , але найчастіше це більш ясно вказати , які аргументи mixinочікує, як $top, $left, $blurі т.д. Змінні аргументи, як ви показали, є великими для максимальної гнучкості, однако.
Джошуа Пінтер

1
Дякую, чувак, мені це дуже допомагає
Нілеш Сутар

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частина повинна бути виключена, коли вона є
недійсною

@ S.Serpooshan Просто додайте elseі включіть все невстановлені властивості всередину.
mbomb007

@ mbomb007 Я знаю, я просто повідомляю про проблему з цим рішенням. А інші відповіді, подані вище, абсолютно кращі.
S.Serpooshan

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, як це.

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

Замість того, щоб писати так.

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

Як показано у відповіді тут


1
Ця відповідь пропонує нічого нового по порівнянні з існуючими відповідями (див: stackoverflow.com/a/23565388/1652962 )
cimmanon

9
@cimmanon Навпаки, це забезпечує додаткову корисність, оскільки ви зможете записати імпорт як @include box-shadow($top, $left, $blur, $color);замість @include box-shadow($top, $left, $blur, $color, null);. Тому ця відповідь є набагато доброякіснішою.
Dan

1
@Dan Насправді ви втрачаєте читабельність, роблячи це таким чином, тому, мабуть, це менш вигідно, ніж відповідь, з якого він отриманий.
TylerH

@TylerH Це правда
Dan

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 точно такий, як ви цього хотіли, але ви повинні написати своє 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
Безумовно, мій улюблений спосіб зробити це дозволяє просто прочитати і зрозуміти, коли вам потрібно повернутися до сценарію. краплі thnx.
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, щоб залишатися близько до "язика"
  • дозволяють передавати змінну кількість аргументів
  • визначте значення за замовчуванням для лінь

Як це додає щось до існуючих відповідей (а саме: stackoverflow.com/a/28072864/1652962 )?
cimmanon

Він пояснив, як сказати, якщо більше ніж один аргумент передано функції, і якщо так, змінити вихід. Іншої відповіді не було.
TetraDev

іноді ви хочете визначити глобальну поведінку. наприклад, анімаційні переходи, де ти, як правило, хочеш мати дуже рівномірний досвід і не хочеш ризикувати "творчим розсудом розробника", коли йдеться про рішення, що робити. це визначає за замовчуванням, який можна змінити, але часто не буде через більш компактний синтаксис, коли не передавати аргументи. ви також можете змінити глобальну поведінку в одному місці таким чином.
diggi

3

З sass@3.4.9:

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

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

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

і зі значенням кнопка буде червоною

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

також працює з hexa


Як це щось додає до наявних відповідей?
cimmanon

3

Навіть DRYer спосіб!

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

А тепер ви можете використовувати свою тінь-коробку ще розумнішою:

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

Лише зауваження - настільки начитане, як це є, і я визнаю, що саме тут слід провести межу між кодом DRY та читабельністю / ремонтопридатністю .
Лев Наполеон

Я погоджуюсь, щоб збільшити читабельність / ремонтопридатність, я створив би "список браузерів" для повторного використання в інших комбінаціях. Це також може бути досить легко зібрати для інших властивостей 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) { ....

Тепер, коли не буде пропущено жодної вставки, нічого не відображатиметься.


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

Як це щось додає до наявних відповідей?
cimmanon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.