在 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); // 使用相同的列表样式
}