你需要知道的Sass插值
你也许会不时地写写 Sass
玩玩,你也会很享受它带给你各种便利。但还有一件事,你并不一定完全了解:插值
(interpolation) - 将一个占位符,替换成一个值。好了,你们都很幸运,因为今天我将把这种问题说清楚。
插值。啥玩意儿?
插值
,通常是指变量插值,或者变量替换。这不是Sass
独有的。实际上,你可以在很多编程语言中,发现这种特性。比如 PHP
, Perl
, Ruby
, Tcl
, Groovy
, Unix shells
, 等等。我们经常说的是,插入一个变量,或者插入一个表达式。
我们还是先来看看一个例子吧。如果你有PHP的基础,接下来应该会很容易了解。比如说,你想打印一个包含变量的字符串,最常见的方式:
$description = "awesome";
echo "Tuts+ is " . $description . "!";
这就不是插值的方式,你这是字符串的连接。这其中,连接了三个字符串:"Tuts+ is "
,awesome
(被 $description
所引用) 以及 "!"
。现在,我们就来看看使用插值而非字符串连接的方式:
$description = "awesome";
echo "Tuts+ is ${description}!";
包裹在变量两边的花括号会告诉PHP,用字符串打印出变量的值。值得注意的是:它需要在双引号里面才可以工作(大多语言都是这样)。
不管怎样,这就是变量/表达式插值。是使用字符串连接,还是使用插值,这都取决于你自己。但可以说一点:插值其实就是字符串连接的语法糖而已。
Sass的插值
我们先看看在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
指令,它将打印相应内容到控制台。
字符串 (Strings)
假设你有一组叫$colors
名的颜色映射(映射是指一个存储了一系列 key/value 组合的变量),但你已经受够了一次又一次地敲 map-get($colors, ...)
。所以,你写了一个简单的color()
函数,使用key去获得相应的值。
把这些组合一下就是:
// _config.scss
$colors: (
"primary": tomato,
"secondary": hotpink
);
// _function.scss
@function color($key) {
@return map-get($colors, $key);
}
// _component.scss
.el {
background-color: color(primary);
}
一切都很好,不是吗?现在,当你敲错名称,或者去取一个不存在的key时,你想给出错误的信息。这将通过 @warn
指令来完成。color()
函数如下:
@function color($key) {
@if not map-has-key($colors, $key) {
@warn "Key not found.";
}
@return map-get($colors, $key);
}
还不错。如果你想知道哪个key没有找到呢?
@function color($key) {
@if not map-has-key($colors, $key) {
@warn "Key `#{$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 in $colors map.";
}
@return map-get($colors, $key);
}
在这个场景里,由于这个 $colors
变量没有使用插值,它将打印以下信息:
Key
awesomeness
not found in $colors map.
CSS函数 (Functions)
到目前为止,我们已经见到了最常见的变量替换场景:打印字符串中变量的内容。这确实是一个好的示例,但我觉得应该还有更好的场景:CSS函数中的变量,比如 calc()
。
假设你想基于侧边栏的宽度设置主容器的大小。你是一个勤奋的前端开发者,已经把这个宽度存储在一个变量中,所以,你可能会这样做:
$sidebar-width: 250px;
.main {
width: calc(100% - $sidebar-width);
}
然后,你会惊讶地发现,根本不work。没有报错,容器的大小却又不正确。如果你去审查你的dom元素,你会看到这个 — 被划掉了。因为,这是不合法的。
.main {
width: calc(100% - $sidebar-width);
}
现在我们应该想到:calc()
是一个CSS函数,不是一个Sass函数。这就是说Sass会将整个表达式解释成一个字符串。你可以试试:
$type-of-expression: type-of(calc(100% - $sidebar-width)); // string
因为这是一个字符串,难怪Sass表现和之前@warn
中的$colors
字符串一样。$sidebar-width
被认为是一个常规字符串,所以打出来就是它自己。但这都不是我们所想要的,是吧?我们用插值这样做。
.main {
width: calc(100% - #{$sidebar-width});
}
现在当Sass编译这个样式文件时,它会用#{$sidebar-width}
的值,250px替换#{$sidebar-width}
。最后,便是合法的CSS表达式。
.main {
width: calc(100% - 250px);
}
任务完成!我们仅仅在这里谈了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指令 (Directives)
我们将视转移到另一个有趣的变量插值场景: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 ": 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结果。所以,我们便没有必要再对变量转义了。
选择器 (Selectors)
好的,这将是最后一个示例:使用变量作为一个选择器,或者选择器的一部分。这不是一种常用的用法,以下的做法不太符合常识:
$value: custom;
selector-$value {
property: value;
}
不幸的是,这根本无法编译成功:
Invalid CSS after "selector-": expected "{", was "$value {"
这是media query
那个例子的原因,差不多。Sass有着自己的方式解析一个CSS选择器。如果它遇到了不可预知的东西,比如一个未经处理的美元符号,它就会直接崩溃。
幸运的,解决这个问题也相当简单(你也已经知道怎么做了):没错,使用插值变量!
$value: custom;
selector-#{$value} {
property: value;
}
结语
在最后,Sass的插值没有看起来那么简单。在一些示例之中,你必须转义你的变量,一些示例中,你却不必。如果是那样,你有两种方式处理:
- 要么你便等着错误信息,然后转义
- 要么你转义除了常规CSS值(你清楚地知道,它会工作得很好)外的所有地方
不管怎样,我希望你明白了插值变量是如何工作的。如果你有什么需要添加的,请在留言中指出。
原文:All You Ever Need to Know About Sass Interpolation
你需要知道的Sass插值的更多相关文章
- 程序员必须要知道的Hadoop的一些事实
程序员必须要知道的Hadoop的一些事实.现如今,Apache Hadoop已经无人不知无人不晓.当年雅虎搜索工程师Doug Cutting开发出这个用以创建分布式计算机环境的开源软...... 1: ...
- 【转载】在IT界取得成功应该知道的10件事
在IT界取得成功应该知道的10件事 2011-08-11 13:31:30 分类: 项目管理 导读:前面大多数文章都是Jack Wallen写的,这是他的新作,看来要成为NB程序员还要不停的自我总结 ...
- 理工科应该的知道的C/C++数学计算库(转)
理工科应该的知道的C/C++数学计算库(转) 作为理工科学生,想必有限元分析.数值计算.三维建模.信号处理.性能分析.仿真分析...这些或多或少与我们常用的软件息息相关,假如有一天你只需要这些大型软件 ...
- 你应该知道的10个奇特的 HTML5 单页网站
网页设计师努力寻找新的方式来展现内容.其中一个大的趋势是单页网站,现在被世界上的一些大的品牌广泛采用,使用它们来为用户提供一个快速,干净和简单的而且美丽的网站. 下面是10个令人惊叹的单页 H ...
- Git / 程序员需要知道的12个Git高级命令
众所周知,Git目前已经是分布式版本控制领域的翘楚,围绕着Git形成了完整的生态圈.学习Git,首先当然是学习Git的基本工作流.相比于SVN等传统版本控制系统来说,Git是专为分布式版本控制而生的强 ...
- 你应该知道的RPC原理
你应该知道的RPC原理 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 而一旦踏入公司尤其是大型互 ...
- 希望早几年知道的5个Unix命令
原文: http://spin.atomicobject.com/2013/09/09/5-unix-commands/ 希望早几年知道的5个Unix命令 使用*nix系统已经有一段时间了.但是还是有 ...
- 关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造)
关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造) 摘要:在中文搜索中的标点.符号往往也是有语义的,比如我们要搜索“C++”或是“C#”,我们不希望搜索出来的全是“C”吧?那样对程 ...
- 对于JavaScript的函数.NET开发人员应该知道的11件事
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 昨天小感冒今天重感冒,也不能长篇大论.如果你是.NET开发人员,在进入前端开发领域的时候,对 ...
随机推荐
- javaweb回顾第三篇数据库访问
前言:本篇主要针对数据库的操作,在这里不适用hibernate或者mybatis,用最原始的JDBC进行讲解,通过了解这些原理以后更容易理解和学习hibernate或mybatis. 1:jdbc的简 ...
- ios之VFL的补充(三)
@"|-50-[buttonA(80@100)]-[buttonB(90@200)]-50-|" 这条语句的含义是:“左右边距都为50,中间有两个按钮,相隔缺省宽度,一个控件宽度为 ...
- 通过修改host文件来允许和禁止主机的访问
通过修改host文件来允许和禁止主机的访问 修改/etc/hosts.deny,加入"sshd:ALL" 修改/etc/hosts.allow,加入"sshd:192.1 ...
- Visual Studio 2013 and .NET 4.6
I'm trying to set the 4.6 .NET framework for my project and in the settings, as it wasn't listed, I ...
- csdn 泄露用户密码害人不浅啊。
先是京东被盗,接着博客园也登陆不了了.
- 深入学习golang(5)—接口
接口 概述 如果说goroutine和channel是Go并发的两大基石,那么接口是Go语言编程中数据类型的关键.在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构 ...
- (转)create table #temptable 临时表 和 declare @bianliang table ()表变量
在开发过程中,经常会遇到使用表变量和本地临时表的情况.下面是对二者的一个介绍: 1. 为什么要使用表变量 表变量是从2000开始引入的,微软认为与本地临时表相比,表变量具有如下优点: a.与其他变量 ...
- LeetCode:Minimum Path Sum(网格最大路径和)
题目链接 Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right ...
- 删除windows系统中以前的设备(比如以前的网卡)或驱动的方法
1.在“开始”菜单单击“运行”,然后在“运行”对话框中输入“CMD”命令打开命令提示符窗口:2.在提示符窗口中输入“Set devmgr_show_nonpresent_devices=1”并回车:3 ...
- 【字符串排序】n个数连接得到最小或最大的多位整数
题目 描述:设有n个正整数,将它们依次连成在一排,组成一个多位数,现在要求可能组成的多位数中最大的多位数是什么? 例如:n=3时,3个整数13,312,343连成的最大多位数为:343-312-13. ...