Home >Web Front-end >HTML Tutorial >What you need to know about Sass interpolation_html/css_WEB-ITnose
You may write Sass for fun from time to time, and you will also enjoy the various conveniences it brings to you. But there's one thing you don't necessarily fully understand: interpolation - replacing a placeholder with a value. Well, you're all in luck because today I'm going to make this clear.
Interpolation usually refers to variable interpolation or variable replacement. This is not unique to Sass. In fact, you can find this feature in many programming languages. Such as PHP, Perl, Ruby, Tcl, Groovy, Unix shells, etc. What we often say is to insert a variable or insert an expression.
Let’s take a look at an example first. If you have a basic knowledge of PHP, the next step should be easy to understand. For example, if you want to print a string containing variables, the most common way is:
$description = "awesome"; echo "Tuts+ is " . $description . "!";
This is not an interpolation method, you are concatenating strings. Among them, three strings are concatenated: "Tuts is ", awesome (referenced by $description) and "!". Now, let’s look at using interpolation instead of string concatenation:
$description = "awesome"; echo "Tuts+ is ${description}!";
The curly braces wrapped around the variable will tell PHP to print out the value of the variable as a string. It's worth noting: it needs to be inside double quotes to work (this is the case in most languages).
Anyway, that’s variable/expression interpolation. Whether to use string concatenation or interpolation is up to you. But one thing can be said: interpolation is actually just syntactic sugar for string concatenation.
Let’s first look at how variable substitution works in Sass.
Sass variables are named with a dollar sign ($) just like PHP. The comparison between the two seems to be over, because when it comes to interpolation, the performance of the two is different. A good explanation is: Sass is based on Ruby and uses ${} for expression substitution.
In Sass, you would do this:
$description: "awesome"; @warn "Tuts+ is #{$description}!";
It is important to note that the $ in the variable cannot be thrown away like in PHP. Variables are wrapped in #{}. Also worth mentioning: you can insert any type of variable, not just strings.
For example:
$answer: 42; @warn "The Answer to the Ultimate Question of Life, the Universe, and Everything is #{$answer}.";
Now you should understand what interpolation is and how it works in Sass. It's time to start working on the actual scenario. First, we will use the @warn directive we just did again, which will print the corresponding content to the console.
Suppose you have a set of color maps called $colors (a map is a variable that stores a series of key/value combinations), but you've had enough I hit map-get($colors, ...) again and again. So, you write a simple color() function that uses key to get the corresponding value.
Putting these together:
// _config.scss $colors: ( "primary": tomato, "secondary": hotpink ); // _function.scss @function color($key) { @return map-get($colors, $key); } // _component.scss .el { background-color: color(primary); }
That’s all good, isn’t it? Now, when you type the wrong name, or retrieve a key that doesn't exist, you want to give an error message. This will be done via the @warn directive. The color() function is as follows:
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key not found."; } @return map-get($colors, $key); }
Not bad. What if you want to know which key is not found?
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key `#{$key}` not found."; } @return map-get($colors, $key); }
Boom~~variable interpolation. When color(awesomeness) is called, the following message will be thrown:
Key awesomeness not found
This is really cool, but we have no idea what the context is. For convenience later, we can write the name of the mapping into the error message.
@function color($key) { @if not map-has-key($colors, $key) { @warn "Key `#{$key}` not found in $colors map."; } @return map-get($colors, $key); }
In this scenario, since the $colors variable is not interpolated, it will print the following message:
Key awesomeness not found in $colors map.
So far, we have seen the most common variable replacement scenario: printing the contents of variables in a string. This is indeed a good example, but I think there should be a better scenario: variables in CSS functions, such as calc().
Suppose you want to set the size of the main container based on the width of the sidebar. You're a diligent front-end developer and have stored this width in a variable, so, you might do:
$sidebar-width: 250px; .main { width: calc(100% - $sidebar-width); }
Then, you'd be surprised to find that doesn't work at all. No error is reported, but the size of the container is incorrect. If you go and inspect your dom element, you'll see this ? crossed out. Because this is illegal.
.main { width: calc(100% - $sidebar-width); }
Now we should think: calc() is a CSS function, not a Sass function. This means that Sass will interpret the entire expression as a string. You can try:
$type-of-expression: type-of(calc(100% - $sidebar-width)); // string
Since this is a string, no wonder Sass behaves the same as the $colors string in @warn before. $sidebar-width is considered a regular string, so it is typed as it is. But that's not what we want, is it? We do this using interpolation.
.main { width: calc(100% - #{$sidebar-width}); }
Now when Sass compiles this style file, it will replace #{$sidebar-width} with the value of #{$sidebar-width}, 250px. Finally, there are legal CSS expressions.
.main { width: calc(100% - 250px); }
Mission accomplished! We only talked about calc() here, but it is actually the same as other CSS native functions, including pseudo-classes. For example: 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的插值没有看起来那么简单。在一些示例之中,你必须转义你的变量,一些示例中,你却不必。如果是那样,你有两种方式处理:
不管怎样,我希望你明白了插值变量是如何工作的。如果你有什么需要添加的,请在留言中指出。