Extend
Extend 是 Less 的伪类,它将其放置在的选择器与匹配其引用的选择器合并。
发布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) {
}
// 上面的块与下面的块执行相同的操作
.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) {
}
附加到选择器的扩展
附加到选择器的扩展看起来像一个普通的带有选择器参数的伪类。选择器可以包含多个扩展子句,但所有扩展子句必须位于选择器的末尾。
- 选择器后的扩展:
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)
语法将 Extend 放置在规则集的主体中。将 Extend 放置在主体中是将其放置在该规则集的每个选择器中的快捷方式。
主体内的 Extend:
pre:hover,
.some-class {
&:extend(div pre);
}
与在每个选择器后添加 Extend 完全相同:
pre:hover:extend(div pre),
.some-class:extend(div pre) {
}
扩展嵌套选择器
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;
}
使用 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;
}
nth 表达式
Nth 表达式的形式很重要。Nth 表达式 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;
}
扩展“all”
当你在扩展参数中最后指定 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} {
// 插值选择器
color: blue;
}
.some-class:extend(.bucket) {
} // 不起作用,没有找到匹配项
在目标选择器中带有变量的扩展不匹配任何内容:
.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;
}
作用域 / 在 @media 中使用扩展
目前,在 @media
声明中的 :extend
仅匹配相同媒体声明中的选择器:
@media print {
.screenClass:extend(.selector) {
} // 媒体内部的扩展
.selector {
// 这将被匹配 - 它在相同的媒体中
color: black;
}
}
.selector { // 样式表的顶部 - 扩展忽略它
color: red;
}
@media screen {
.selector {
// 另一个媒体内的规则集 - 扩展忽略它
color: blue;
}
}
编译为:
@media print {
.selector,
.screenClass {
/* 同一媒体内的规则集被扩展 */
color: black;
}
}
.selector {
/* 样式表顶部的规则集被忽略 */
color: red;
}
@media screen {
.selector {
/* 另一个媒体内的规则集被忽略 */
color: blue;
}
}
注意:扩展不匹配嵌套的@media
声明内的选择器:
@media screen {
.screenClass:extend(.selector) {
} // 媒体内的扩展
@media (min-width: 1023px) {
.selector {
// 嵌套媒体内的规则集 - 扩展忽略它
color: blue;
}
}
}
这将编译为:
@media screen and (min-width: 1023px) {
.selector {
/* 另一个嵌套媒体内的规则集被忽略 */
color: blue;
}
}
顶级扩展匹配所有内容,包括嵌套媒体内的选择器:
@media screen {
.selector {
/* 嵌套媒体内的规则集 - 顶级扩展有效 */
color: blue;
}
@media (min-width: 1023px) {
.selector {
/* 嵌套媒体内的规则集 - 顶级扩展有效 */
color: blue;
}
}
}
.topLevel:extend(.selector) {
} /* 顶级扩展匹配所有内容 */
编译为:
@media screen {
.selector,
.topLevel {
/* 媒体内的规则集被扩展 */
color: blue;
}
}
@media screen and (min-width: 1023px) {
.selector,
.topLevel {
/* 嵌套媒体内的规则集被扩展 */
color: blue;
}
}
重复检测
目前没有重复检测。
例如:
.alert-info,
.widget {
/* 声明 */
}
.alert:extend(.alert-info, .widget) {
}
输出:
.alert-info,
.widget,
.alert,
.alert {
/* 声明 */
}
扩展的用例
经典用例
经典用例是避免添加基础类。例如,如果你有
.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;
}
多个选择器
另一个用例是在多个选择器之间共享样式。例如,如果你有以下 HTML:
<button class="primary">Primary Button</button>
<button class="secondary">Secondary Button</button>
并且你想要两个按钮都具有相同的样式,则可以使用 extend:
.button {
border: 1px solid black;
padding: 10px;
}
.primary:extend(.button) {
background-color: blue;
color: white;
}
.secondary:extend(.button) {
background-color: gray;
color: black;
}
这将编译为:
.button,
.primary,
.secondary {
border: 1px solid black;
padding: 10px;
}
.primary {
background-color: blue;
color: white;
}
.secondary {
background-color: gray;
color: black;
}
继承
另一个用例是继承。例如,如果你有以下 HTML:
<div class="parent">
<div class="child"></div>
</div>
并且你想要子元素继承父元素的样式,则可以使用 extend:
.parent {
background-color: gray;
color: white;
}
.child:extend(.parent) {
font-size: 20px;
}
这将编译为:
.parent,
.child {
background-color: gray;
color: white;
}
.child {
font-size: 20px;
}
减少 CSS 大小
Mixin 将所有属性复制到选择器中,这可能会导致不必要的重复。因此,你可以使用 extends 而不是 mixins 将选择器移动到要使用的属性,这会导致生成的 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;
}
示例(使用 extends):
.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 块,但需要将相同的样式应用于两个块,你可以使用 extends 关联两个区域。
示例:
li.list > a {
// 列表样式
}
button.list-style {
&:extend(li.list > a); // 使用相同的列表样式
}