Christian-health / StudyNote2017

2017年学习笔记
0 stars 0 forks source link

less overView #22

Open Christian-health opened 6 years ago

Christian-health commented 6 years ago

使用《》来标记重点

Less 网站地址:http://www.lesscss.net/features/

变量

顾名思义:

@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;  《对变量进行加减运算》

#header {
  color: @light-blue;
}

输出:

#header {
  color: #6c94be;
}

注意:

《由于变量只能定义一次,实际上他们就是“常量” 》

Christian-health commented 6 years ago

混合mixins

混合就是一种将一系列属性从一个规则集引入(“混合”)到另一个规则集的方式。假设我们有以下 class:

.bordered { border-top: dotted 1px black; border-bottom: solid 2px black; } 我们希望在另一个规则集内部使用上面这些属性。那么,我们就只需要访问我们想要的属性所在类的名称即可,就像下面这样:

menu a {

color: #111; .bordered; }

.post a { color: red; .bordered; } 类 .bordered 的属性现在就会同事呈现在 #menu a 和 .post a 中了(注意,同样可以将 #ids 作为 mixins)。

《换句话说,可以使用(类)进行混合,可以使用(id)进行混合》

例如:

.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

#menu a {
  color: #111;
  .bordered;   《使用类进行混合》
}

.post a {
  color: red;
  .bordered;
}

#bordered_useId {
  border-top: dotted 1px red;
  border-bottom: solid 2px red;
}

#menu p {
  color: #111;
  #bordered_useId;《使用id进行混合》
}

.post1 a {
  color: red;
 #bordered_useId
}
Christian-health commented 6 years ago

嵌套规则(Nested rules)

Less 为我们提供了嵌套的能力, 而不是合并在样式表中.假设我们有下面的 CSS:

#header {
  color: black;
}
#header .navigation {
  font-size: 12px;
}
#header .logo {
  width: 300px;
}

在 Less 中,我们可以以下面这种方式编写:

#header {
  color: black;
  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
  }
}

这样的代码更简洁, 它模仿了 HTML 的结构.

使用这种方法照样可以在混合中包含伪类(pseudo-selectors)。下面是一个经典的 clearfix 代码,在这里使用 mixin 重写了(& 表示当前选择器的父选择器):

.clearfix {
  display: block;
  zoom: 1;

  &:after {  《& 表示当前选择器的父选择器》
    content: " ";
    display: block;
    font-size: 0;
    height: 0;
    clear: both;
    visibility: hidden;
  }
}
Christian-health commented 6 years ago

运算(opertaions) 加减乘除

任何数值,颜色和变量都可以进行运算。这里有一对示例:

@base: 5%;
@filler: @base * 2;
@other: @base + @filler;

color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;

最后的输出结果与你预期的一样 -- Less 能够推断颜色和单位之间的区别。如果在一个运算中使用了单位,比如:

@var: 1px + 5; 在这个例子中 Less 会在最终输出结果中使用这个单位 -- 6px。

Christian-health commented 6 years ago

函数(Functions)

Less 提供了许多用于转换颜色,处理字符串和进行算术运算的函数。他们在函数参考一节有详细的的介绍。

这些函数使用起来非常简单。在下面的例子中我们使用 percentage 将 0.5 转换为 50%,然后将基础颜色值的饱和度增加了 5%,最后将背景颜色的亮度增加了 25% 之后又将色相值增加 8:

@base: #f04615;
@width: 0.5;

.class {
  width: percentage(@width); // returns `50%`
  color: saturate(@base, 5%);
  background-color: spin(lighten(@base, 25%), 8);
}
Christian-health commented 6 years ago

命名空间和访问器(Namespaces & Accessors)

(不要将它与 CSS @namespace or namespace 选择器混为一谈)。

有时候,出于组织的目的,或者为了提供一些封装,你会希望将你的mixins 组合在一起。在 Less 中做到这一点非常直观,假设你想在 #bundle 下捆绑一些 mixins 和变量,以便稍候复用或者分发:

#bundle {
  .button {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white
    }
  }
  .tab { ... }
  .citation { ... }
}

现在如果我们想在 #header a 中混合 .button 类,那么我们可以这样做:

#header a {
  color: orange;
  #bundle > .button;
}

Note that variables declared within a namespace will be scoped to that namespace only and will not be available outside of the scope via the same syntax that you would use to reference a mixin (#Namespace > .mixin-name). So, for example, you can't do the following: (#Namespace > @this-will-not-work). 请注意,在命名空间中声明的变量将仅限于该命名空间,并且将不能在范围之外使用与引用mixin(#Namespace> .mixin-name)相同的语法来使用。 所以,例如,您不能执行以下操作:(#Namespace> @ this-will-not-work)。

例如:

#bundle {
  .button {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white
    }
  }
  .tab { 
       background-color: yellow;
   }
  .citation { 
       background-color: red;
  }
}

#header a {
  color: orange;
  #bundle > .button;
}

less转换之后:

#bundle .button {
  display: block;
  border: 1px solid black;
  background-color: grey;
}
#bundle .button:hover {
  background-color: white;
}
#bundle .tab {
  background-color: yellow;
}
#bundle .citation {
  background-color: red;
}
#header a {
  color: orange;
  display: block;
  border: 1px solid black;
  background-color: grey;
}
#header a:hover {
  background-color: white;
}

这里有点理解不了为什么是如下的结果:

#header a {
  color: orange;
  display: block;
  border: 1px solid black;
  background-color: grey;
}
#header a:hover {
  background-color: white;
}

其实

#header a {
  color: orange;
  #bundle > .button;
}

这句话的意思是,就是在#header a中使用 #bundle > .button; 也就是使用.button这个类。 所以不要管其他的什么,就是把.button这个类的东西放入到#header a {}之中,所以&:hover的父类型,应该是a,所以最终应该是a:hover

Christian-health commented 6 years ago

作用域(Scope)

Less 中的作用域与编程语言中的作用域概念非常相似。首先会在局部查找变量和混合,如果没找到,编译器就会在父作用域中查找,依次类推。

@var: red;

#page {
  @var: white;  《先声明,后使用》
  #header {
    color: @var; // white
  }
}

《变量和混合不必在使用前声明》 所以变量写后面也没事

因此下面的代码与前面的例子等价:

@var: red;

#page {
  #header {
    color: @var; // white
  }
  @var: white;  《先使用,后声明》
}
Christian-health commented 6 years ago

注释

可以使用块注释和行注释:

/* One hell of a block
style comment! */
@var: red;

// Get in line!
@var: white;
Christian-health commented 6 years ago

导入

导入工作与你预期的一样。你可以导入一个 .less 文件,然后这个文件中的所有变量都可以使用了。对于 .less 文件而言,其扩展名是可选的。

@import "library"; // library.less  《导入less文件》
@import "typo.css";
Christian-health commented 6 years ago

变量 Variables

概述(over view)

在你的样式表中相同的值重复几十次甚至上百次并不少见:

a,
.link {
  color: #428bca;
}
.widget {
  color: #fff;
  background: #428bca;
}

变量通过为你提供一种在一个地方管理这些值的方法让你的代码变得更容易维护:

// 变量
@link-color:        #428bca; // sea blue
@link-color-hover:  darken(@link-color, 10%);

// 用法
a,
.link {
  color: @link-color;
}
a:hover {
  color: @link-color-hover;
}
.widget {
  color: #fff;
  background: @link-color;
}
Christian-health commented 6 years ago

变量插值(variable interpolation)

在上面的例子主要集中于在CSS规则中使用变量管理值,实际上它们还可以用在其他地方,比如选择器名称,属性名,URLs以及@import语句中。

《可以使用变量名称的地方:选择器名称,属性名,URLs以及@import语句中》

选择器(Selectors)作为变量

版本: 1.4.0

// 变量
@mySelector: banner;

// 用法
.@{mySelector} {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}

最终编译为:

.banner {
  font-weight: bold;
  line-height: 40px;
  margin: 0 auto;
}
Christian-health commented 6 years ago

Urls URLs作为变量

// 变量
@images: "../img";

// 用法
body {
  color: #444;
  background: url("@{images}/white-sand.png");
}
Christian-health commented 6 years ago

Import 语句 (没看懂)

版本: 1.4.0

语法: @import "@{themes}/tidal-wave.less";

注意,目前都只有将变量声明在根作用域或者是当前作用域中,然后只有当前文件以及使用这个文件时才会考虑什么时候查找一个变量。这意味着这种用法通常在你注入变量到编译过程中或者在根文件的开始部分声明变量的做法是有限的。

当你引入一个CSS文件,同时不使用内联选项(比如,import语句保持不变)时让面的规则就不会应用。

示例:

// 变量
@themes: "../../src/themes";

// 用法
@import "@{themes}/tidal-wave.less";
Christian-health commented 6 years ago

属性 把属性值做成变量

@property: color;

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

.widget {
  color: #0ee;
  background-color: #999;
}
Christian-health commented 6 years ago

变量是延迟加载

变量是延迟加载的,在使用前不一定要预先声明。

有效的Less片段:

.lazy-eval {
  width: @var;
}

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

下面这个也是有效的Less片段:

.lazy-eval-scope {
  width: @var;
/*
 为什么是width:9%  因为,这里是 
  width:@var 
  @var: @a;
  @a: 9%;
 所以没有使用外部的变量,所以没有使用@a:100%
*/
  @a: 9%;
}

@var: @a;
@a: 100%;

最终都会编译为:

.lazy-eval-scope {
  width: 9%;
}

《在定义一个变量两次时,只会使用最后定义的变量,Less会从当前作用域中向上搜索。这个行为类似于CSS的定义中始终使用最后定义的属性值。》

比如:

@var: 0;
.class {
  @var: 1;
  .brass {
    @var: 2;
    three: @var;
    @var: 3;
  }
  one: @var;
}

等价于:

@var: 0;
.class {
  @var: 1; 
  one: @var;
  .brass {
    @var: 2;
    three: @var;
    @var: 3;
  }
}

会编译为:

.class {
  one: 1;
}
.class .brass {
  three: 3;
}
Christian-health commented 6 years ago

默认变量 (默认变量会被复写,覆盖)

有时候你会用到默认变量-让你能够在没有设置某些变量的情况下设置指定的变量。这一特性并不强制要求你这么做,因为你可以很容易通过插入后定义同名变量的方式覆盖默认变量。

比如:

// library
@base-color: green;
@dark-color: darken(@base-color, 10%);

// use of library
@import "library.less";
@base-color: red;

这个是能够工作的 - 其中base-color会被重写,而dark-color依然是暗红色。

Christian-health commented 6 years ago

Extend 扩展选择器

extend是一个Less伪类,它会合并它所在的选择器和它所匹配的引用

nav ul {
  &:extend(.inline);  //《合并它所在的选择器和它所匹配的引用》
  background: blue;
}

在上面设置的规则中,:extend选择器会在.inline类出现的地方在.inline上应用"扩展选择器"(也就是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的 - 输出之前移除了扩展,然后选择器块保持不变。如果代码块中没有放入属性,则从输入中移除它(但是扩展仍然会影响其他选择器)。

Christian-health commented 6 years ago

扩展语法(extend语法) ===》

extend可以附加给一个选择器,也可以放入一个规则集中。它看起来像是一个带选择器参数伪类,也可以使用关键字all选择相邻的选择器。

示例:

.a:extend(.b) {}

// 上面的代码块与下面这个做一样的事情 .a { &:extend(.b); } .c:extend(.d all) { // 扩展".d"的所有实例,比如".x.d"或者".d.x" } .c:extend(.d) { // 扩展选择器输出为".d"的唯一实例 } 它可以包含多个要扩展的类,使用逗号分割即可。

示例:

.e:extend(.f) {} .e:extend(.g) {}

// 上面的代码与下面的做一样的事情 .e:extend(.f, .g) {}

Christian-health commented 6 years ago

为选择器附加扩展

给选择器附加扩展看起来就像一个普通的带参数的伪类选择器。一个选择器可以包含多个扩展分支,但是所有的扩展都必须在选择器的尾部。

选择器之后的扩展: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)。因为扩展必须在最后。 如果一个规则集包含多个选择器,所有选择器都可以使用extend关键字。下面演示了一个规则集中多个带extend的选择器:

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

Christian-health commented 6 years ago

规则集内的extend

也可以使用&:extend(selector)语法在规则集内置入extend。将extend放入规则集内是一种将它放入单个规则选择器的快捷方式。

规则内的extend:

pre:hover, .some-class { &:extend(div pre); } 与给每个选择器添加一个extend完全相同:

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

Christian-health commented 6 years ago

嵌套选择器中的extend

extend还可以匹配嵌套选择器,比如有下面的Less:

示例:

.bucket { tr { // 目标选择器中的嵌套规则 color: blue; } } .some-class:extend(.bucket tr) {} // 识别嵌套规则 这会输出:

.bucket tr, .some-class { color: blue; } 从本质上将extend会查找编译后的CSS,而不是原始的less。

示例:

.bucket { tr & { // 目标选择器中的嵌套 color: blue; } } .some-class:extend(tr .bucket) {} // 识别嵌套规则 输出:

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

Christian-health commented 6 years ago

extend中的精确匹配

Extend默认会在选择器之间寻找精确匹配。它不管选择器是以星号开始还是不是。它也不管两个nth表达式是否具有相同的意义,它们必须以相同的形式匹配。唯一例外的是属性选择器中的引号,less会知道它们是相同的,然后匹配它。

示例:

.a.class, .class.a, .class > .a { color: blue; } .test:extend(.class) {} // 不会匹配上面的任何选择器的值 号开头也是有关系的。选贼起.class和.class是等价的,而extend不会匹配它们:

.class { color: blue; } .noStar:extend(.class) {} 不会匹配.class选择器 输出:

*.class { color: blue; } 伪类的顺序是有关系的。选择器link:hover:visited和link:visited:hover匹配相同的元素集合,但是extend会区别对待它们:

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

link:hover:visited { color: blue; }

Christian-health commented 6 years ago

nth表达式

Nth形式的表达式也是有关系的。Nth表达式1n+3和n+3是等价的,但是extend并不能匹配它们:

:nth-child(1n+3) { color: blue; } .child:extend(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; }

Christian-health commented 6 years ago

extend "all"

当你在extend参数的最后面指定all关键字时,它会告诉告诉匹配作为其他选择器一部分的选择器。这个选择器会被复制,然后匹配的选择器部分会使用扩展替换,创建一个新的选择器。

示例:

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

Christian-health commented 6 years ago

extend中的选择器插值

Extend不能匹配变量选择器。如果选择器包含变量,extend会忽略它。 这是一个悬而未决的特性,改变它并不容易。然而,extend可以附加给插值选择器。

带变量的选择器不会匹配:

@variable: .bucket; @{variable} { // 插值选择器 color: blue; } .some-class:extend(.bucket) {} // 找不到匹配 同时在extend中使用目标选择器变量也什么都不匹配:

.bucket { color: blue; } .some-class:extend(@{variable}) {} // 插值选择器什么也不匹配 @variable: .bucket; 上面两个例子都会编译为:

.bucket { color: blue; } 然而, :extend 附加给插值选择器是能够工作的:

.bucket { color: blue; } @{variable}:extend(.bucket) {} @variable: .selector; 上面的例子会编译为:

.bucket, .selector { color: blue; }

Christian-health commented 6 years ago

作用域/@media 内的extend

编写在media声明内的extend也应该只匹配同一media声明内的选择器:

@media print { .screenClass:extend(.selector) {} // media内的extend .selector { // 这个会匹配到-因为在同一的media内 color: black; } } .selector { // 定义样式表中的规则 - extend会忽略它 color: red; } @media screen { .selector { // 另一个media声明内的规则 - extend也会忽略它 color: blue; } } 最终编译为:

@media print { .selector, .screenClass { / 同一media内的规则扩展成功 / color: black; } } .selector { / 定义样式表中的规则被忽略 / color: red; } @media screen { .selector { / 其他media中的规则也被忽略 / color: blue; } } 编写在media声明内的extend不会匹配嵌套声明内的选择器:

@media screen { .screenClass:extend(.selector) {} // media内的extend @media (min-width: 1023px) { .selector { // 嵌套media内的规则 - extend会忽略它 color: blue; } } } 编译为:

@media screen and (min-width: 1023px) { .selector { / 其他嵌套media内的规则被忽略 / color: blue; } } 顶级extend匹配一切,包括media嵌套内的选择器:

@media screen { .selector { / media嵌套内的规则 - 顶级extend正常工作 / color: blue; } @media (min-width: 1023px) { .selector { / media嵌套内的规则 - 顶级extend正常工作 / color: blue; } } }

.topLevel:extend(.selector) {} / 顶级extend匹配一切 / 编译为:

@media screen { .selector, .topLevel { / media嵌套内的规则被扩展了 / color: blue; } } @media screen and (min-width: 1023px) { .selector, .topLevel { / media嵌套内的规则被扩展了 / color: blue; } }

Christian-health commented 6 years ago

检测重复

现在,这里还没有检测重复。

示例:

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

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

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

Christian-health commented 6 years ago

Extend 用例

经典用例

经典用于就是避免添加基础类。比如,如果你有:

.animal { background-color: black; color: white; } 如果你想有一个animal子类型,并且要重写背景颜色。那么你有两个选择,首先改变你的HTML

Bear .animal { background-color: black; color: white; } .bear { background-color: brown; } 或者简化HTML,然后在你的less中使用extend,比如:

Bear .animal { background-color: black; color: white; } .bear { &:extend(.animal); background-color: brown; }

css尺寸规并

Mixins会复制所有的属性到选择器中,这可能导致不必要的重复。因此你可以使用extend来代替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; } extend示例:

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

合并样式/更高级的mixin

另一个用例可以用作mixin的替代 - 因为mixin仅仅能用于简单的选择器,如果你的html中有两个不同的块,但是你需要为这两个块应用相同的样式,那么你可以使用extend来关联这两块。

示例:

li.list > a { // list styles } button.list-style { &:extend(li.list > a); // 使用相同的列表样式 }

Christian-health commented 6 years ago

Mixins 混合

你可以混合“类”选择器或者“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;
Christian-health commented 6 years ago

不输出混合集合

如果你想要创建一个混合集,但是却不想让它输出到你的样式中,你可以在混合集的名字后面加上一个括号。

.my-mixin {
  color: black;
}
.my-other-mixin() {  //不想让它输出到你的样式
《这个东西类似于代码中的public protected private里面的private,只是给内部使用》
  background: white;
}
.class {
  .my-mixin;
  .my-other-mixin;
}

结果为:

《没有输出.my-other-mixin这个类型》
.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}
Christian-health commented 6 years ago

带选择器的混合集合

混合集不仅可以包含各种属性,而且可以包括各种选择器。

例如:

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

结果为:

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

相当于把.my-hover-mixin()这个类型的代码直接的放入到button中,那么如下:

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

然后less进行转换,就变成了:

button:hover {
  border: 1px solid red;
}
Christian-health commented 6 years ago

命名空间

如果你想要将属性混合到比较复杂的选择器中,你可以通过嵌套多层id或者class。

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

.c {
  #outer > .inner;
}

同样 > 是可选的

// 下面四种写法效果是一样的

#outer > .inner;
#outer > .inner();
#outer.inner;
#outer.inner();

这种用法的效果相当于我们熟知的命名空间,你可以把混合集放到一个id选择器里面,这样可以确保它(这个混合集)不会跟其他的库冲突。

例如:

#my-library {
  .my-mixin() {
    color: black;
  }
}

// 可以这样调用
.class {
  #my-library > .my-mixin();
}
Christian-health commented 6 years ago

!import 关键字

在调用的混合集后面追加 !important 关键字,可以使混合集里面的所有属性都继承 !important:

例如:

.foo (@bg: #f5f5f5, @color: #900) {
  background: @bg;
  color: @color;
}
.unimportant {
  .foo();
}
.important {
  .foo() !important;《混合集里面的所有属性都继承 !important》
}

结果为:

.unimportant {
  background: #f5f5f5;
  color: #900;
}
.important {
  background: #f5f5f5 !important;  《混合集里面的所有属性都继承 !important》
  color: #900 !important;《混合集里面的所有属性都继承 !important》
}
Christian-health commented 6 years ago

parametric Mixins ( 参数混合)

如何给mixins传递参数 mixins也可以接受参数,在它进行mix in操作时会将变量传递给选择器代码块。

比如:

.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的border-radius。

你也可以使用不接受参数的mixins。如果你想从输出的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;
}
Christian-health commented 6 years ago

带多个参数的 Mixins

参数可以用分号或者逗号分割。但是推荐使用分号分割。因为逗号符号有两个意思:它可以解释为mixins参数分隔符或者css列表分隔符。

使用逗号作为mixin的分隔符则无法用它创建逗号分割的参数列表。换句话说,如果编译器在mixin调用或者声明中看到至少一个分号,它会假设参数是由分号分割的,而所有的逗号都属于CSS列表:

  1. 两个参数,并且每个参数都是逗号分割的列表:.name(1,2,3;something, ele),
  2. 三个参数,并且每个参数都包含一个数字:.name(1,2,3),
  3. 使用伪造的分号创建mixin,调用的时候参数包含一个逗号分割的css列表:.name(1,2,3;),
  4. 逗号分割默认值:.name(@param1: red, blue)。

定义多个具有相同名称和参数数量的mixins是合法的。Less会使用它可以应用的属性。如果使用mixin的时候只带一个参数,比如.mixin(green),这个属性会导致所有的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;
}
Christian-health commented 6 years ago

命名参数

引用mixin时可以通过参数名称而不是参数的位置来为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;
}
Christian-health commented 6 years ago

@argument 参数

@arguments在mixins内部有特殊意义,调用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;
}
Christian-health commented 6 years ago

高级参数和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 会绑定到参数 @a 之后
   // 而@arguments是绑定所有参数
}
Christian-health commented 6 years ago

模式匹配

有时候,你可能想要基于你传递给它的参数改变mixin的行为。先来看一些基础的示例:

.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,结果会变成暗色。

这里发生了什么:

  1. 第一个mixin定义并没有匹配,因为它期望第一个参数是dark。
  2. 第二个mixin定义匹配了,因为它接受的参数是预期的light。
  3. 第三个mixin定义也匹配了,因为它任何值都在其预料只用。

这里只会使用匹配的mixin。变量匹配,然后绑定给任意变量。

除了变量匹配,只有一个值与其自身相等。

你也可以基于参数数量来匹配,这里有个例子:

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

现在,如果我们用一个参数来调用.mixin,这将会输出第一个定义,但是如果我们使用两个参数调用它,这回获取第二个定义,这就是@a淡入到@b。

Christian-health commented 6 years ago

Mixins as Function 调用一个Mixins返回一个变量,所以就有点像一个函数一样

从mixin中返回变量
所有定义在一个mixin中的变量都是可见的,还可以用于调用它的作用域中(除非调用它的作用域定义了同名变量)。

示例:

.mixin() {
  @width:  100%;
  @height: 200px;
}

.caller {
  .mixin();
  width:  @width;
  height: @height;
}
结果:

.caller {
  width:  100%;
  height: 200px;
}
因此定义在mixin中的变量还可以充当它的返回值。这样就允许我们创建一个用起来类似函数的mixin。

示例:

.average(@x, @y) {
  @average: ((@x + @y) / 2);
}

div {
  .average(16px, 50px); // "call" the mixin
  padding: @average;    // use its "return" value
}
结果:

div {
  padding: 33px;
}
Christian-health commented 6 years ago

Passing Rulesets to mixins =======》

允许在mixin中定义包装的CSS块
发布于 v1.7.0

你可能希望定义一个mixin将一个媒体查询中的一个代码块或者一个浏览器不支持的类名抽象出来。
现在,你可以传递规则集给mixin,然后该mixin会包装这些规则集。比如:

.desktop-and-old-ie(@rules) {
  @media screen and (min-width: 1200) { @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: 1200) {
  header {
    background-color: red;
  }
}
html.lt-ie9 header {
  background-color: red;
}
A ruleset can be now assigned to a variable or passed in to a mixin and can contain 
the full set of less features, e.g.

@my-ruleset: {
    .my-selector {
      background-color: black;
    }
  };
You can even take advantage of media query bubbling, for instance

@media (orientation: portrait) and tv {
  .my-selector {
    background-color: black;
  }
}
which will output

@my-ruleset: {
    .my-selector {
      @media tv {
        background-color: black;
      }
    }
  };
@media (orientation:portrait) {
    @my-ruleset();
}