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) {}
// 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) {}
继承附加到选择器
附加到选择器的扩展看起来像一个普通的伪类,将选择器作为参数。 一个选择器可以包含多个扩展子句,但所有扩展都必须位于选择器的末尾。
- 在选择器之后扩展:
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 关键字。 在一个规则集中扩展的多个选择器:
.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
// body
}
继承内部规则集
可以使用 &:extend(selector)
语法将 Extend 放入规则集的主体中。 将 extend 放入主体是将其放入该规则集的每个选择器的快捷方式。
在主体内继承:
pre:hover,
.some-class {
&:extend(div pre);
}
与在每个选择器之后添加扩展完全相同:
pre:hover:extend(div pre),
.some-class:extend(div pre) {}
继承嵌套选择器
Extend 能够匹配嵌套的选择器。 关注 less:
例子:
.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;
}
精确匹配继承
默认情况下扩展会查找选择器之间的精确匹配。 选择器是否使用前导星并不重要。 两个第 n 个表达式具有相同的含义并不重要,它们需要具有相同的形式才能匹配。 唯一的例外是属性选择器中的引号,less 知道它们具有相同的含义并匹配它们。
例子:
.a.class,
.class.a,
.class > .a {
color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above
明星确实很重要。 选择器 *.class
和 .class
是等价的,但 extend 不会匹配它们:
*.class {
color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector
输出
*.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;
}
第 n 个表达式
第 N 种表达形式很重要。 第 N 个表达式 1n+3
和 n+3
是等价的,但扩展不会匹配它们:
: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;
}
你可以将这种操作模式视为本质上进行非破坏性搜索和替换。
继承选择器插值
Extend is not 能够匹配选择器和变量。 如果选择器包含变量,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;
}
作用域/继承内部 @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;
}
}
重复检测
目前没有重复检测。
例子:
.alert-info,
.widget {
/* declarations */
}
.alert:extend(.alert-info, .widget) {}
输出
.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;
}
减少 CSS 大小
Mixins 将所有属性复制到一个选择器中,这会导致不必要的重复。 因此,你可以使用 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;
}
示例(带扩展):
.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;
}
组合样式/更高级的混合
另一个用例是作为混入的替代方案 - 因为混入只能与简单的选择器一起使用,如果你有两个不同的 html 块,但需要对两者应用相同的样式,你可以使用 extends 来关联两个区域。
例子:
li.list > a {
// list styles
}
button.list-style {
&:extend(li.list > a); // use the same list styles
}