LESS 语言功能的深入指南。请参阅 概述 以快速了解 Less。
有关安装和设置 Less 环境的深入指南以及 Less 开发文档,请参阅:使用 Less.js。
LESS 语言功能的深入指南。请参阅 概述 以快速了解 Less。
有关安装和设置 Less 环境的深入指南以及 Less 开发文档,请参阅:使用 Less.js。
在单个位置控制常用的值。
在样式表中看到几十次(如果不是几百次)重复相同的值的情况并不少见
a,
.link {
color: #428bca;
}
.widget {
color: #fff;
background: #428bca;
}
通过提供一种从单个位置控制这些值的方法,变量使你的代码更容易维护
// Variables
@link-color: #428bca; // sea blue
@link-color-hover: darken(@link-color, 10%);
// Usage
a,
.link {
color: @link-color;
}
a:hover {
color: @link-color-hover;
}
.widget {
color: #fff;
background: @link-color;
}
上面的示例重点介绍了使用变量来控制CSS 规则中的值,但它们也可以用于其他地方,例如选择器名称、属性名称、URL 和 @import
语句。
v1.4.0
// Variables
@my-selector: banner;
// Usage
.@{my-selector} {
font-weight: bold;
line-height: 40px;
margin: 0 auto;
}
编译为
.banner {
font-weight: bold;
line-height: 40px;
margin: 0 auto;
}
// Variables
@images: "../img";
// Usage
body {
color: #444;
background: url("@{images}/white-sand.png");
}
v1.4.0
语法:@import "@{themes}/tidal-wave.less";
请注意,在 v2.0.0 之前,只考虑在根或当前作用域中声明的变量,并且在查找变量时只考虑当前文件和调用文件。
示例
// Variables
@themes: "../../src/themes";
// Usage
@import "@{themes}/tidal-wave.less";
v1.6.0
@property: color;
.widget {
@{property}: #0ee;
background-@{property}: #999;
}
编译为
.widget {
color: #0ee;
background-color: #999;
}
在 Less 中,可以使用另一个变量来定义变量的名称。
@primary: green;
@secondary: blue;
.section {
@color: primary;
.element {
color: @@color;
}
}
编译为
.section .element {
color: green;
}
使用变量前不必声明变量。
有效的 Less 代码片段
.lazy-eval {
width: @var;
}
@var: @a;
@a: 9%;
这也是有效的 Less
.lazy-eval {
width: @var;
@a: 9%;
}
@var: @a;
@a: 100%;
两者都编译为
.lazy-eval {
width: 9%;
}
定义变量两次时,将使用变量的最后一个定义,从当前作用域向上搜索。这类似于 CSS 本身,其中定义中的最后一个属性用于确定值。
例如
@var: 0;
.class {
@var: 1;
.brass {
@var: 2;
three: @var;
@var: 3;
}
one: @var;
}
编译为
.class {
one: 1;
}
.class .brass {
three: 3;
}
从本质上讲,每个作用域都有一个“最终”值,类似于浏览器中的属性,如下例所示,使用自定义属性
.header {
--color: white;
color: var(--color); // the color is black
--color: black;
}
这意味着,与其他 CSS 预处理语言不同,Less 变量的行为与 CSS 非常相似。
v3.0.0
使用 $prop
语法,您可以轻松地将属性视为变量。有时这可以使您的代码更简洁。
.widget {
color: #efefef;
background-color: $color;
}
编译为
.widget {
color: #efefef;
background-color: #efefef;
}
请注意,与变量类似,Less 将选择当前/父作用域内的最后一个属性作为“最终”值。
.block {
color: red;
.inner {
background-color: $color;
}
color: blue;
}
编译为
.block {
color: red;
color: blue;
}
.block .inner {
background-color: blue;
}
我们有时会收到有关默认变量的请求 - 仅当变量尚未设置时设置变量的能力。此功能不是必需的,因为您可以通过在后面放置定义来轻松覆盖变量。
例如
// library
@base-color: green;
@dark-color: darken(@base-color, 10%);
// use of library
@import "library.less";
@base-color: red;
这很好用,因为 惰性加载 - @base-color
被覆盖,@dark-color
为深红色。
使用
&
引用父选择器
&
运算符表示 嵌套规则 的父选择器,最常见于将修改类或伪类应用于现有选择器
a {
color: blue;
&:hover {
color: green;
}
}
结果为
a {
color: blue;
}
a:hover {
color: green;
}
请注意,如果没有 &
,上面的示例将导致 a :hover
规则(匹配 <a>
标签内悬停元素的后代选择器),而这通常不是我们使用嵌套 :hover
时想要的。
“父选择器”运算符有各种用途。基本上,任何时候您需要嵌套规则的选择器以默认方式以外的其他方式组合时。例如,&
的另一个典型用法是生成重复的类名
.button {
&-ok {
background-image: url("ok.png");
}
&-cancel {
background-image: url("cancel.png");
}
&-custom {
background-image: url("custom.png");
}
}
输出
.button-ok {
background-image: url("ok.png");
}
.button-cancel {
background-image: url("cancel.png");
}
.button-custom {
background-image: url("custom.png");
}
&
&
可以在选择器中出现多次。这使得在不重复其名称的情况下重复引用父选择器成为可能。
.link {
& + & {
color: red;
}
& & {
color: green;
}
&& {
color: blue;
}
&, &ish {
color: cyan;
}
}
将输出
.link + .link {
color: red;
}
.link .link {
color: green;
}
.link.link {
color: blue;
}
.link, .linkish {
color: cyan;
}
请注意,&
表示所有父选择器(不仅仅是最近的祖先),因此以下示例
.grand {
.parent {
& > & {
color: red;
}
& & {
color: green;
}
&& {
color: blue;
}
&, &ish {
color: cyan;
}
}
}
结果为
.grand .parent > .grand .parent {
color: red;
}
.grand .parent .grand .parent {
color: green;
}
.grand .parent.grand .parent {
color: blue;
}
.grand .parent,
.grand .parentish {
color: cyan;
}
将选择器前置到继承的(父)选择器可能很有用。这可以通过将 &
放在当前选择器之后来完成。例如,在使用 Modernizr 时,您可能希望根据支持的功能指定不同的规则
.header {
.menu {
border-radius: 5px;
.no-borderradius & {
background-image: url('images/button-background.png');
}
}
}
选择器 .no-borderradius &
将在其父 .header .menu
之前添加 .no-borderradius
,以在输出中形成 .no-borderradius .header .menu
.header .menu {
border-radius: 5px;
}
.no-borderradius .header .menu {
background-image: url('images/button-background.png');
}
&
还可以用于生成逗号分隔列表中选择器的每种可能排列
p, a, ul, li {
border-top: 2px dotted #366;
& + & {
border-top: 0;
}
}
这将扩展到指定元素的所有可能(16)种组合
p,
a,
ul,
li {
border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
border-top: 0;
}
从其他样式表导入样式
在标准 CSS 中,@import
at 规则必须位于所有其他类型规则之前。但 Less 不关心你将 @import
语句放在哪里。
示例
.foo {
background: #900;
}
@import "this-is-valid.less";
@import
语句可能会根据文件扩展名以不同的方式被 Less 处理
.css
扩展名,它将被视为 CSS,并且 @import
语句保持原样(请参阅下面的 内联选项)。.less
,并且它将作为导入的 Less 文件包含在内。示例
@import "foo"; // foo.less is imported
@import "foo.less"; // foo.less is imported
@import "foo.php"; // foo.php imported as a Less file
@import "foo.css"; // statement left in place, as-is
可以使用以下选项来覆盖此行为。
Less 为 CSS
@import
CSS at 规则提供了几个扩展,以便更灵活地处理外部文件。
语法:@import (关键字) "文件名";
已实现以下导入选项
reference
:使用 Less 文件,但不要输出它inline
:将源文件包含在输出中,但不要处理它less
:将文件视为 Less 文件,无论文件扩展名是什么css
:将文件视为 CSS 文件,无论文件扩展名是什么once
:仅包含文件一次(这是默认行为)multiple
:多次包含文件optional
:在找不到文件时继续编译每个
@import
允许使用多个关键字,你必须使用逗号分隔关键字
示例:@import (optional, reference) "foo.less";
使用 @import (reference)
导入外部文件,但除非引用,否则不要将导入的样式添加到编译输出中。
发布 v1.5.0
示例:@import (reference) "foo.less";
想象一下,reference
标记导入文件中每个 at 规则和选择器带有 reference 标记,按正常方式导入,但在生成 CSS 时,不会输出“reference”选择器(以及仅包含 reference 选择器的任何媒体查询)。除非 reference 样式用作 mixins 或 扩展,否则 reference 样式不会显示在生成的 CSS 中。
此外,reference
根据使用的方法(mixin 或扩展)产生不同的结果
@import
语句的位置被拉入。reference
样式用作 隐式 mixin 时,它的规则被混合,标记为“未引用”,并按正常方式出现在引用位置。这允许您仅从库中提取特定的目标样式,例如 Bootstrap,方法如下
.navbar:extend(.navbar all) {}
您将仅从 Bootstrap 中提取 .navbar
相关的样式。
使用 @import (inline)
包含外部文件,但不处理它们。
发布 v1.5.0
示例:@import (inline) "not-less-compatible.css";
当 CSS 文件可能与 Less 不兼容时,您将使用此方法;这是因为尽管 Less 支持大多数已知的标准 CSS,但它不支持某些位置的注释,并且不支持在不修改 CSS 的情况下支持所有已知的 CSS hack。
因此,您可以使用此方法将文件包含在输出中,以便所有 CSS 都在一个文件中。
使用 @import (less)
将导入的文件视为 Less,而不管文件扩展名是什么。
发布 v1.4.0
示例
@import (less) "foo.css";
使用 @import (css)
将导入的文件视为常规 CSS,而不管文件扩展名是什么。这意味着导入语句将保持原样。
发布 v1.4.0
示例
@import (css) "foo.less";
输出
@import "foo.less";
@import
语句的默认行为。这意味着仅导入文件一次,并且将忽略该文件的后续导入语句。
发布 v1.4.0
这是 @import
语句的默认行为。
示例
@import (once) "foo.less";
@import (once) "foo.less"; // this statement will be ignored
使用 @import (multiple)
允许导入具有相同名称的多个文件。这是与 once 相反的行为。
发布 v1.4.0
示例
// file: foo.less
.a {
color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";
输出
.a {
color: green;
}
.a {
color: green;
}
使用 @import (optional)
仅在文件存在时允许导入文件。如果没有 optional
关键字,当导入找不到的文件时,Less 会抛出 FileError 并停止编译。
发布 v2.3.0
Extend 是一个 Less 伪类,它将它所在的 selector 与匹配它所引用的 selector 合并。
发布 v1.4.0
nav ul {
&:extend(.inline);
background: blue;
}
在上面的规则集中,:extend
选择器将“扩展选择器”(nav ul
)应用到 .inline
类,无论 .inline
类出现在何处。声明块将保持原样,但不会引用扩展(因为扩展不是 css)。
因此,以下内容
nav ul {
&:extend(.inline);
background: blue;
}
.inline {
color: red;
}
输出
nav ul {
background: blue;
}
.inline,
nav ul {
color: red;
}
请注意 nav ul:extend(.inline)
选择器如何输出为 nav ul
- 扩展在输出前被删除,选择器块保持原样。如果该块中没有放置任何属性,则将其从输出中删除(但扩展仍然可能影响其他选择器)。
扩展要么附加到选择器,要么放置到规则集中。它看起来像一个伪类,带有选择器参数,后面可以跟关键字 all
示例
.a:extend(.b) {}
// the above block does the same thing as the below block
.a {
&:extend(.b);
}
.c:extend(.d all) {
// extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
.c:extend(.d) {
// extends only instances where the selector will be output as just ".d"
}
它可以包含一个或多个要扩展的类,用逗号分隔。
示例
.e:extend(.f) {}
.e:extend(.g) {}
// the above and the below do the same thing
.e:extend(.f, .g) {}
附加到选择器的扩展看起来像一个普通伪类,带有选择器作为参数。一个选择器可以包含多个扩展子句,但所有扩展必须位于选择器的末尾。
pre:hover:extend(div pre)
。pre:hover :extend(div pre)
。pre:hover:extend(div pre):extend(.bucket tr)
- 请注意,这与 pre:hover:extend(div pre, .bucket tr)
相同pre:hover:extend(div pre).nth-child(odd)
。扩展必须是最后一个。如果一个规则集包含多个选择器,那么任何一个选择器都可以有扩展关键字。一个规则集中有多个带有扩展的选择器
.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
// body
}
可以使用 &:extend(selector)
语法将扩展放置到规则集的主体中。将扩展放置到主体中是将其放置到该规则集的每个选择器中的快捷方式。
主体内的扩展
pre:hover,
.some-class {
&:extend(div pre);
}
与在每个选择器后添加扩展完全相同
pre:hover:extend(div pre),
.some-class:extend(div pre) {}
扩展能够匹配嵌套选择器。遵循 less
示例
.bucket {
tr { // nested ruleset with target selector
color: blue;
}
}
.some-class:extend(.bucket tr) {} // nested ruleset is recognized
输出
.bucket tr,
.some-class {
color: blue;
}
本质上,扩展查看已编译的 css,而不是原始 less。
示例
.bucket {
tr & { // nested ruleset with target selector
color: blue;
}
}
.some-class:extend(tr .bucket) {} // nested ruleset is recognized
输出
tr .bucket,
.some-class {
color: blue;
}
扩展默认情况下在选择器之间查找精确匹配。选择器是否使用前导星号并不重要。两个 nth 表达式具有相同含义并不重要,它们需要具有相同形式才能匹配。唯一的例外是属性选择器中的引号,less 知道它们具有相同含义并匹配它们。
示例
.a.class,
.class.a,
.class > .a {
color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above
前导星号很重要。选择器 *.class
和 .class
是等效的,但扩展不会匹配它们
*.class {
color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector
输出
*.class {
color: blue;
}
伪类顺序很重要。选择器 link:hover:visited
和 link:visited:hover
匹配同一组元素,但扩展将它们视为不同
link:hover:visited {
color: blue;
}
.selector:extend(link:visited:hover) {}
输出
link:hover:visited {
color: blue;
}
nth 表达式形式很重要。nth 表达式 1n+3
和 n+3
是等效的,但扩展不会匹配它们
:nth-child(1n+3) {
color: blue;
}
.child:extend(:nth-child(n+3)) {}
输出
:nth-child(1n+3) {
color: blue;
}
属性选择器中的引号类型并不重要。以下所有内容都是等效的。
[title=identifier] {
color: blue;
}
[title='identifier'] {
color: blue;
}
[title="identifier"] {
color: blue;
}
.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}
输出
[title=identifier],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
当您在扩展参数中最后指定 all 关键字时,它会告诉 Less 将该选择器作为另一个选择器的一部分进行匹配。选择器将被复制,然后选择器的匹配部分将被扩展替换,从而生成一个新的选择器。
示例
.a.b.test,
.test.c {
color: orange;
}
.test {
&:hover {
color: green;
}
}
.replacement:extend(.test all) {}
输出
.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
color: orange;
}
.test:hover,
.replacement:hover {
color: green;
}
您可以将这种操作模式视为本质上执行非破坏性搜索和替换。
扩展无法匹配带有变量的选择器。如果选择器包含变量,扩展将忽略它。
但是,扩展可以附加到插值选择器。
带有变量的选择器将不会匹配
@variable: .bucket;
@{variable} { // interpolated selector
color: blue;
}
.some-class:extend(.bucket) {} // does nothing, no match is found
并且带有目标选择器中变量的扩展不匹配任何内容
.bucket {
color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket;
以上两个示例编译为
.bucket {
color: blue;
}
但是,附加到插值选择器的 :extend
有效
.bucket {
color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;
编译为
.bucket, .selector {
color: blue;
}
目前,:extend
在 @media
声明中只会匹配同一媒体声明中的选择器
@media print {
.screenClass:extend(.selector) {} // extend inside media
.selector { // this will be matched - it is in the same media
color: black;
}
}
.selector { // ruleset on top of style sheet - extend ignores it
color: red;
}
@media screen {
.selector { // ruleset inside another media - extend ignores it
color: blue;
}
}
编译为
@media print {
.selector,
.screenClass { /* ruleset inside the same media was extended */
color: black;
}
}
.selector { /* ruleset on top of style sheet was ignored */
color: red;
}
@media screen {
.selector { /* ruleset inside another media was ignored */
color: blue;
}
}
注意:扩展不会匹配嵌套 @media
声明中的选择器
@media screen {
.screenClass:extend(.selector) {} // extend inside media
@media (min-width: 1023px) {
.selector { // ruleset inside nested media - extend ignores it
color: blue;
}
}
}
编译为
@media screen and (min-width: 1023px) {
.selector { /* ruleset inside another nested media was ignored */
color: blue;
}
}
顶级扩展匹配所有内容,包括嵌套媒体中的选择器
@media screen {
.selector { /* ruleset inside nested media - top level extend works */
color: blue;
}
@media (min-width: 1023px) {
.selector { /* ruleset inside nested media - top level extend works */
color: blue;
}
}
}
.topLevel:extend(.selector) {} /* top level extend matches everything */
编译为
@media screen {
.selector,
.topLevel { /* ruleset inside media was extended */
color: blue;
}
}
@media screen and (min-width: 1023px) {
.selector,
.topLevel { /* ruleset inside nested media was extended */
color: blue;
}
}
目前没有重复检测。
示例
.alert-info,
.widget {
/* declarations */
}
.alert:extend(.alert-info, .widget) {}
输出
.alert-info,
.widget,
.alert,
.alert {
/* declarations */
}
经典用例是避免添加基类。例如,如果您有
.animal {
background-color: black;
color: white;
}
并且您想要一个覆盖背景色的动物子类型,那么您有两个选择,首先更改您的 HTML
<a class="animal bear">Bear</a>
.animal {
background-color: black;
color: white;
}
.bear {
background-color: brown;
}
或者简化 HTML 并使用 less 中的扩展。例如
<a class="bear">Bear</a>
.animal {
background-color: black;
color: white;
}
.bear {
&:extend(.animal);
background-color: brown;
}
混合会将所有属性复制到一个选择器中,这可能导致不必要的重复。因此,您可以使用扩展而不是混合来将选择器移动到您希望使用的属性,从而减少生成的 CSS。
示例 - 使用混合
.my-inline-block() {
display: inline-block;
font-size: 0;
}
.thing1 {
.my-inline-block;
}
.thing2 {
.my-inline-block;
}
输出
.thing1 {
display: inline-block;
font-size: 0;
}
.thing2 {
display: inline-block;
font-size: 0;
}
示例(使用扩展)
.my-inline-block {
display: inline-block;
font-size: 0;
}
.thing1 {
&:extend(.my-inline-block);
}
.thing2 {
&:extend(.my-inline-block);
}
输出
.my-inline-block,
.thing1,
.thing2 {
display: inline-block;
font-size: 0;
}
另一个用例是作为混合的替代品 - 因为混合只能与简单选择器一起使用,如果您有两个不同的 HTML 块,但需要对两者应用相同的样式,则可以使用扩展来关联两个区域。
示例
li.list > a {
// list styles
}
button.list-style {
&:extend(li.list > a); // use the same list styles
}
合并属性
merge
功能允许将来自多个属性的值聚合到单个属性下的逗号或空格分隔列表中。merge
对于背景和变换等属性很有用。
使用逗号追加属性值
发布 v1.5.0
示例
.mixin() {
box-shadow+: inset 0 0 10px #555;
}
.myclass {
.mixin();
box-shadow+: 0 0 20px black;
}
输出
.myclass {
box-shadow: inset 0 0 10px #555, 0 0 20px black;
}
使用空格追加属性值
发布 v1.7.0
示例
.mixin() {
transform+_: scale(2);
}
.myclass {
.mixin();
transform+_: rotate(15deg);
}
输出
.myclass {
transform: scale(2) rotate(15deg);
}
为了避免任何意外的连接,merge
需要在每个连接挂起声明中使用显式的 +
或 +_
标志。
从现有样式中“混合”属性
您可以混合类选择器和 id 选择器,例如
.a, #b {
color: red;
}
.mixin-class {
.a();
}
.mixin-id {
#b();
}
结果为
.a, #b {
color: red;
}
.mixin-class {
color: red;
}
.mixin-id {
color: red;
}
从历史上看,混合调用中的括号是可选的,但可选括号已被弃用,并且在未来的版本中将是必需的。
.a();
.a; // currently works, but deprecated; don't use
.a (); // white-space before parentheses is also deprecated
如果您想创建一个混合,但不想让该混合出现在您的 CSS 输出中,请在混合定义后加上括号。
.my-mixin {
color: black;
}
.my-other-mixin() {
background: white;
}
.class {
.my-mixin();
.my-other-mixin();
}
输出
.my-mixin {
color: black;
}
.class {
color: black;
background: white;
}
混合不仅可以包含属性,还可以包含选择器。
例如
.my-hover-mixin() {
&:hover {
border: 1px solid red;
}
}
button {
.my-hover-mixin();
}
输出
button:hover {
border: 1px solid red;
}
如果您想在更复杂的选取器中混合属性,则可以堆叠多个 id 或类。
#outer() {
.inner {
color: red;
}
}
.c {
#outer.inner();
}
注意:旧版 Less 语法允许在命名空间和混合之间使用 >
和空格。此语法已弃用,可能会被移除。目前,它们的作用相同。
#outer > .inner(); // deprecated
#outer .inner(); // deprecated
#outer.inner(); // preferred
像这样对您的混合进行命名空间化可以减少与其他库混合或用户混合的冲突,但也可以成为“组织”混合组的一种方式。
示例
#my-library {
.my-mixin() {
color: black;
}
}
// which can be used like this
.class {
#my-library.my-mixin();
}
如果一个命名空间有一个保护,那么它定义的混合只有在保护条件返回 true 时才会使用。命名空间保护的评估与混合保护的评估完全相同,因此以下两个混合的工作方式相同
#namespace when (@mode = huge) {
.mixin() { /* */ }
}
#namespace {
.mixin() when (@mode = huge) { /* */ }
}
default
函数被认为对所有嵌套命名空间和混合具有相同的值。以下混合永远不会被评估;它的一个保护必定为假
#sp_1 when (default()) {
#sp_2 when (default()) {
.mixin() when not(default()) { /* */ }
}
}
!important
关键字在 mixin 调用后使用 !important
关键字,将所有继承的属性标记为 !important
示例
.foo (@bg: #f5f5f5, @color: #900) {
background: @bg;
color: @color;
}
.unimportant {
.foo();
}
.important {
.foo() !important;
}
结果为
.unimportant {
background: #f5f5f5;
color: #900;
}
.important {
background: #f5f5f5 !important;
color: #900 !important;
}
如何向 mixin 传递参数
Mixin 还可以接受参数,这些参数是在 mixin 混合时传递给选择器块的变量。
例如
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
下面是如何将其混合到各种规则集中
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
参数化 Mixin 也可以为其参数设置默认值
.border-radius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
现在我们可以这样调用它
#header {
.border-radius();
}
它将包含一个 5px 的边框半径。
你还可以使用不带参数的参数化 Mixin。如果你想在 CSS 输出中隐藏规则集,但希望在其他规则集中包含其属性,这将非常有用
.wrap() {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
pre { .wrap() }
输出内容为
pre {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
参数目前使用分号或逗号分隔。
最初,参数仅用逗号分隔,但后来添加了分号,以支持将逗号分隔的列表值传递给单个参数。
注意:从 Less 4.0 开始,你可以使用括号转义 [~()
] 包装列表值,例如 .name(@param1: ~(red, blue))
。这类似于引号转义语法:~"quote"
。这可能会使你的代码库中不再需要分号分隔符。
示例
.name(1, 2, 3; something, else)
.name(1, 2, 3)
.name(1, 2, 3;)
。注意:如果尾随分号看起来很奇怪,你可能更喜欢:.name(~(1, 2, 3))
@param-values: red, blue; .name(@param1: @param-values)
..name(@param1: red, blue;)
.name(@param1: ~(red, blue))
使用具有相同名称和参数数量的多个混合是合法的。Less 将使用所有适用的属性。如果你使用具有一个参数的混合,例如 .mixin(green);
,那么将使用具有一个强制参数的所有混合的属性
.mixin(@color) {
color-1: @color;
}
.mixin(@color, @padding: 2) {
color-2: @color;
padding-2: @padding;
}
.mixin(@color, @padding, @margin: 2) {
color-3: @color;
padding-3: @padding;
margin: @margin @margin @margin @margin;
}
.some .selector div {
.mixin(#008000);
}
编译为
.some .selector div {
color-1: #008000;
color-2: #008000;
padding-2: 2;
}
混合引用可以通过其名称而不是仅通过位置提供参数值。任何参数都可以通过其名称引用,并且它们不必按任何特定顺序
.mixin(@color: black; @margin: 10px; @padding: 20px) {
color: @color;
margin: @margin;
padding: @padding;
}
.class1 {
.mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
.mixin(#efca44; @padding: 40px);
}
编译为
.class1 {
color: #33acfe;
margin: 20px;
padding: 20px;
}
.class2 {
color: #efca44;
margin: 10px;
padding: 40px;
}
@arguments
变量@arguments
在混合中具有特殊含义,它包含在调用混合时传递的所有参数。如果你不想处理单个参数,这将很有用
.box-shadow(@x: 0, @y: 0, @blur: 1px, @color: #000) {
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
box-shadow: @arguments;
}
.big-block {
.box-shadow(2px, 5px);
}
导致
.big-block {
-webkit-box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
box-shadow: 2px 5px 1px #000;
}
@rest
变量如果你希望混合采用可变数量的参数,则可以使用 ...
。在变量名后使用此项将把这些参数分配给变量。
.mixin(...) { // matches 0-N arguments
.mixin() { // matches exactly 0 arguments
.mixin(@a: 1) { // matches 0-1 arguments
.mixin(@a: 1, ...) { // matches 0-N arguments
.mixin(@a, ...) { // matches 1-N arguments
此外
.mixin(@a, @rest...) {
// @rest is bound to arguments after @a
// @arguments is bound to all arguments
}
有时,你可能希望根据传递给它的参数来更改混合的行为。让我们从一些基本内容开始
.mixin(@s, @color) { ... }
.class {
.mixin(@switch, #888);
}
现在,假设我们希望 .mixin
根据 @switch
的值表现得不同,我们可以将 .mixin
定义为
.mixin(dark, @color) {
color: darken(@color, 10%);
}
.mixin(light, @color) {
color: lighten(@color, 10%);
}
.mixin(@_, @color) {
display: block;
}
现在,如果我们运行
@switch: light;
.class {
.mixin(@switch, #888);
}
我们将获得以下 CSS
.class {
color: #a2a2a2;
display: block;
}
其中传递给 .mixin
的颜色变亮了。如果 @switch
的值为 dark
,则结果将是较暗的颜色。
以下是发生的情况
dark
作为第一个参数。light
。仅使用匹配的混合定义。变量匹配并绑定到任何值。除变量之外的任何其他内容仅与等于其自身的值匹配。
我们还可以匹配元数,这是一个示例
.mixin(@a) {
color: @a;
}
.mixin(@a, @b) {
color: fade(@a, @b);
}
现在,如果我们使用单个参数调用 .mixin
,我们将获得第一个定义的输出,但如果我们使用两个参数调用它,我们将获得第二个定义,即 @a
渐变为 @b
。
从 mixin 调用中选择属性和变量
在 Less 3.5 中发布 v3.5.0
从 Less 3.5 开始,你可以使用属性/变量访问器从已评估 mixin 的规则中选择一个值。这让你可以使用类似于函数的 mixin。
示例
.average(@x, @y) {
@result: ((@x + @y) / 2);
}
div {
// call a mixin and look up its "@result" value
padding: .average(16px, 50px)[@result];
}
结果为
div {
padding: 33px;
}
如果你有多个匹配的 mixin,所有规则都将被评估并合并,并返回具有该标识符的最后一个匹配值。这类似于 CSS 中的层叠,它允许你“覆盖”mixin 值。
// library.less
#library() {
.mixin() {
prop: foo;
}
}
// customize.less
@import "library";
#library() {
.mixin() {
prop: bar;
}
}
.box {
my-value: #library.mixin[prop];
}
输出
.box {
my-value: bar;
}
如果你没有在 [@lookup]
中指定查找值,而是在 mixin 或规则集调用后写 []
,所有值都将层叠,并且将选择最后声明的值。
这意味着:上面的示例中的平均 mixin 可以写成
.average(@x, @y) {
@result: ((@x + @y) / 2);
}
div {
// call a mixin and look up its final value
padding: .average(16px, 50px)[];
}
输出是相同的
div {
padding: 33px;
}
对于别名为 mixin 调用的规则集或变量,相同的层叠行为也是正确的。
@dr: {
value: foo;
}
.box {
my-value: @dr[];
}
输出
.box {
my-value: foo;
}
已弃用 - 使用属性/值访问器
在 Mixin 中定义的变量和 Mixin 可见,且可以在调用方的作用域中使用。只有一个例外:如果调用方包含具有相同名称的变量(包括由另一个 Mixin 调用定义的变量),则不会复制该变量。仅保护调用方局部作用域中存在的变量。从父作用域继承的变量会被覆盖。
注意:此行为已弃用,将来,变量和 Mixin 将不会以这种方式合并到调用方作用域中。
示例
.mixin() {
@width: 100%;
@height: 200px;
}
.caller {
.mixin();
width: @width;
height: @height;
}
结果为
.caller {
width: 100%;
height: 200px;
}
无法覆盖在调用方作用域中直接定义的变量。但是,在调用方父作用域中定义的变量不受保护,并且会被覆盖
.mixin() {
@size: in-mixin;
@definedOnlyInMixin: in-mixin;
}
.class {
margin: @size @definedOnlyInMixin;
.mixin();
}
@size: globaly-defined-value; // callers parent scope - no protection
结果为
.class {
margin: in-mixin in-mixin;
}
最后,在 Mixin 中定义的 Mixin 也充当返回值
.unlock(@value) { // outer mixin
.doSomething() { // nested mixin
declaration: @value;
}
}
#namespace {
.unlock(5); // unlock doSomething mixin
.doSomething(); //nested mixin was copied here and is usable
}
结果为
#namespace {
declaration: 5;
}
创建循环
在 Less 中,Mixin 可以调用自身。此类递归 Mixin 与 保护表达式和 模式匹配结合使用,可用于创建各种迭代/循环结构。
示例
.loop(@counter) when (@counter > 0) {
.loop((@counter - 1)); // next iteration
width: (10px * @counter); // code for each iteration
}
div {
.loop(5); // launch the loop
}
输出
div {
width: 10px;
width: 20px;
width: 30px;
width: 40px;
width: 50px;
}
使用递归循环生成 CSS 网格类的通用示例
.generate-columns(4);
.generate-columns(@n, @i: 1) when (@i =< @n) {
.column-@{i} {
width: (@i * 100% / @n);
}
.generate-columns(@n, (@i + 1));
}
输出
.column-1 {
width: 25%;
}
.column-2 {
width: 50%;
}
.column-3 {
width: 75%;
}
.column-4 {
width: 100%;
}
当您想匹配表达式(而不是简单值或元数)时,保护非常有用。如果您熟悉函数式编程,您可能已经遇到过它们。
为了尽可能贴近 CSS 的声明式本质,Less 选择通过受保护的 Mixin而不是 if
/else
语句来实现条件执行,这与 @media
查询功能规范类似。
我们从一个示例开始
.mixin(@a) when (lightness(@a) >= 50%) {
background-color: black;
}
.mixin(@a) when (lightness(@a) < 50%) {
background-color: white;
}
.mixin(@a) {
color: @a;
}
关键是 when
关键字,它引入了一个保护序列(此处仅有一个保护)。现在,如果我们运行以下代码
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }
我们将得到以下内容
.class1 {
background-color: black;
color: #ddd;
}
.class2 {
background-color: white;
color: #555;
}
守卫中可用的比较运算符的完整列表:>
、>=
、=
、=<
、<
。此外,关键字 true
是唯一真值,使这两个混入相等
.truth(@a) when (@a) { ... }
.truth(@a) when (@a = true) { ... }
关键字 true
之外的任何值都为假值
.class {
.truth(40); // Will not match any of the above definitions.
}
请注意,您还可以将参数相互比较,或与非参数比较
@media: mobile;
.mixin(@a) when (@media = mobile) { ... }
.mixin(@a) when (@media = desktop) { ... }
.max(@a; @b) when (@a > @b) { width: @a }
.max(@a; @b) when (@a < @b) { width: @b }
您可以对守卫使用逻辑运算符。语法基于 CSS 媒体查询。
使用 and
关键字组合守卫
.mixin(@a) when (isnumber(@a)) and (@a > 0) { ... }
您可以通过用逗号 ,
分隔守卫来模拟 or 运算符。如果任何守卫计算结果为真,则认为匹配
.mixin(@a) when (@a > 10), (@a < -10) { ... }
使用 not
关键字否定条件
.mixin(@b) when not (@b > 0) { ... }
最后,如果您想根据值类型匹配混入,可以使用 is
函数
.mixin(@a; @b: 0) when (isnumber(@b)) { ... }
.mixin(@a; @b: black) when (iscolor(@b)) { ... }
以下是基本类型检查函数
iscolor
isnumber
isstring
iskeyword
isurl
如果您想检查某个值是否除了是数字外还属于特定单位,可以使用以下之一
ispixel
ispercentage
isem
isunit
在 Less 3.5 中发布 v3.5.0
将混入调用分配给变量
混入可以分配给变量,以便作为变量调用,或用于映射查找。
#theme.dark.navbar {
.colors(light) {
primary: purple;
}
.colors(dark) {
primary: black;
secondary: grey;
}
}
.navbar {
@colors: #theme.dark.navbar.colors(dark);
background: @colors[primary];
border: 1px solid @colors[secondary];
}
这将输出
.navbar {
background: black;
border: 1px solid grey;
}
整个混入调用可以作为别名,并作为变量调用。如下所示
#library() {
.colors() {
background: green;
}
}
.box {
@alias: #library.colors();
@alias();
}
输出
.box {
background: green;
}
请注意,与在根中使用的混入不同,分配给变量且未带任何参数调用的混入调用始终需要括号。以下内容无效。
#library() {
.colors() {
background: green;
}
}
.box {
@alias: #library.colors;
@alias(); // ERROR: Could not evaluate variable call @alias
}
这是因为如果变量被分配为选择器列表或混入调用,则会产生歧义。例如,在 Less 3.5+ 中,此变量可以用这种方式使用。
.box {
@alias: #library.colors;
@{alias} {
a: b;
}
}
上述内容将输出
.box #library.colors {
a: b;
}
将规则集分配给变量
发布 v1.7.0
分离规则集是存储在变量中的 css 属性、嵌套规则集、媒体声明或其他任何内容的组。你可以将其包含到规则集或其他结构中,并且其所有属性都将被复制到那里。你还可以将其用作 mixin 参数,并像其他任何变量一样传递它。
简单示例
// declare detached ruleset
@detached-ruleset: { background: red; }; // semi-colon is optional in 3.5.0+
// use detached ruleset
.top {
@detached-ruleset();
}
编译为
.top {
background: red;
}
分离规则集调用后的括号是必需的(除非后面跟着 查找值)。调用 @detached-ruleset;
将不起作用。
当你想定义一个 mixin 来抽象出将一段代码包装在媒体查询或不受支持的浏览器类名中时,它很有用。规则集可以传递给 mixin,以便 mixin 可以包装内容,例如
.desktop-and-old-ie(@rules) {
@media screen and (min-width: 1200px) { @rules(); }
html.lt-ie9 & { @rules(); }
}
header {
background-color: blue;
.desktop-and-old-ie({
background-color: red;
});
}
此处 desktop-and-old-ie
mixin 定义了媒体查询和根类名,以便你可以使用 mixin 来包装一段代码。这将输出
header {
background-color: blue;
}
@media screen and (min-width: 1200px) {
header {
background-color: red;
}
}
html.lt-ie9 header {
background-color: red;
}
现在可以将规则集分配给变量或传递给 mixin,并且可以包含 Less 特性的全套,例如
@my-ruleset: {
.my-selector {
background-color: black;
}
};
你甚至可以利用 媒体查询冒泡,例如
@my-ruleset: {
.my-selector {
@media tv {
background-color: black;
}
}
};
@media (orientation:portrait) {
@my-ruleset();
}
它将输出
@media (orientation: portrait) and tv {
.my-selector {
background-color: black;
}
}
分离规则集调用会以与 mixin 调用相同的方式解锁(返回)其所有 mixin 到调用方。但是,它不会返回变量。
返回的 mixin
// detached ruleset with a mixin
@detached-ruleset: {
.mixin() {
color: blue;
}
};
// call detached ruleset
.caller {
@detached-ruleset();
.mixin();
}
结果为
.caller {
color: blue;
}
私有变量
@detached-ruleset: {
@color:blue; // this variable is private
};
.caller {
color: @color; // syntax error
}
分离规则集可以使用在定义和调用它的位置可访问的所有变量和 mixin。换句话说,它可以使用定义和调用方作用域。如果两个作用域都包含相同的变量或 mixin,则声明作用域值优先。
声明作用域是分离规则集主体被定义的作用域。将分离规则集从一个变量复制到另一个变量不会修改其作用域。规则集不会仅仅通过在那里被引用就获得对新作用域的访问权限。
最后,分离规则集可以通过解锁(导入)到作用域中来获得对作用域的访问权限。
注意:通过调用的 mixin 将变量解锁到作用域中已被弃用。使用 属性/变量访问器。
独立规则集会看到调用者的变量和混合
@detached-ruleset: {
caller-variable: @caller-variable; // variable is undefined here
.caller-mixin(); // mixin is undefined here
};
selector {
// use detached ruleset
@detached-ruleset();
// define variable and mixin needed inside the detached ruleset
@caller-variable: value;
.caller-mixin() {
variable: declaration;
}
}
编译为
selector {
caller-variable: value;
variable: declaration;
}
从定义中可访问的变量和混合会胜过调用者中可用的变量和混合
@variable: global;
@detached-ruleset: {
// will use global variable, because it is accessible
// from detached-ruleset definition
variable: @variable;
};
selector {
@detached-ruleset();
@variable: value; // variable defined in caller - will be ignored
}
编译为
selector {
variable: global;
}
规则集不会仅仅因为在其中被引用而获得对新范围的访问权限
@detached-1: { scope-detached: @one @two; };
.one {
@one: visible;
.two {
@detached-2: @detached-1; // copying/renaming ruleset
@two: visible; // ruleset can not see this variable
}
}
.use-place {
.one > .two();
@detached-2();
}
抛出错误
ERROR 1:32 The variable "@one" was not declared.
独立规则集通过在范围内解锁(导入)而获得访问权限
#space {
.importer-1() {
@detached: { scope-detached: @variable; }; // define detached ruleset
}
}
.importer-2() {
@variable: value; // unlocked detached ruleset CAN see this variable
#space > .importer-1(); // unlock/import detached ruleset
}
.use-place {
.importer-2(); // unlock/import detached ruleset second time
@detached();
}
编译为
.use-place {
scope-detached: value;
}
在 Less 3.5 中发布 v3.5.0
从 Less 3.5 开始,你可以使用属性/变量访问器(也称为“查找”)从变量(独立)规则集中选择一个值。
@config: {
option1: true;
option2: false;
}
.mixin() when (@config[option1] = true) {
selected: value;
}
.box {
.mixin();
}
输出
.box {
selected: value;
}
如果从查找中返回的是另一个独立规则集,你可以使用第二次查找来获取该值。
@config: {
@colors: {
primary: blue;
}
}
.box {
color: @config[@colors][primary];
}
返回的查找值本身可以是变量。就像,你可以写
@config: {
@dark: {
primary: darkblue;
}
@light: {
primary: lightblue;
}
}
.box {
@lookup: dark;
color: @config[@@lookup][primary];
}
这将输出
.box {
color: darkblue;
}
在 Less 3.5 中发布 v3.5.0
使用规则集和混合作为值映射
通过将命名空间与查找 []
语法结合起来,你可以将你的规则集/混合变成映射。
@sizes: {
mobile: 320px;
tablet: 768px;
desktop: 1024px;
}
.navbar {
display: block;
@media (min-width: @sizes[tablet]) {
display: inline-block;
}
}
输出
.navbar {
display: block;
}
@media (min-width: 768px) {
.navbar {
display: inline-block;
}
}
混合作为映射更加通用,这是因为命名空间和重载混合的能力。
#library() {
.colors() {
primary: green;
secondary: blue;
}
}
#library() {
.colors() { primary: grey; }
}
.button {
color: #library.colors[primary];
border-color: #library.colors[secondary];
}
输出
.button {
color: grey;
border-color: blue;
}
你还可以通过别名混合来简化此操作。即
.button {
@colors: #library.colors();
color: @colors[primary];
border-color: @colors[secondary];
}
请注意,如果查找值生成了另一个规则集,您可以追加第二个 []
查找,如下所示
@config: {
@options: {
library-on: true
}
}
& when (@config[@options][library-on] = true) {
.produce-ruleset {
prop: val;
}
}
通过这种方式,规则集和变量调用可以模拟一种类似于混合的“命名空间”。
至于使用混合还是将规则集分配给变量作为映射,这取决于您。您可能希望通过重新声明分配给规则集的变量来替换整个映射。或者您可能希望“合并”各个键/值对,在这种情况下,作为映射的混合可能更合适。
需要注意的一件重要事情是,[@lookup]
中的值是键(变量)名称 @lookup
,而不是作为变量进行求值。如果您希望键名本身是变量,则可以使用 @@variable
语法。
例如
.foods() {
@dessert: ice cream;
}
@key-to-lookup: dessert;
.lunch {
treat: .foods[@@key-to-lookup];
}
这将输出
.lunch {
treat: ice cream;
}
Less 的一些其他范围功能
直观地说,混合可以访问定义范围。
#ns {
@a: one;
.mixin-1() {
prop: @a;
}
}
.rule {
#ns.mixin-1();
}
/* OUTPUTS:
.rule {
prop: one;
}
*/
这是一些可能在未来版本中删除的混合范围功能的列表。
#ns {
.mixin-1() {
prop: @a;
}
}
.rule {
@a: one;
#ns.mixin-1();
}
/* OUTPUTS:
.rule {
prop: one;
}
*/
这是违反直觉的,因为
首选方法:传递您希望对混合可见的变量。
#ns {
.mixin-1(@a) {
prop: @a;
}
}
.rule {
#ns.mixin-1(@a: one);
}
Mixin 将把它们自己的变量推送到调用者作用域,但仅在变量未在本地定义时才这样做。
#ns {
.mixin-1() {
@a: one;
@b: two;
}
}
.rule {
@b: three;
#ns.mixin-1();
prop-1: @a;
prop-2: @b;
}
/* OUTPUTS:
.rule {
prop-1: one;
prop-2: three;
}
*/
这是违反直觉的,因为
此外,通过引入映射,你可以直接检索变量值(和 mixin)。
首选方法:
#ns {
.mixin-1() {
@a: one;
@b: two;
}
}
.rule {
@returns: #ns.mixin-1();
prop-1: @returns[@a];
prop-2: @returns[@b];
}
/* OUTPUTS:
.rule {
prop-1: one;
prop-2: two;
}
*/
与已弃用的变量行为类似,mixin 也被推送到调用者作用域。但是,与变量不同,与合并作用域 mixin 同名的 mixin 会被合并。
#ns {
.mixin-1() {
prop-1: one;
prop-2: two;
}
}
.rule {
#ns();
.mixin-1();
.mixin-1() {
prop-3: three;
}
}
/* OUTPUT:
.rule {
prop-1: one;
prop-2: two;
prop-3: three;
}
*/
首选方法:直接调用 mixin。
#ns {
.mixin-1() {
prop-1: one;
prop-2: two;
}
}
.rule {
.mixin-1() {
prop-3: three;
}
#ns.mixin-1();
.mixin-1();
}
/* OUTPUT:
.rule {
prop-1: one;
prop-2: two;
prop-3: three;
}
*/
以下是一个技巧,用于定义变量并将其保留在某个私有作用域中,防止它们泄漏到全局空间。
& {
// Vars
@height: 100px;
@width: 20px;
// Don't define any prop:value on this scope (as doing so will generate (wrong) output).
.test {
height: @height;
width: @width;
}
}
.rest {
height: @height; // Name error: variable @height is undefined
}
此处,@height
和 @width
仅针对 & { ... }
创建的作用域定义。你还可以将作用域嵌套在规则中
.some-module {
@height: 200px;
@width: 200px;
text-align: left;
line-height: @height; // 200px
& {
// Override original values
@height: 100px;
@width: auto;
.some-module__element {
height: @height; // 100px
width: @width; // 200px
}
.some-module__element .text {
line-height: (@height / 2); // 50px
}
}
& {
// Override original values
@height: 50px;
.some-module__another-element {
height: @height; // 50px
width: @width; // 200px
}
.some-module__another-element .text {
line-height: (@height / 2); // 25px
}
}
}
选择器周围的“if”
发布 v1.5.0
与 Mixin 保护类似,保护也可以应用于 css 选择器,这是一种语法糖,用于声明 mixin 然后立即调用它。
例如,在 1.5.0 之前,你必须这样做
.my-optional-style() when (@my-option = true) {
button {
color: white;
}
}
.my-optional-style();
现在,你可以直接将保护应用于样式。
button when (@my-option = true) {
color: white;
}
你还可以通过将此与 &
特性结合使用来实现 if
类型语句,从而允许你对多个保护进行分组。
& when (@my-option = true) {
button {
color: white;
}
a {
color: blue;
}
}
请注意,你还可以通过使用实际的 if()
函数和变量调用来实现类似的模式。如
@dr: if(@my-option = true, {
button {
color: white;
}
a {
color: blue;
}
});
@dr();
发布 v2.5.0
导入 JavaScript 插件以添加 Less.js 函数和特性
使用 @plugin
at-rule 类似于为 .less
文件使用 @import
。
@plugin "my-plugin"; // automatically appends .js if no extension
由于 Less 插件在 Less 范围内进行评估,因此插件定义可以非常简单。
registerPlugin({
install: function(less, pluginManager, functions) {
functions.add('pi', function() {
return Math.PI;
});
}
})
或者,你可以使用 module.exports
(在浏览器和 Node.js 中均可工作)。
module.exports = {
install: function(less, pluginManager, functions) {
functions.add('pi', function() {
return Math.PI;
});
}
};
请注意,其他 Node.js CommonJS 约定(如 require()
)在浏览器中不可用。在编写跨平台插件时请记住这一点。
你可以使用插件做什么?很多,但让我们从基础开始。我们将首先关注你可能放入 install
函数中的内容。假设你编写了以下内容
// my-plugin.js
install: function(less, pluginManager, functions) {
functions.add('pi', function() {
return Math.PI;
});
}
// etc
恭喜!你已经编写了一个 Less 插件!
如果你在样式表中使用它
@plugin "my-plugin";
.show-me-pi {
value: pi();
}
你会得到
.show-me-pi {
value: 3.141592653589793;
}
但是,如果你想将它乘以其他值或执行其他 Less 操作,则需要返回一个合适的 Less 节点。否则,样式表中的输出将是纯文本(这可能符合你的目的)。
这意味着,这是更正确的
functions.add('pi', function() {
return new tree.Dimension(Math.PI);
});
注意:维度是一个带或不带单位的数字,例如“10px”,它将是 less.Dimension(10, "px")
。有关单位列表,请参阅 Less API。
现在你可以在操作中使用你的函数。
@plugin "my-plugin";
.show-me-pi {
value: pi() * 2;
}
你可能已经注意到,你的插件文件有一些可用的全局变量,即函数注册表(functions
对象)和 less
对象。这些是为了方便而存在的。
通过 @plugin
at-rule 添加的函数遵循 Less 范围规则。这非常适合希望添加功能而不引入命名冲突的 Less 库作者。
例如,假设你从两个第三方库中拥有 2 个插件,这两个插件都具有名为“foo”的函数。
// lib1.js
// ...
functions.add('foo', function() {
return "foo";
});
// ...
// lib2.js
// ...
functions.add('foo', function() {
return "bar";
});
// ...
没关系!你可以选择哪个库的函数创建哪个输出。
.el-1 {
@plugin "lib1";
value: foo();
}
.el-2 {
@plugin "lib2";
value: foo();
}
这将产生
.el-1 {
value: foo;
}
.el-2 {
value: bar;
}
对于分享其插件的插件作者来说,这意味着你还可以通过将它们放在特定范围内来有效地创建私有函数。就像这样,这将导致错误
.el {
@plugin "lib1";
}
@value: foo();
从 Less 3.0 开始,函数可以返回任何类型的节点,并且可以在任何级别调用。
这意味着,在 2.x 中会抛出一个错误,因为函数必须是属性值或变量赋值的一部分
.block {
color: blue;
my-function-rules();
}
在 3.x 中,不再是这样,函数可以返回 At-Rules、Rulesets、任何其他 Less 节点、字符串和数字(后两者将转换为 Anonymous 节点)。
有时,你可能希望调用一个函数,但你不想输出任何内容(例如存储一个值以供以后使用)。在这种情况下,你只需要从函数返回 false
。
var collection = [];
functions.add('store', function(val) {
collection.push(val); // imma store this for later
return false;
});
@plugin "collections";
@var: 32;
store(@var);
稍后你可以做类似的事情
functions.add('retrieve', function(val) {
return new tree.Value(collection);
});
.get-my-values {
@plugin "collections";
values: retrieve();
}
Less.js 插件应导出一个具有以下一个或多个属性的对象。
{
/* Called immediately after the plugin is
* first imported, only once. */
install: function(less, pluginManager, functions) { },
/* Called for each instance of your @plugin. */
use: function(context) { },
/* Called for each instance of your @plugin,
* when rules are being evaluated.
* It's just later in the evaluation lifecycle */
eval: function(context) { },
/* Passes an arbitrary string to your plugin
* e.g. @plugin (args) "file";
* This string is not parsed for you,
* so it can contain (almost) anything */
setOptions: function(argumentString) { },
/* Set a minimum Less compatibility string
* You can also use an array, as in [3, 0] */
minVersion: ['3.0'],
/* Used for lessc only, to explain
* options in a Terminal */
printUsage: function() { },
}
install()
函数的 PluginManager 实例提供用于添加访问器、文件管理器和后置处理器的函数。
以下是一些展示不同插件类型的示例仓库。
虽然 @plugin
调用适用于大多数场景,但在某些情况下,你可能希望在解析开始之前加载插件。
请参阅“使用 Less.js”部分中的 预加载插件,了解如何执行此操作。