在 Less v1.4.0 引入了 Extend,Extend 是一个 Less 伪类,它将放置它的选择器与其引用的匹配的选择器合并。例如:
// 放置 extend 的选择器,nav ul nav ul { // 引用 .inline &:extend(.inline); background: blue; }
在上面的规则集中,:extend 选择器会将 "继承选择器" (nav ul) 应用于 .inline 类,无论 .inline 类出现在哪里。声明块将保持原样,但不会引用扩展(因为扩展不是 CSS)。所以如下:
nav ul { // 表示继承 .inline 下声明的样式 &:extend(.inline); background: blue; } .inline { color: red; }
编译 Less,输出 CSS 如下:
nav ul { background: blue; } .inline, nav ul { color: red; }
扩展要么附加到选择器,要么放入规则集中。它看起来像一个带有选择器参数的伪类,可选地后跟关键字 all。例子:
/* 继承 .b1 */ .b1 { color: red; } .a1:extend(.b1) { background: blue; } /* 继承 .b2 */ .b2 { color: red; } .a2 { &:extend(.b2); background: blue; } /* 扩展 “.b3” 的所有实例,例如 “.x.b3” 或 “.b3.x” */ .b3 { color: red; .myDiv { border: solid 1px red; } } .div3 { .b3 { font-size: 20px; } } .a3:extend(.b3 all) { background: blue; } /* 仅扩展 “.b4” 选择器,仅输出 “.b4” 的实例 */ .b4 { color: red; .myDiv { border: solid 1px red; } } .div4 { .b4 { font-size: 20px; } } .a4:extend(.b4) { background: blue; }
编译 Less,输出 CSS 如下:
/* 继承 .b1 */ .b1, .a1 { color: red; } .a1 { background: blue; } /* 继承 .b2 */ .b2, .a2 { color: red; } .a2 { background: blue; } /* 扩展 “.b3” 的所有实例,例如 “.x.b3” 或 “.b3.x” */ .b3, .a3 { color: red; } .b3 .myDiv, .a3 .myDiv { border: solid 1px red; } .div3 .b3, .div3 .a3 { font-size: 20px; } .a3 { background: blue; } /* 仅扩展 “.b4” 选择器,仅输出 “.b4” 的实例 */ .b4, .a4 { color: red; } .b4 .myDiv { border: solid 1px red; } .div4 .b4 { font-size: 20px; } .a4 { background: blue; }
注意,extend 可以包含一个或多个要扩展的类,以逗号分隔。例子:
.e:extend(.f, .g) {}
到选择器的 extend 看起来更像一个普通的伪类,将选择器作为参数。一个选择器可以包含多个 extend 子句,但所有 extend 都必须位于选择器的末尾。其中:
extend 必须放在选择器之后,例如:pre:hover:extend(div pre),如果将 extend 没有放在选择器末尾,是不允许的,例如:pre:hover:extend(div pre).nth-child(odd).
选择器和 extend 之间的空格是允许的,例如:pre:hover :extend(div pre)
选择器允许多个 extend,例如:pre:hover:extend(div pre):extend(.bucket tr) 等价 pre:hover:extend(div pre, .bucket tr)
如果规则集包含多个选择器,则其中任何一个都可以具有 extend 关键字。例如:
.big-division, .big-bag:extend(.bag), .big-bucket:extend(.bucket) { // ... }
可以使用 &:extend(selector) 语法将 Extend 放入规则集的主体中。将 extend 放入主体是将其放入该规则集的每个选择器的快捷方式。例如:
在主体内放置 extend:
pre:hover, .some-class { &:extend(div pre); }
与在每个选择器之后添加 extend 完全相同:
pre:hover:extend(div pre), .some-class:extend(div pre) { //... }
Extend 能够匹配嵌套的选择器。例子:
.bucket { tr { // 具有选择器的嵌套规则集 color: blue; } } // 继承嵌套规则集 .some-class:extend(.bucket tr) { //... }
编译 Less,输出 CSS 如下:
.bucket tr, .some-class { color: blue; }
本质上,extend 着眼于编译后的 css,而不是原始的 less。例子:
.bucket { // 这里的 & 表示 .bucket tr & { // 嵌套规则集 color: blue; } } // 继承嵌套规则集 .some-class:extend(tr .bucket) { //... }
编译 Less,输出 CSS 如下:
tr .bucket, .some-class { color: blue; }
默认情况下扩展会查找选择器之间的精确匹配。选择器是否使用前导向并不重要。两个第 n 个表达式具有相同的含义并不重要,它们需要具有相同的形式才能匹配。唯一的例外是属性选择器中的引导,Less 知道它们具有相同的含义并匹配它们。
例子:
.a.class, .class.a, .class > .a { color: blue; } // 这将与上面的任何选择器不匹配 .test:extend(.class) { //... }
主角确实很重要。选择器 *.class 和 .class 是等价的,但 extend 不会匹配它们:
*.class { color: blue; } // 这将与 *.class 选择器不匹配 .noStar:extend(.class) {}
编译 Less,输出 CSS 如下:
*.class { color: blue; }
伪类的顺序确实很重要。选择器 link:hover:visited 和 link:visited:hover 匹配同一组元素,但 extend 将它们视为不同的:
link:hover:visited { color: blue; } .selector:extend(link:visited:hover) { //... }
编译 Less,输出 CSS 如下:
link:hover:visited { color: blue; }
第 n 个表达式形式确实很重要。第 n 个表达式 1n+3 和 n+3 是等价的,但 extend 不会匹配它们:
:nth-child(1n+3) { color: blue; } :nth-child(n+3) { background: red; } .child:extend(:nth-child(n+3)) { font-size: 12px; }
编译 Less,输出 CSS 如下:
:nth-child(1n+3) { color: blue; } :nth-child(n+3), .child { background: red; } .child { font-size: 12px; }
属性选择器中的引用类型无关紧要。以下所有内容都是等价的:
[title=identifier] { color: blue; } [title='identifier'] { color: blue; } [title="identifier"] { color: blue; } .noQuote:extend([title=identifier]) {} .singleQuote:extend([title='identifier']) {} .doubleQuote:extend([title="identifier"]) {}
编译 Less,输出 CSS 如下:
[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) {}
编译 Less,输出 CSS 如下:
.a.b.test, .test.c, .a.b.replacement, .replacement.c { color: orange; } .test:hover, .replacement:hover { color: green; }
你可以将这种操作模式视为本质上进行非破坏性搜索和替换。
Extend 无法将选择器与变量匹配。若选择器包含变量,则 extend 将忽略它。但是,extend 可以附加到插值选择器。
带有变量的选择器将不会被匹配:
@variable: .bucket; @{variable} { // 插值选择器 color: blue; } .some-class:extend(.bucket) {} // 什么也不做,找不到匹配项
并在目标选择器中使用变量扩展不匹配:
.bucket { color: blue; } .some-class:extend(@{variable}) {} // 插值选择器不匹配任何内容 @variable: .bucket;
编译以上两个 Less,输出 CSS 如下:
.bucket { color: blue; }
但是,附加到插值选择器的 :extend 有效:
.bucket { color: blue; } @{variable}:extend(.bucket) {} @variable: .selector;
编译 Less,输出 CSS 如下:
.bucket, .selector { color: blue; }
目前,@media 声明中的 :extend 只会匹配同一媒体声明中的选择器:
@media print { .screenClass:extend(.selector) {} // 扩展内部 media .selector { // 这将是匹配的-它在同一 media 上 color: black; } } .selector { // 样式表顶部的规则集 - extend 忽略它 color: red; } @media screen { .selector { // 另一个媒体中的规则集 - extend 忽略它 color: blue; } }
编译 Less,输出 CSS 如下:
@media print { .selector, .screenClass { /* 扩展了同一 media 中的规则集 */ color: black; } } .selector { /* 样式表顶部的规则集被忽略 */ color: red; } @media screen { .selector { /* 忽略了另一个介质中的规则集 */ color: blue; } }
注意:扩展与嵌套 @media 声明内的选择器不匹配:
@media screen { .screenClass:extend(.selector) {} // 扩展内部 media @media (min-width: 1023px) { .selector { // 嵌套 media 中的规则集 - extend 忽略它 color: blue; } } }
编译 Less,输出 CSS 如下:
@media screen and (min-width: 1023px) { .selector { /* 另一个嵌套媒体中的规则集被忽略 */ color: blue; } }
顶层扩展匹配所有内容,包括嵌套媒体内的选择器:
@media screen { .selector { /* 嵌套 media 中的规则集 - 顶级扩展工作 */ color: blue; } @media (min-width: 1023px) { .selector { /* 嵌套 media 中的规则集 - 顶级 extend 工作 */ color: blue; } } } .topLevel:extend(.selector) {} /* 顶级 extend 匹配所有内容 */
编译 Less,输出 CSS 如下:
@media screen { .selector, .topLevel { /* 扩展了介质内部的规则集 */ color: blue; } } @media screen and (min-width: 1023px) { .selector, .topLevel { /* 扩展了嵌套 media 中的规则集 */ color: blue; } }
目前没有重复检测。例子:
.alert-info, .widget { /* declarations */ } .alert:extend(.alert-info, .widget) {}
编译 Less,输出 CSS 如下:
.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 中使用 extend。 例如
<a class="bear">Bear</a> .animal { background-color: black; color: white; } .bear { &:extend(.animal); background-color: brown; }
Mixins 将所有属性复制到一个选择器中,这会导致不必要的重复。 因此,你可以使用 extends 而不是 mixins 将选择器向上移动到你希望使用的属性,这会导致生成更少的 CSS。
示例 - 使用 mixin:
.my-inline-block() { display: inline-block; font-size: 0; } .thing1 { .my-inline-block; } .thing2 { .my-inline-block; }
编译 Less,输出 CSS 如下:
.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); }
编译 Less,输出 CSS 如下:
.my-inline-block, .thing1, .thing2 { display: inline-block; font-size: 0; }
另一个用例是作为混入的替代方案 - 因为混入只能与简单的选择器一起使用,如果你有两个不同的 html 块,但需要对两者应用相同的样式,你可以使用 extends 来关联两个区域。
例子:
li.list > a { // list 样式 } button.list-style { &:extend(li.list > a); // 使用相同的列表样式 }