Tạo một mixin Sass với các đối số tùy chọn


201

Tôi đang viết một mixin như thế này:

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

Khi được gọi là điều tôi thực sự muốn là nếu không có $insetgiá trị nào được thông qua, không có gì là đầu ra, thay vì nó biên dịch thành thứ như thế này:

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

Làm cách nào để viết lại mixin để nếu không có giá trị nào $insetđược chuyển, không có gì là đầu ra?


6
Thật xấu hổ khi SASS không có blankhoặc nilgiá trị.
Joshua Pinter

1
Btw, trong khi xem xét một giới hạn SASS khác, tôi đã tìm ra một cách hay để loại bỏ các trích dẫn trong những tình huống này. Tôi đã thêm một câu trả lời cho nó.
Joshua Pinter

4
Bây giờ trong năm 2015, bạn chỉ có thể sử dụng nullđể bỏ qua attr / prop. ie @include box-shadow($top, $left, $blur, $color, null)
Rơi

Câu trả lời:


257

Cách làm của DRY'r

Và, nói chung, một mẹo gọn gàng để loại bỏ các trích dẫn.

@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 Phiên bản 3+, bạn có thể sử dụng 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);
} 

Đã chọn cái này ở đây: chuyển một danh sách cho một mixin dưới dạng một đối số với SASS


6
Như Bob Sammer chỉ ra, trong phiên bản SASS mới hơn, bạn cũng có thể sử dụng phương thức unquote () thay vì # {} để xóa dấu ngoặc kép. Chúc mừng.
Joshua Pinter

4
cách đơn giản nhất là sử dụng nullcho giá trị mặc định của các tham số tùy chọn thay vì ""và chúng sẽ không được hiển thị ở đầu ra! @mixin box-shadow($top, $left,... , $inset:null) {}
S.Serpooshan

@ S.Serpooshan Tôi tò mò không biết phiên bản này đã được thêm vào. Điều này chắc chắn không được hỗ trợ trở lại vào năm 2012.
Joshua Pinter

79

Một cách tốt hơn rất nhiều

là phải vượt qua $args...đến @mixin. Bằng cách đó, cho dù $argsbạn sẽ vượt qua bao nhiêu . Trong @inputcuộc gọi, bạn có thể vượt qua tất cả các đối số cần thiết. Thích như vậy:

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

Và bây giờ bạn có thể sử dụng lại bóng hộp của mình trong mọi lớp bạn muốn bằng cách chuyển tất cả các đối số cần thiết:

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

11
Đó là của tốt để biết nhưng thường thì nó rõ ràng hơn để chỉ ra những gì đối số một mixinđược mong đợi, như $top, $left, $blurvv đối số biến, như bạn đã thấy, là tuyệt vời cho linh hoạt tối đa, mặc dù.
Joshua Pinter

1
Cảm ơn, anh bạn đã giúp tôi rất nhiều
Nilesh Sutar

48

Sass hỗ trợ @ifbáo cáo. (Xem tài liệu .)

Bạn có thể viết mixin của bạn như thế này:

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

Điều này không hữu ích ở đây, chỉ insetloại trừ một phần khi nó là null, không phải tất cả các thuộc tính bóng hộp
S.Serpooshan

@ S.Serpooshan Chỉ cần thêm một elsevà bao gồm tất cả các thuộc tính không chèn bên trong.
mbomb007

@ mbomb007 tôi biết, tôi chỉ báo cáo một vấn đề với giải pháp này. Và các câu trả lời khác được cung cấp ở trên là hoàn toàn tốt hơn.
S.Serpooshan

26

Bạn có thể đặt thuộc tính bằng null làm giá trị mặc định và nếu bạn không vượt qua tham số thì nó sẽ không được giải thích.

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

Điều này có nghĩa là bạn có thể viết câu lệnh bao gồm như thế này.

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

Thay vì viết nó như thế này.

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

Như thể hiện trong câu trả lời ở đây


1
Câu trả lời này không có gì mới so với các câu trả lời hiện có (xem: stackoverflow.com/a/23565388/1652962 )
cimmanon

9
@cimmanon Ngược lại, điều này cung cấp tiện ích bổ sung khi bạn có thể viết nhập @include box-shadow($top, $left, $blur, $color);thay vì @include box-shadow($top, $left, $blur, $color, null);. Vì vậy, câu trả lời này là rất nhiều lợi ích.
Dan

1
@Dan Thật ra bạn mất khả năng đọc khi làm theo cách đó, vì vậy có thể nói rằng nó ít có lợi hơn câu trả lời mà nó bắt nguồn.
TylerH

@TylerH Đó là sự thật
Dan

14

Câu hỏi cũ, tôi biết, nhưng tôi nghĩ rằng điều này vẫn còn có liên quan. Có thể cho rằng, một cách rõ ràng hơn để làm điều này là sử dụng hàm unquote () (mà SASS đã có từ phiên bản 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);
}

Điều này gần tương đương với câu trả lời của Josh, nhưng tôi nghĩ rằng hàm được đặt tên rõ ràng ít bị xáo trộn hơn cú pháp nội suy chuỗi.


12

Tôi biết đó không chính xác là câu trả lời mà bạn đang tìm kiếm nhưng bạn có thể vượt qua "null"như đối số cuối cùng khi @include box-shadowmixin, như thế này@include box-shadow(12px, 14px, 2px, green, null); Bây giờ, nếu đối số đó chỉ là một trong thuộc tính đó so với thuộc tính đó (và giá trị (mặc định) của nó) sẽ không được biên dịch . Nếu có hai hoặc nhiều đối số trên "dòng" đó, chỉ những đối số mà bạn đã hủy sẽ không được biên dịch (trường hợp của bạn).

Đầu ra CSS chính xác như bạn muốn, nhưng bạn phải viết 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
Chắc chắn cách yêu thích của tôi để làm điều này giúp mọi thứ đơn giản để đọc và hiểu khi bạn phải quay lại với một kịch bản. giọt thnx.
Plentybinary

7

Đây là giải pháp tôi sử dụng, với ghi chú bên dưới:

@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);
}
  • thích chuyển các giá trị thuộc tính như css riêng để ở gần "lưỡi"
  • cho phép chuyển số lượng đối số biến
  • xác định một giá trị mặc định cho sự lười biếng

Làm thế nào để điều này thêm bất cứ điều gì qua các câu trả lời hiện có (cụ thể là: stackoverflow.com/a/28072864/1652962 )?
cimmanon

Ông giải thích làm thế nào để biết nếu có nhiều hơn một đối số được truyền cho hàm và nếu vậy, hãy thay đổi đầu ra. Câu trả lời khác là không.
TetraDev

đôi khi, bạn muốn xác định một hành vi toàn cầu. ví dụ: các hiệu ứng chuyển cảnh mà bạn thường muốn có trải nghiệm rất đồng đều và không muốn mạo hiểm "quyền phát triển sáng tạo" khi quyết định làm gì. điều này xác định một mặc định có thể bị ghi đè nhưng thường sẽ không phải do cú pháp nhỏ gọn hơn khi không truyền đối số. bạn cũng có thể thay đổi hành vi toàn cầu ở một nơi theo cách này.
duggi

3

Với sass@3.4.9:

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

và sử dụng không có giá trị, nút sẽ có màu xanh

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

và với giá trị, nút sẽ có màu đỏ

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

cũng hoạt động với hexa


Làm thế nào để điều này thêm bất cứ điều gì qua các câu trả lời hiện có?
cimmanon

3

Ngay cả cách DRYer!

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

Và bây giờ bạn có thể sử dụng lại bóng hộp của mình thậm chí thông minh hơn:

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

Chỉ cần một lưu ý - dễ đọc như thế này và tôi thừa nhận rằng, đây là nơi người ta nên vẽ ranh giới giữa mã DRY và khả năng đọc / bảo trì .
Leo Napoleon

Tôi đồng ý, để tăng khả năng đọc / bảo trì, tôi sẽ tạo một "danh sách trình duyệt" để sử dụng lại trong các mixin khác. Điều này cũng có thể được lắp ráp khá dễ dàng vào các thuộc tính css khác, có thể được thực thi bằng một tập hợp các hỗn hợp khô. Bài viết này từ năm 2014 vẫn là ví dụ tuyệt vời.
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;
    }
}

Điều này được cho là tồi tệ hơn tất cả các câu trả lời khác, do tính dài dòng của nó. Ngoài ra, nó đủ gần với một trong những câu trả lời khác để tính là một bản sao.
cimmanon

1

Cách siêu đơn giản

Chỉ cần thêm một giá trị mặc định là none$ inset - vì vậy

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

Bây giờ khi không có $ inset nào được thông qua, sẽ không được hiển thị.


1

Bạn luôn có thể gán null cho các đối số tùy chọn của mình. Đây là một sửa chữa đơn giản

@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

Tôi chưa quen với trình biên dịch css, hy vọng điều này sẽ giúp,

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

Làm thế nào để điều này thêm bất cứ điều gì qua các câu trả lời hiện có?
cimmanon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.