การสร้างหรืออ้างอิงตัวแปรแบบไดนามิกใน Sass


95

ฉันพยายามใช้การแก้ไขสตริงกับตัวแปรของฉันเพื่ออ้างอิงตัวแปรอื่น:

// 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');

แต่เมื่อฉันทำสิ่งนี้ฉันได้รับข้อผิดพลาดต่อไปนี้:

ตัวแปรที่ไม่ได้กำหนด: "$ foo-"

Sass รองรับตัวแปรตัวแปรสไตล์ PHP หรือไม่

คำตอบ:


51

Sass ไม่อนุญาตให้สร้างหรือเข้าถึงตัวแปรแบบไดนามิก อย่างไรก็ตามคุณสามารถใช้รายการสำหรับลักษณะการทำงานที่คล้ายกัน

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:

#smth {
  width: 30px; 
}

9
@castus วิธีนี้ช่วยแก้ปัญหาของคุณได้อย่างไร? ฉันพบปัญหาที่คล้ายกันมากซึ่งฉันต้องใช้ค่าสตริงจากรายการและเพิ่ม $ เข้าไปและใช้เป็นตัวแปร
cmegown

89

สิ่งนี้ทำได้จริงโดยใช้แผนที่ SASS แทนตัวแปร นี่คือตัวอย่างสั้น ๆ :

การอ้างอิงแบบไดนามิก:

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

ผลลัพธ์เป็น:

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

สร้างแบบไดนามิก:

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

ผลลัพธ์เป็น:

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

10
โปรดทราบว่านี่ยังไม่ใช่ "ตัวแปรไดนามิก" นี่เป็นเพียงรูปแบบหนึ่งของการใช้รายการที่เราใช้มาตลอด
cimmanon

13
สิ่งนี้ขยายตามรายการซึ่งยอมรับเฉพาะหมายเลขดัชนีเป็นตัวแปรที่ระบุ ช่วยให้สามารถเรียกตัวแปรด้วยชื่อที่สร้างขึ้นแบบไดนามิกซึ่งสร้างขึ้นโดยการต่อสตริงที่ส่งผ่านซึ่งเป็นฟังก์ชันที่ร้องขอ
dibbledeedoo

3
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ แม้ว่าจะไม่ใช่ไดนามิกอย่างสมบูรณ์ แต่ก็เลียนแบบฟังก์ชันการทำงานที่ร้องขอได้ดีที่สุด
thomaux

1
แม้ว่าจะมีประโยชน์ แต่ตัวอย่างนี้ไม่ได้สร้างตัวแปรใด ๆ เลย
ithil

จริง. แม้จะมีชื่อคำถามของ op แต่ข้อความของมันไม่ได้อธิบายถึงการสร้างตัวแปรดังนั้นฉันจึงไม่ได้พูดถึงเรื่องนั้น อย่างไรก็ตามเพิ่งเพิ่มส่วนที่เกี่ยวข้องกับการทำเช่นนั้น (แม้ว่าจะยังอยู่ในแผนที่ไม่ใช่ตัวแปรเอกพจน์)
dibbledeedoo

5

เมื่อใดก็ตามที่ฉันต้องใช้ค่าตามเงื่อนไขฉันพึ่งพาฟังก์ชัน นี่คือตัวอย่างง่ายๆ

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

ฉันคิดว่านี่คือสิ่งที่ฉันกำลังมองหา นี่คือการรับค่าที่ส่งผ่านไปยัง mixin เป็นหลักและเรียกใช้ผ่านฟังก์ชัน จากนั้นขึ้นอยู่กับชุดของคำสั่ง if ให้ส่งคืนค่าสตริงเดียวกันกับตัวแปร เป็นไปได้ไหมที่จะทำสิ่งนี้ด้วยจำนวนค่าที่อาจไม่สิ้นสุด สมมติว่าเรามีรายการสตริงมากมายไม่ใช่แค่ foo หรือ bar
cmegown

3
นี่เป็นการปฏิบัติที่ไม่ดีอย่างแท้จริงคุณไม่ต้องการที่จะจบลงด้วยห่วงโซ่ของเงื่อนไขที่ไม่มีที่สิ้นสุด ใช้แผนที่ SASS กับคู่ค่าคีย์และดึงค่าจากแผนที่นั้นแทน
mystrdat

ส่วนใหญ่มันซ้ำซ้อนในตู้โชว์นี้ - ทำไมคุณไม่เรียกแค่@include do-this($foo);? ... อย่างไรก็ตามสิ่งนี้จะสมเหตุสมผลถ้าฟังก์ชั่นทำบางสิ่งบางอย่างได้จริง แต่มันจะผ่านไปเท่านั้น ...
jave.web

2

นี่เป็นอีกทางเลือกหนึ่งหากคุณกำลังทำงานกับรางรถไฟและอาจอยู่ภายใต้สถานการณ์อื่น ๆ

หากคุณเพิ่ม. erb ต่อท้ายนามสกุลไฟล์ Rails จะประมวลผล erb บนไฟล์ก่อนที่จะส่งไปยังตัวแปล SASS สิ่งนี้ทำให้คุณมีโอกาสทำในสิ่งที่คุณต้องการใน Ruby ได้

ตัวอย่างเช่น: (File: 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') %>
}

ผลลัพธ์ใน scss ต่อไปนี้:

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

#target {
  width: $foo-baz;
}

ซึ่งของหยาบส่งผลให้เกิด css ต่อไปนี้:

#target {
  width: 20px;
}

0

ฉันเจอความจำเป็นในการอ้างอิงสีแบบไดนามิกเมื่อเร็ว ๆ นี้

ฉันมีไฟล์ _colours.scss สำหรับทุกโปรเจ็กต์ซึ่งฉันกำหนดสีทั้งหมดของฉันเพียงครั้งเดียวและอ้างอิงเป็นตัวแปรตลอด

ในไฟล์ _forms.scss ของฉันฉันต้องการตั้งค่ารูปแบบปุ่มสำหรับแต่ละสีที่มี มักจะเป็นงานที่น่าเบื่อ สิ่งนี้ช่วยให้ฉันหลีกเลี่ยงการเขียนโค้ดเดียวกันสำหรับแต่ละสีที่ต่างกัน

ข้อเสียเพียงอย่างเดียวคือคุณต้องระบุชื่อสีและค่าแต่ละสีก่อนที่จะเขียน css จริง

// $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

ในการสร้างตัวแปรแบบไดนามิกเป็นไปไม่ได้ใน SASS ณ ตอนนี้เนื่องจากคุณจะเพิ่ม / เชื่อมต่อตัวแปรอื่นที่ต้องแยกวิเคราะห์หนึ่งครั้งเมื่อคุณรันคำสั่ง sass

ทันทีที่คำสั่งทำงานคำสั่งจะแสดงข้อผิดพลาดสำหรับ Invalid CSS เนื่องจากตัวแปรที่ประกาศทั้งหมดของคุณจะตามมา

เมื่อเรียกใช้แล้วคุณจะไม่สามารถประกาศตัวแปรได้อีกทันที

เพื่อให้ทราบว่าฉันเข้าใจสิ่งนี้แล้วโปรดระบุว่าสิ่งต่อไปนี้ถูกต้องหรือไม่:

คุณต้องการประกาศตัวแปรโดยที่ส่วนถัดไป (word) เป็นแบบไดนามิก

สิ่งที่ต้องการ

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

หากนี่คือสิ่งที่คุณต้องการฉันกลัว ณ ตอนนี้สิ่งนี้ไม่ได้รับอนุญาต


3
น่าเสียดายที่สิ่งนี้ไม่ทำงาน: error scss / components.scss (บรรทัด 71: CSS ไม่ถูกต้องหลัง "$ font-": expected ":" คือ "$ n: normal $ n 1 ... ")
Krzysztof Romanowski

4
@castus อ๊ะ! ขออภัยที่ไม่ชัดเจน - ฉันไม่ได้ให้คำตอบแทนที่จะอธิบายคำถามอีกครั้ง
Om Shankar

16
อาจไม่ควรโพสต์วิธีแก้ปัญหาที่ไม่ได้รับอนุญาต!
Rhyso

ฉันกว้างสิ่งนี้จะใช้งานได้ แต่ดูเหมือนว่าเราไม่สามารถสร้างตัวแปรผ่าน sass ได้?
v3nt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.