時々、趣味で Sass を書くこともできますし、それがもたらすさまざまな利便性を楽しむこともできるでしょう。しかし、必ずしも十分に理解していないことが 1 つあります。それは、補間 - プレースホルダーを値に置き換えることです。さて、今日はこれをはっきりさせておきますので、皆さんは幸運です。
補間は通常、変数の補間または変数の置換を指します。これは Sass に限ったことではありません。実際、この機能は多くのプログラミング言語で見られます。 PHP、Perl、Ruby、Tcl、Groovy、Unix シェルなど。私たちがよく言うのは、変数を挿入する、または式を挿入するということです。
まず例を見てみましょう。 PHP の基本的な知識がある場合は、次のステップは簡単に理解できるはずです。たとえば、変数を含む文字列を出力したい場合、最も一般的な方法は次のとおりです:
$description = "awesome"; echo "Tuts+ is " . $description . "!";
これは補間メソッドではなく、文字列を連結しています。このうち、「Tuts+ is "、awesome ($description で参照)、および "!" の 3 つの文字列が連結されています。ここで、文字列連結の代わりに補間を使用する方法を見てみましょう:
$description = "awesome"; echo "Tuts+ is ${description}!";
変数を囲む中括弧は、変数の値を文字列として出力するように PHP に指示します。注目に値します: 機能するには二重引用符で囲む必要があります (これはほとんどの言語の場合です)。
とにかく、それが変数/式の補間です。文字列の連結と補間を使用するかどうかは、ユーザー次第です。しかし、一つ言えることは、補間は実際には文字列連結のための糖衣構文にすぎないということです。
まず、Sass で変数置換がどのように機能するかを見てみましょう。
Sass 変数は、PHP と同様にドル記号 ($) を使用して名前が付けられます。補間に関しては、両者のパフォーマンスが異なるため、両者の比較は終了したようです。適切な説明は次のとおりです。Sass は Ruby に基づいており、式の置換に ${} を使用します。
Sass では、次のようにします:
$description: "awesome"; @warn "Tuts+ is #{$description}!";
PHP のように変数内の $ を失うことはできないことに注意してください。変数は #{} で囲まれます。また、文字列だけでなく、あらゆるタイプの変数を挿入できることにも注意してください。
例:
$answer: 42; @warn "The Answer to the Ultimate Question of Life, the Universe, and Everything is #{$answer}.";
ここで、補間とは何か、そしてそれが Sass でどのように機能するかを理解する必要があります。いよいよ実際のシナリオに取り組み始めます。まず、先ほど実行した @warn ディレクティブを再度使用します。これにより、対応するコンテンツがコンソールに出力されます。
$colors というカラー マップのセットがあるとします (マップとは、一連のキーと値の組み合わせを格納する変数を指します) が、map を何度も入力するのにうんざりしています - get($colors, ...)。したがって、キーを使用して対応する値を取得する単純な color() 関数を作成します。
これらをまとめてください:
すべて問題ありませんね?ここで、間違った名前を入力したり、存在しないキーを取得したりしたときに、エラー メッセージを表示する必要があります。これは @warn ディレクティブを介して行われます。 color() 関数は次のとおりです:
// _config.scss $colors: ( "primary": tomato, "secondary": hotpink ); // _function.scss @function color($key) { @return map-get($colors, $key); } // _component.scss .el { background-color: color(primary); }
悪くありません。どのキーが見つからないかを知りたい場合はどうすればよいでしょうか?
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key not found."; } @return map-get($colors, $key); }
嘣~~変数補間。 color(awesomeness) が呼び出されると、次のメッセージがスローされます:
Key awesomeness not found
これは本当に素晴らしいですが、コンテキストが何なのかはわかりません。後で便利なように、マッピングの名前をエラー メッセージに書き込むことができます。
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key `#{$key}` not found."; } @return map-get($colors, $key); }
このシナリオでは、$colors 変数は補間を使用しないため、次の情報が出力されます:
$colors マップには見つからない主要な機能
これまで見てきました。ここで、最も一般的な変数置換シナリオ、つまり変数の内容を文字列で出力します。これは確かに良い例ですが、calc() などの CSS 関数の変数という、より良いシナリオがあるはずだと思います。
サイドバーの幅に基づいてメインコンテナのサイズを設定したいとします。あなたは勤勉なフロントエンド開発者で、この幅を変数に保存しているので、次のようにするかもしれません:
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key `#{$key}` not found in $colors map."; } @return map-get($colors, $key); }
すると、まったく機能しないことに驚くでしょう。エラーは報告されませんが、コンテナーのサイズが正しくありません。 dom 要素を調べてみると、これに取り消し線が引かれているのがわかります。これは違法だからです。
$sidebar-width: 250px; .main { width: calc(100% - $sidebar-width); }
ここで、calc() は Sass 関数ではなく CSS 関数であると考えるべきです。これは、Sass が式全体を文字列として解釈することを意味します。試してみることができます:
.main { width: calc(100% - $sidebar-width); }
これは文字列なので、Sass が以前の @warn の $colors 文字列と同じように動作するのも不思議ではありません。 $sidebar-width は通常の文字列とみなされ、そのまま入力されます。でも、それは私たちが望んでいることではありませんよね?これは補間を使用して行います。
うわーSass がこのスタイル ファイルをコンパイルすると、#{$sidebar-width} が #{$sidebar-width} の値 250px に置き換えられます。最後に、正当な CSS 式があります。
やれやれ任務完了!ここでは calc() についてのみ説明しましたが、実際には、疑似クラスを含む他の CSS ネイティブ関数と同じです。例: url()、linear-gradient()、radial-gradient()、cubic-bezier()。
以下是另一个使用CSS函数的例子:
@for $i from 1 through $max { .el:nth-of-type(#{$i}) { // ... } }
这是一个你有可能遇到过的场景:for循环和:nth-*()选择器一起使用。再一次说明,你需要使用插值变量,才能最终得到想得到的结果。
小结:Sass会把CSS函数认为是字符串,所以想要在最后获得它们的值,要求你转义所有同它们一起使用的变量。
我们将视转移到另一个有趣的变量插值场景:CSS指令,比如@support,@page,最重要的还是@media。
现在,Sass是怎样解析CSS指令,尤其是demia指令的。我已经查看过Sass的源码,当我Ruby环境有点问题的时候,我找到一些有趣的事情。
def query_expr interp = interpolation return interp if interp return unless tok(/\(/) res = ['('] ss res << sass_script(:parse) if tok(/:/) res << ': ' ss res << sass_script(:parse) end res << tok!(/\)/) ss res end
第一行告诉Sass,如果有一个插值表达式的话,便返回media query。如果找到一个开括号((),便会一直往下走,解析所有的东西,反之就会抛出一个错误。我们在这里试试一个例子:
$value: screen; @media $value { // ... }
毫不惊讶的是,这失败了:
Invalid CSS after "@media (" at media) ": expected media query (e.g. print, screen, print and screen), was "$value {"
就像错误信息提示的那样,它期待一个media query。在这里,如果你的变量在 @media 字符串后面,需要使用插值才可以。比如:
$value: screen; @media #{$value} { // ... }
和我们之前讨论的Ruby转义规则一样,如果@media后面紧跟(()),你就不再需要插值变量了,因为Sass会求出所有在这些括号里面的值。比如:
$value: 1336px; @media (max-width: $value) { // ... }
在这个示例中,Sass将这个表达式(max-width: $value)转化成(max-width: 1337px),最后生成合法的CSS结果。所以,我们便没有必要再对变量转义了。
好的,这将是最后一个示例:使用变量作为一个选择器,或者选择器的一部分。这不是一种常用的用法,以下的做法不太符合常识:
$value: custom; selector-$value { property: value; }
不幸的是,这根本无法编译成功:
Invalid CSS after "selector-": expected "{", was "$value {"
这是media query那个例子的原因,差不多。Sass有着自己的方式解析一个CSS选择器。如果它遇到了不可预知的东西,比如一个未经处理的美元符号,它就会直接崩溃。
幸运的,解决这个问题也相当简单(你也已经知道怎么做了):没错,使用插值变量!
$value: custom; selector-#{$value} { property: value; }
在最后,Sass的插值没有看起来那么简单。在一些示例之中,你必须转义你的变量,一些示例中,你却不必。如果是那样,你有两种方式处理:
不管怎样,我希望你明白了插值变量是如何工作的。如果你有什么需要添加的,请在留言中指出。