Tạo hoặc tham chiếu động các biến trong Sass


91

Tôi đang cố gắng sử dụng nội suy chuỗi trên biến của mình để tham chiếu một biến khác:

// Set up variable and mixin
$foo-baz: 20px;

@mixin do-this($bar) {
    width: $foo-#{$bar};
}

// Use mixin by passing 'baz' string as a param for use $foo-baz variable in the mixin
@include do-this('baz');

Nhưng khi tôi thực hiện việc này, tôi gặp lỗi sau:

Biến không xác định: "$ foo-".

Sass có hỗ trợ các biến biến kiểu PHP không?

Câu trả lời:


49

Sass không cho phép các biến được tạo hoặc truy cập động. Tuy nhiên, bạn có thể sử dụng danh sách cho các hành vi tương tự.

scss:

$list: 20px 30px 40px;    
@mixin get-from-list($index) {
  width: nth($list, $index);
}

$item-number: 2;
#smth {
  @include get-from-list($item-number);
}

css được tạo:

#smth {
  width: 30px; 
}

9
@castus giải quyết vấn đề của bạn như thế nào? Tôi đang gặp phải một vấn đề tương tự trong đó tôi cần lấy một giá trị chuỗi từ một danh sách và thêm $ vào nó và sử dụng nó như một biến.
cmegown

86

Điều này thực sự có thể thực hiện bằng cách sử dụng bản đồ SASS thay vì các biến. Đây là một ví dụ nhanh:

Tham chiếu động:

$colors: (
  blue: #007dc6,
  blue-hover: #3da1e0
);

@mixin colorSet($colorName) {
    color: map-get($colors, $colorName);
    &:hover {
        color: map-get($colors, $colorName#{-hover});
    }
}
a {
    @include colorSet(blue);
}

Kết quả đầu ra như:

a { color:#007dc6 }
a:hover { color:#3da1e0 }

Tạo động:

@function addColorSet($colorName, $colorValue, $colorHoverValue: null) {
  $colorHoverValue: if($colorHoverValue == null, darken( $colorValue, 10% ), $colorHoverValue);

  $colors: map-merge($colors, (
    $colorName: $colorValue,
    $colorName#{-hover}: $colorHoverValue
  ));

  @return $colors;
}

@each $color in blue, red {
  @if not map-has-key($colors, $color) {
    $colors: addColorSet($color, $color);
  }
  a {
    &.#{$color} { @include colorSet($color); }
  }
}

Kết quả đầu ra như:

a.blue { color: #007dc6; }
a.blue:hover { color: #3da1e0; }
a.red { color: red; }
a.red:hover { color: #cc0000; }

10
Lưu ý rằng đây vẫn không phải là "biến động". Đây chỉ là một biến thể của việc sử dụng danh sách các danh sách mà chúng tôi đã sử dụng mãi mãi.
cimmanon

13
Điều này thực sự mở rộng theo danh sách, danh sách chỉ chấp nhận một số chỉ mục làm biến xác định. Nó cho phép các biến được gọi với một tên được tạo động, được tạo bằng cách nối một chuỗi đã truyền, đó là chức năng được yêu cầu.
dibbledeedoo

3
Đây phải là câu trả lời được chấp nhận. Mặc dù không hoàn toàn động, điều này bắt chước chức năng được yêu cầu tốt nhất.
thomaux

1
Trong khi hữu ích, ví dụ này không tạo ra bất kỳ biến ở tất cả
ithil

Thật. Mặc dù tiêu đề của câu hỏi op, văn bản của nó không mô tả việc tạo ra các biến, vì vậy tôi không giải quyết vấn đề đó. Tuy nhiên, chỉ cần thêm một phần liên quan để làm điều đó (mặc dù vẫn với bản đồ, không phải biến số ít).
dibbledeedoo

5

Bất cứ khi nào tôi cần sử dụng giá trị có điều kiện, tôi đều dựa vào các hàm. Đây là một ví dụ đơn giản.

$foo: 2em;
$bar: 1.5em;

@function foo-or-bar($value) {
  @if $value == "foo" {
    @return $foo;
  }
  @else {
    @return $bar;
  }
}

@mixin do-this($thing) {
  width: foo-or-bar($thing);
}

Tôi nghĩ đây chính xác là những gì tôi đang tìm kiếm. Đây thực chất là lấy giá trị được truyền vào mixin và chạy nó thông qua hàm. Sau đó, tùy thuộc vào một loạt các câu lệnh if, trả về cùng một giá trị chuỗi như một biến. Có thể thực hiện điều này với một số giá trị có thể là vô hạn không? Giả sử chúng ta có một danh sách gồm nhiều chuỗi, không chỉ foo hoặc bar.
cmegown

3
Đây là thực hành xấu thuần túy, bạn không muốn kết thúc với một chuỗi điều kiện if vô tận. Sử dụng bản đồ SASS với các cặp giá trị chính và thay vào đó lấy các giá trị từ nó.
mystrdat

Nó chủ yếu là thừa trong buổi giới thiệu này - tại sao bạn không gọi @include do-this($foo);? ... tuy nhiên điều này sẽ có ý nghĩa, nếu chức năng thực sự đã làm một cái gì đó, nhưng nó chỉ đi qua ...
jave.web

2

Đây là một tùy chọn khác nếu bạn đang làm việc với đường ray và có thể trong các trường hợp khác.

Nếu bạn thêm .erb vào cuối phần mở rộng của tệp, Rails sẽ xử lý lỗi trên tệp trước khi gửi nó đến trình thông dịch SASS. Điều này giúp bạn có cơ hội làm những gì bạn muốn trong Ruby.

Ví dụ: (Tệp: foo.css.scss.erb)

// Set up variable and mixin
$foo-baz: 20px; // variable

<%
def do_this(bar)
  "width: $foo-#{bar};"
end
%>

#target {
  <%= do_this('baz') %>
}

Kết quả trong scss sau:

// Set up variable and mixin
$foo-baz: 20px; // variable

#target {
  width: $foo-baz;
}

Cái nào, trong số thô, dẫn đến css sau:

#target {
  width: 20px;
}

0

Gần đây, tôi bắt gặp nhu cầu tham chiếu động một màu.

Tôi có tệp _colours.scss cho mọi dự án, nơi tôi xác định tất cả các màu của mình một lần và tham chiếu chúng dưới dạng các biến trong suốt.

Trong tệp _forms.scss của tôi, tôi muốn thiết lập các kiểu nút cho từng màu có sẵn. Thường là một nhiệm vụ tẻ nhạt. Điều này đã giúp tôi tránh phải viết cùng một mã cho mỗi màu khác nhau.

Nhược điểm duy nhất là bạn phải liệt kê từng tên màu và giá trị trước khi viết css thực.

// $red, $blue - variables defined in _colours.scss
$colours: 
  'red' $red,
  'blue' $blue;

@each $name, $colour in $colours {
  .button.has-#{$name}-background-color:hover {
    background-color: lighten($colour, 15%);
  }
}

-2

Hiện tại, không thể tạo một biến động trong SASS, vì bạn sẽ thêm / kết nối một var khác cần được phân tích cú pháp một lần khi bạn chạy lệnh sass.

Ngay sau khi lệnh chạy, nó sẽ báo lỗi cho CSS không hợp lệ, vì tất cả các biến đã khai báo của bạn sẽ theo sau khi lưu trữ.

Sau khi chạy, bạn không thể khai báo các biến một cách nhanh chóng

Để biết rằng tôi đã hiểu điều này, vui lòng nêu rõ điều sau là đúng:

bạn muốn khai báo các biến trong đó phần tiếp theo (từ) là động

cái gì đó như

$list: 100 200 300;

@each $n in $list {
    $font-$n: normal $n 12px/1 Arial;
}

// should result in something like

$font-100: normal 100 12px/1 Arial;
$font-200: normal 200 12px/1 Arial;
$font-300: normal 300 12px/1 Arial;

// So that we can use it as follows when needed

.span {
    font: $font-200;
    p {
       font: $font-100
    }
}

Nếu đây là những gì bạn muốn, tôi sợ là bây giờ, điều này không được phép


3
Đáng tiếc là điều này không làm việc: Lỗi SCSS / components.scss (Tuyến 71: CSS hợp lệ sau khi "$ in-": dự kiến ":", là "$ n: bình thường $ n 1 ...")
Krzysztof Romanowski

4
@castus, rất tiếc! xin lỗi vì không rõ ràng - Tôi không đưa ra một giải pháp, chứ không phải giải thích các câu hỏi một lần nữa
Om Shankar

15
có lẽ không nên đăng một giải pháp không được phép!
Rhyso

tôi chiều rộng điều này sẽ hoạt động nhưng có vẻ như chúng tôi không thể tạo các biến thông qua sass?
v3nt
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.