less 浅谈

目录

前言

一、概述

二、变量

1、概述

2、变量插值

(1)、选择器

(2)、URLs

(3)、导入语句

(4)、属性

3、可变变量

4、惰性评估

5、属性作为变量(新!)

三、父选择器

1、多重 &

2、更改选择器顺序

3、组合爆炸

四、继承

1、扩展语法

2、延伸到选择器

3、扩展内部规则集

4、扩展嵌套选择器

5、与Extend的精确匹配

6、nth 表达式

7、扩展“全部”

8、带扩展的选择器插值

9、在 @media 内部进行范围界定/扩展

10、重复检测

11、扩展的用例

(1)、经典用例

(2)、减少CSS大小

(3)、组合样式/更高级的混音

五、合并

1、逗号

2、空间

六、混合

1、不输出Mixin

2、混合器中的选择器

3、名称空间

4、保护名称空间

5、“!important” 关键字

6、参数混合

(1)、多参数混合

(2)、命名参数

(3)、@arguments变量

(4)、高级参数和@rest变量

7、模式匹配

8、使用mixin作为函数

(1)、属性/值访问器

(2)、重写mixin值

(3)、未命名查找

(4)、将mixin和变量解锁到调用者范围

9、递归混合

10、混合守卫

(1)、保护比较运算符

(2)、保护逻辑运算符

(3)、类型检查功能

11、混叠

(1)、变量调用

七、CSS 警卫

八、分离规则集

1、范围界定

(1)、定义和调用方范围可见性

(2)、引用不会修改分离的规则集范围

(3)、解锁将修改分离的规则集范围

2、属性/变量访问器

(1)、(查找值)

(2)、查找中的变量

九、@按规则导入

1、文件扩展名

2、导入选项

(1)、参考

3、内联

4、less

5、css

6、once

7、multiple

8、optional

十、@插件规则

1、编写第一个插件

2、插件作用域

3、空函数

4、less.js 插件对象

5、预加载插件

十一、Maps(新!)

1、在查找中使用变量


前言

Less 快速入门 | Less.js 中文文档 - Less 中文网Less 扩充了 CSS 语言,增加了诸如变量、混合(mixin)、运算、函数等功能。 Less 既可以运行在服务器端(Node.js 和 Rhino 平台)也可以运行在客户端(浏览器)。https://less.bootcss.com/#%E6%A6%82%E8%A7%88

安装 Less:

npm install less less-loader -D

一、概述

关于LESS语言特征的深入指南。有关Less的快速摘要,请参见概述。

有关安装和设置Less环境的详细指南以及为Less开发的文档,请参阅:使用Less。js。

二、变量

在单个位置控制常用值。

1、概述

看到相同的值在样式表中重复几十次(如果不是几百次的话)并不罕见:

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

2、变量插值

上面的例子重点是使用变量来控制CSS规则中的值,但它们也可以用于其他地方,例如选择器名称、属性名称、URL和@import语句。

(1)、选择器

// 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;
}

(2)、URLs

// Variables
@images: "../img";

// Usage
body {
  color: #444;
  background: url("@{images}/white-sand.png");
}

(3)、导入语句

语法:@import“@{themes}/tidewave.less”;

请注意,在v2之前。0.0时,仅考虑在根或当前作用域中声明的变量,并且在查找变量时仅考虑当前文件和调用文件。

例子:

// Variables
@themes: "../../src/themes";

// Usage
@import "@{themes}/tidal-wave.less";

(4)、属性

@property: color;

.widget {
  @{property}: #0ee;
  background-@{property}: #999;
}

编译为:

.widget {
  color: #0ee;
  background-color: #999;
}

3、可变变量

在Less中,您可以使用另一个变量定义变量的名称。

@primary:  green;
@secondary: blue;

.section {
  @color: primary;

  .element {
    color: @@color;
  }
}

其汇编目的是:

.section .element {
  color: green;
}

4、惰性评估

变量在使用前不必声明。

有效代码段:

.lazy-eval {
  width: @var;
}

@var: @a;
@a: 9%;

这也是有效的:

.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预处理语言不同,更少的变量的行为与CSS非常相似。

5、属性作为变量(新!)

您可以使用$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; 
}

三、函数

Less 函数

三、父选择器

使用引用父选择器:&

& 运算符表示嵌套规则的父选择器,在将修改类或伪类应用于现有选择器时最常用:

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

1、多重 &

& 在选择器中可能出现多次。这使得重复引用父选择器而不重复其名称成为可能。

.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;
}

2、更改选择器顺序

在继承的(父)选择器前面加上选择器可能很有用。这可以通过将 & 置于当前选择器之后来完成。例如,使用Modernizer时,您可能希望根据支持的功能指定不同的规则:

.header {
  .menu {
    border-radius: 5px;
    .no-borderradius & {
      background-image: url('images/button-background.png');
    }
  }
}

选择器。无边界半径 & 将预加边界。没有边界半径到其父级。标题。菜单,以形成。没有边界半径。标题。输出菜单:

.header .menu {
  border-radius: 5px;
}
.no-borderradius .header .menu {
  background-image: url('images/button-background.png');
}

3、组合爆炸

& 也可用于在逗号分隔的列表中生成选择器的所有可能排列:

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

四、继承

Extend是一个伪类,它将它所使用的选择器与它所引用的选择器相合并。

发布v1.4.0

nav ul {
  &:extend(.inline);
  background: blue;
}

在上面的规则集中,:extend选择器将“extensing selector”(nav ul)应用于。内联类(无论在何处)。将显示内联类。声明块将保持原样,但不引用扩展(因为扩展不是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的形式输出-在输出之前删除extend,选择器块保持原样。如果没有在该块中放入任何属性,则该块将从输出中删除(但扩展仍可能影响其他选择器)。

1、扩展语法

扩展可以附加到选择器,也可以放置到规则集中。它看起来像一个伪类,选择器参数后跟关键字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) {}

2、延伸到选择器

附加到选择器的Extend看起来像一个普通的伪类,带有选择器作为参数。选择器可以包含多个extend子句,但所有extend必须位于选择器的末尾。

  • 在选择器: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)。第n个孩子(奇数)。扩展必须是最后一个。

如果规则集包含多个选择器,则其中任何一个都可以具有extend关键字。在一个规则集中具有扩展的多个选择器:

.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
  // body
}

3、扩展内部规则集

可以使用&:Extend(选择器)语法将Extend放入规则集的主体中。将extend放入正文是将其放入该规则集的每个选择器的快捷方式。

在身体内部延伸:

pre:hover,
.some-class {
  &:extend(div pre);
}

与在每个选择器后添加扩展完全相同:

pre:hover:extend(div pre),
.some-class:extend(div pre) {}

4、扩展嵌套选择器

Extend能够匹配嵌套选择器。以下是:

例子:

.bucket {
  tr { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(.bucket tr) {} // nested ruleset is recognized

输出:

.bucket tr,
.some-class {
  color: blue;
}

本质上,extend关注的是编译后的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;
}

5、与Extend的精确匹配

默认情况下,“扩展”查找选择器之间的精确匹配。选择器是否使用主星并不重要。两个第n个表达式具有相同的含义并不重要,它们需要具有相同的形式才能匹配。唯一的例外是属性选择器中的引号,less知道它们具有相同的含义并匹配它们。

例子:

.a.class,
.class.a,
.class > .a {
  color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above

主角确实很重要。选择器*。上课和上课。类是等效的,但extend将不匹配它们:

*.class {
  color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector

输出:

*.class {
  color: blue;
}

伪类的顺序确实很重要。选择器link:hover:visted和link:visted:hover匹配同一组元素,但extend将它们视为不同的元素:

link:hover:visited {
  color: blue;
}
.selector:extend(link:visited:hover) {}

输出:

link:hover:visited {
  color: blue;
}

6、nth 表达式

第n种表达形式很重要。n表达式1n+3和n+3是等效的,但extend与它们不匹配:

: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;
}

7、扩展“全部”

当您在扩展参数中指定all关键字last时,它告诉Less将该选择器作为另一个选择器的一部分进行匹配。将复制选择器,然后仅将选择器的匹配部分替换为extend,从而生成一个新的选择器。

例子:

.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;
}

您可以认为这种操作模式本质上是进行非破坏性搜索和替换。

8、带扩展的选择器插值

Extend无法将选择器与变量匹配。若选择器包含变量,extend将忽略它。

但是,“延伸”可以附加到插值选择器。

带有变量的选择器将不匹配:

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

9、在 @media 内部进行范围界定/扩展

当前,@media声明中的:extend将仅匹配同一媒体声明中的选择器:

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

10、重复检测

目前没有重复检测。

例子:

.alert-info,
.widget {
  /* declarations */
}

.alert:extend(.alert-info, .widget) {}

输出:

.alert-info,
.widget,
.alert,
.alert {
  /* declarations */
}

11、扩展的用例

(1)、经典用例

经典用例是避免添加基类。例如,如果你有

.animal {
  background-color: black;
  color: white;
}

你想要一个动物的子类型来覆盖背景色,然后你有两个选择,首先改变你的HTML

<a class="animal bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  background-color: brown;
}

或者简化html,并在您的应用程序中使用extend。例如

<a class="bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}

(2)、减少CSS大小

mixin将所有属性复制到选择器中,这可能导致不必要的重复。因此,您可以使用extends而不是mixin将选择器向上移动到您希望使用的属性,这会减少生成的CSS。

示例-使用mixin:

.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;
}

(3)、组合样式/更高级的混音

另一个用例是作为mixin的替代方案,因为mixin只能与简单的选择器一起使用,如果您有两个不同的html块,但需要对这两个块应用相同的样式,则可以使用extends来关联两个区域。

例子:

li.list > a {
  // list styles
}
button.list-style {
  &:extend(li.list > a); // use the same list styles
}

五、合并

组合属性

合并功能允许将多个属性中的值聚合到单个属性下以逗号或空格分隔的列表中。合并对于背景和变换等属性很有用。

1、逗号

用逗号附加属性值

发布v1。5

例子:

.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;
}

2、空间

用空格追加属性值

发布v1。7

例子:

.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;
}

目前和过去,mixin调用中的括号都是可选的,但可选括号已被弃用,并且在将来的版本中需要。

.a(); 
.a;  // currently works, but deprecated; don't use

1、不输出Mixin

如果您想创建一个mixin,但不希望该mixin出现在CSS输出中,请在mixin定义后加上括号。

.my-mixin {
  color: black;
}
.my-other-mixin() {
  background: white;
}
.class {
  .my-mixin();
  .my-other-mixin();
}

输出:

.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}

2、混合器中的选择器

mixin不仅可以包含属性,还可以包含选择器。

例如:

.my-hover-mixin() {
  &:hover {
    border: 1px solid red;
  }
}
button {
  .my-hover-mixin();
}

输出:

button:hover {
  border: 1px solid red;
}

3、名称空间

如果要在更复杂的选择器中混合属性,可以堆叠多个id或类。

#outer() {
  .inner {
    color: red;
  }
}

.c {
  #outer > .inner();
}

“>” 和 空格 都是可选的。

// all do the same thing
#outer > .inner();
#outer .inner();
#outer.inner();

将mixin命名为like可以减少与其他库mixin或用户mixin的冲突,但也可以是“组织”mixin组的一种方式。

例子:

#my-library {
  .my-mixin() {
    color: black;
  }
}
// which can be used like this
.class {
  #my-library.my-mixin();
}

4、保护名称空间

如果名称空间具有保护,则仅当保护条件返回true时才使用由其定义的混合。命名空间保护的计算方式与mixin上的保护完全相同,因此以下两个mixin的工作方式相同:

#namespace when (@mode = huge) {
  .mixin() { /* */ }
}

#namespace {
  .mixin() when (@mode = huge) { /* */ }
}

默认函数假定对所有嵌套命名空间和mixin具有相同的值。以下mixin从未经过评估,其一个防护装置保证是假的:

#sp_1 when (default()) {
  #sp_2 when (default()) {
    .mixin() when not(default()) { /* */ }
  }
}

5、“!important” 关键字

!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;
}

6、参数混合

如何将参数传递给mixin

mixin还可以接受参数,这些参数是混合在选择器块中时传递给选择器块的变量。

例如:

.border-radius(@radius) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

下面是我们如何将其混合到各种规则集中:

#header {
  .border-radius(4px);
}
.button {
  .border-radius(6px);
}

参数混合也可以具有其参数的默认值:

.border-radius(@radius: 5px) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

我们现在可以这样调用它:

#header {
  .border-radius();
}

它将包括5px的边界半径。

您还可以使用不接受参数的参数混合。如果希望从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;
}

(1)、多参数混合

参数可以是分号或逗号分隔的。建议使用分号。符号逗号具有双重含义:它可以解释为mixin参数分隔符或css列表分隔符。

使用逗号作为mixin分隔符使得无法创建逗号分隔的列表作为参数。另一方面,如果编译器在mixin调用或声明中看到至少一个分号,则它假定参数由分号分隔,并且所有逗号都属于css列表:

  • 两个参数,每个参数包含逗号分隔的列表:。名称(1,2,3;某物,其他),
  • 三个参数,每个参数包含一个数字:。姓名(1,2,3),
  • 使用伪分号创建mixin调用,其中一个参数包含逗号分隔的css列表:。姓名(1,2,3;),
  • 逗号分隔的默认值:。名称(@param1:red,blue;)。

使用相同的名称和参数数量定义多个mixin是合法的。Less将使用所有可以应用的属性。如果将mixin与一个参数一起使用,例如。混合(绿色);,然后将使用具有一个强制参数的所有mixin的属性:

.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;
}

(2)、命名参数

mixin引用可以通过名称而不是位置来提供参数值。任何参数都可以通过其名称引用,并且它们不必按任何特殊顺序:

.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;
}

(3)、@arguments变量

@参数在mixin中具有特殊意义,它包含调用mixin时传递的所有参数。如果您不想处理单个参数,这将非常有用:

.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;
}

(4)、高级参数和@rest变量

你可以用 ... 如果希望mixin接受可变数量的参数。在变量名后使用此选项将把这些参数分配给变量。

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

7、模式匹配

有时,您可能希望根据传递给它的参数更改mixin的行为。让我们从一些基本的东西开始:

.mixin(@s; @color) { ... }

.class {
  .mixin(@switch; #888);
}

现在让我们假设我们想要。mixin的行为不同,基于@switch的值,我们可以定义。混音本身:

.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;
}

颜色传递到的地方。米辛被点亮了。如果@switch的值为深色,则结果将为深色。

发生的事情如下:

  • 第一个mixin定义不匹配,因为它预期第一个参数为dark。
  • 第二个mixin定义匹配,因为它需要灯光。
  • 第三个mixin定义匹配,因为它需要任何值。

仅使用匹配的mixin定义。变量匹配并绑定到任何值。变量以外的任何内容都只与等于自身的值匹配。

我们也可以在算术上进行匹配,下面是一个示例:

.mixin(@a) {
  color: @a;
}
.mixin(@a; @b) {
  color: fade(@a; @b);
}

现在如果我们打电话。通过一个参数mixin,我们将得到第一个定义的输出,但是如果我们用两个参数调用它,我们将得到第二个定义,即@a褪色为@b。

8、使用mixin作为函数

从mixin调用中选择属性和变量

(1)、属性/值访问器

发布v3。5

从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;
}

(2)、重写mixin值

如果有多个匹配的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;
}

(3)、未命名查找

如果未在[@lookup]中指定查找值,而是在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;
}

(4)、将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;
}

9、递归混合

创建循环

在更少的情况下,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%;
}

10、混合守卫

与简单的值或算术相反,当您想要匹配表达式时,保护非常有用。如果您熟悉函数式编程,您可能已经遇到过它们。

为了尽可能接近CSS的声明性本质,Less选择了通过受保护的mixin而不是if/else语句来实现条件执行,这与@media query特性规范类似。

让我们从一个例子开始:

.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;
}

(1)、保护比较运算符

在guards中可用的比较运算符的完整列表为:>、>=、=、=、=<、<。此外,关键字true是唯一的truthy值,使这两个混音等效:

.truth(@a) when (@a) { ... }
.truth(@a) when (@a = true) { ... }

除关键字true以外的任何值都是falsy:

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

(2)、保护逻辑运算符

您可以将逻辑运算符与防护一起使用。该语法基于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) { ... }

(3)、类型检查功能

最后,如果要根据值类型匹配mixin,可以使用is函数:

.mixin(@a; @b: 0) when (isnumber(@b)) { ... }
.mixin(@a; @b: black) when (iscolor(@b)) { ... }

以下是基本类型检查功能:

  • iscolor
  • isnumber
  • isstring
  • iskeyword
  • isurl

如果要检查某个值是否为数字以外的特定单位,可以使用以下选项之一:

  • ispixel
  • ispercentage
  • isem
  • isunit

11、混叠

发布v3。5

将mixin调用分配给变量

可以将mixin分配给要作为变量调用调用的变量,也可以用于映射查找。

#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;
}

(1)、变量调用

整个mixin调用可以使用别名并作为变量调用调用。例如:

#library() {
  .rules() {
    background: green;
  }
}
.box {
  @alias: #library.rules();
  @alias();
}

输出:

.box {
  background: green;
}

注意,与root中使用的mixin不同,分配给变量的mixin调用和不带参数的mixin调用总是需要括号。以下内容无效。

#library() {
  .rules() {
    background: green;
  }
}
.box {
  @alias: #library.colors;
  @alias();   // ERROR: Could not evaluate variable call @alias
}

这是因为若变量被分配了选择器列表或mixin调用,那个么它是不明确的。例如,在小于3.5+的情况下,此变量可以这样使用。

.box {
  @alias: #library.colors;
  @{alias} {
    a: b;
  }
}

上述结果将是:

.box #library.colors {
  a: b;
}

七、CSS 警卫

“如果”在选择器周围

发布v1。5

与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;
}

您还可以通过将其与&feature相结合来实现if-type语句,从而允许您对多个保护进行分组。

& when (@my-option = true) {
  button {
    color: white;
  }
  a {
    color: blue;
  }
}

注意,通过使用实际的if()函数和变量调用,也可以实现类似的模式。例如:

@dr: if(@my-option = true, {
  button {
    color: white;
  }
  a {
    color: blue;
  }
});
@dr();

八、分离规则集

将规则集分配给变量

发布v1。7

分离规则集是一组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规则集;这是行不通的。

当您想要定义一个mixin,该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;
  });
}

在这里,桌面和旧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,并且可以包含一整套较少的特性,例如。

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

1、范围界定

分离的规则集可以在定义和调用它的地方使用所有可访问的变量和混合。否则,定义和调用方作用域对它都是可用的。如果两个作用域包含相同的变量或mixin,则声明作用域值优先。

声明范围是定义分离规则集主体的范围。将分离的规则集从一个变量复制到另一个变量中无法修改其范围。规则集不会仅通过在那里引用而获得对新范围的访问。

最后,分离的规则集可以通过解锁(导入)到范围中来获得对范围的访问。

注意:不推荐通过一个名为mixin的函数将变量解锁到作用域中。使用属性/变量访问器。

(1)、定义和调用方范围可见性

分离的规则集可以看到调用方的变量和混合:

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

可从定义中访问的变量和mixin胜过调用者中可用的变量和mixin:

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

(2)、引用不会修改分离的规则集范围

规则集不能仅通过在其中引用来访问新范围:

@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.

(3)、解锁将修改分离的规则集范围

分离的规则集通过在作用域内解锁(导入)获得访问权限:

#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;
}

2、属性/变量访问器

(1)、(查找值)

发布v3。5

从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];
}

(2)、查找中的变量

返回的查找值本身可以是变量。如中所示,您可以编写:

@config: {
  @dark: {
    primary: darkblue;
  }
  @light: {
    primary: lightblue;
  }
}

.box {
  @lookup: dark;
  color: @config[@@lookup][primary];
}

这将输出:

.box {
  color: darkblue;
}

九、@按规则导入

从其他样式表导入样式

在标准CSS中,@import at规则必须优先于所有其他类型的规则。但是Less不在乎把@import语句放在哪里。

例子:

.foo {
  background: #900;
}
@import "this-is-valid.less";

1、文件扩展名

@根据文件扩展名的不同,导入语句的处理方式可能会有所不同:

如果文件有一个。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

以下选项可用于覆盖此行为。

2、导入选项

Less为CSS@import CSS at规则提供了多个扩展,使您能够更灵活地处理外部文件。

语法:@import(关键字)“filename

已实施以下导入选项:

  • reference:使用较少的文件,但不要输出它
  • inline:在输出中包含源文件,但不处理它
  • less:将文件视为less文件,无论文件扩展名是什么
  • css:无论文件扩展名是什么,都将该文件视为css文件
  • once:仅包含文件一次(这是默认行为)
  • multiple:多次包含该文件
  • optional:未找到文件时继续编译

每个@import允许有多个关键字,您必须使用逗号分隔关键字:

示例:@import(可选,参考)“foo.less”;

(1)、参考

使用@import(reference)导入外部文件,但除非引用,否则不要将导入的样式添加到编译输出中。

发布v1。5

例如:@import(reference)“foo.less”;

想象一下,引用在导入的文件中用引用标志标记每个at规则和选择器,并按正常方式导入,但在生成CSS时,“引用”选择器(以及任何仅包含引用选择器的媒体查询)不会输出。除非引用样式用作混合样式或扩展样式,否则引用样式不会显示在生成的CSS中。

此外,参考会根据使用的方法(混合或扩展)产生不同的结果:

  • extend:当选择器被扩展时,只有新的选择器被标记为未被引用,并且它被拉入reference@import语句的位置。
  • mixin:当引用样式用作隐式mixin时,它的规则将被混合,标记为“notreference”,并以正常方式显示在引用位置。

参考示例

这允许您通过执行以下操作,仅从库(如引导)中引入特定的目标样式:

.navbar:extend(.navbar all) {}

你只会停下来。引导中与导航栏相关的样式。

3、内联

使用@import(inline)包含外部文件,但不处理它们。

发布v1。5

示例:@import(inline)“不低于兼容的.css”;

当CSS文件可能不太兼容时,您将使用此选项;这是因为尽管Less支持大多数已知的标准CSS,但它在某些地方不支持注释,并且不支持所有已知的CSS攻击,而不修改CSS。

因此,您可以使用它将文件包含在输出中,以便所有CSS都位于一个文件中。

4、less

使用@import(less)将导入的文件视为less,而不考虑文件扩展名。

发布v1。4

例子:

@import (less) "foo.css";

5、css

使用@import(css)将导入的文件视为常规css,而不考虑文件扩展名。这意味着import语句将保持原样。

发布v1。4

例子:

@import (css) "foo.less";

输出:

@import "foo.less";

6、once

@import语句的默认行为。这意味着该文件只导入一次,该文件的后续导入语句将被忽略。

发布v1。4

这是@import语句的默认行为。

例子:

@import (once) "foo.less";
@import (once) "foo.less"; // this statement will be ignored

7、multiple

使用@import(multiple)允许导入具有相同名称的多个文件。这是与以前相反的行为。

发布v1。4

例子:

// file: foo.less
.a {
  color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";

输出:

.a {
  color: green;
}
.a {
  color: green;
}

8、optional

使用@import(可选)仅当文件存在时才允许导入文件。如果没有可选关键字Less,则在导入找不到的文件时会抛出文件错误并停止编译。

发布v2。3

十、@插件规则

发布v2。5

导入JavaScript插件以添加更少的内容。js功能和特性

1、编写第一个插件

在规则中使用@plugin与在规则中使用@import类似。更少的文件。

@plugin "my-plugin";  // automatically appends .js if no extension

由于在较小的范围内评估的插件较少,因此插件定义可能非常简单。

registerPlugin({
    install: function(less, pluginManager, functions) {
        functions.add('pi', function() {
            return Math.PI;
        });
    }
})

或者您可以使用模块。导出(填充以在浏览器和Node.js中工作)。

module.exports = {
    install: function(less, pluginManager, functions) {
        functions.add('pi', function() {
            return Math.PI;
        });
    }
};

注意另一个节点。js CommonJS约定,如require()在浏览器中不可用。在编写跨平台插件时,请记住这一点。

你可以用插件做什么?很多,但让我们从基础开始。我们将首先关注安装函数中可能包含的内容。假设你写了这个:

// my-plugin.js
install: function(less, pluginManager, functions) {
    functions.add('pi', function() {
        return Math.PI;
    });
}
// etc

祝贺你写的插件少了!

如果要在样式表中使用此选项:

@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”,它会更小。尺寸(10,“px”)。有关单元列表,请参阅Less API。

现在您可以在操作中使用您的函数。

@plugin "my-plugin";
.show-me-pi {
  value: pi() * 2;
}

您可能已经注意到,插件文件有可用的全局变量,即函数注册表(functions对象)和less对象。这些是为了方便。

2、插件作用域

由@plugin at rule添加的函数遵循范围较小的规则。这对于希望添加功能而不引入命名冲突的库作者来说是非常好的。

例如,假设您有两个来自两个第三方库的插件,它们都有一个名为“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();

从3.0开始,函数可以返回任何类型的节点类型,并且可以在任何级别调用。

也就是说,这将在2中抛出一个错误。x、 因为函数必须是属性或变量赋值的一部分:

.block {
    color: blue;
    my-function-rules();
}

在3。x、 情况不再如此,函数可以在规则、规则集、任何其他较少的节点、字符串和数字处返回(后两者转换为匿名节点)。

3、空函数

有时,您可能希望调用函数,但不希望输出任何内容(例如存储值以供以后使用)。在这种情况下,您只需要从函数返回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();   
}

4、less.js 插件对象

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实例提供了添加访问者、文件管理器和后期处理器的方法。

下面是一些示例repo,展示了不同的插件类型。

  • 后处理器(post-processor):https://github.com/less/less-plugin-clean-css
  • 参观者(visitor):https://github.com/less/less-plugin-inline-urls
  • 文件管理器(file-manager):https://github.com/less/less-plugin-npm-import

5、预加载插件

尽管@plugin调用在大多数情况下都能很好地工作,但有时您可能希望在解析开始之前加载插件。

请参阅“使用更少的.js”部分中的预加载插件,了解如何做到这一点。

十一、Maps(新!)

发布v3。5

使用规则集和混合作为值的映射

通过将名称空间与查找相结合 [ ] 语法相结合,您可以将规则集/混合转换为映射。

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

由于名称空间和重载mixin的能力,mixin比maps更通用。

#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;
}

您还可以通过对mixin进行别名处理来简化此过程。即:

.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;
  }
}

通过这种方式,规则集和变量调用可以模拟一种类似于mixin的“名称空间”。

至于是否使用mixin或分配给变量的规则集作为映射,这取决于您。您可能希望通过重新声明分配给rulset的变量来替换整个映射。或者您可能希望“合并”单个键/值对,在这种情况下,作为映射混合可能更合适。

1、在查找中使用变量

需要注意的一件重要事情是[@lookup]中的值是键(变量)名称@lookup,并且不是作为变量计算的。如果希望键名本身是可变的,可以使用@variable语法。

例如:

.foods() {
  @dessert: ice cream;
}

@key-to-lookup: dessert;

.lunch {
  treat: .foods[@@key-to-lookup];
}

这将产生:

.lunch {
  treat: ice cream;
}

【参考】

深入解读 Less 特性 | Less.js 中文文档 - Less 中文网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值