Article directory
1 Overview
Extend is a Less pseudo-class that extends the rules of the current hierarchy.
nav ul {
&:extend(.inline);
background: blue;
}
In the rule set above, :extend
the selector .inline
will apply the rules of to the "extended selector" ie nav ul
. At the same time, nav ul
the rules themselves will remain as they are.
As follows:
nav ul {
&:extend(.inline);
background: blue;
}
.inline {
color: red;
}
The generated result is as follows:
nav ul {
background: blue;
}
.inline,
nav ul {
color: red;
}
2. Grammar
extend
Looks like a pseudo-class that can be attached directly to a selector or used in a ruleset, and also supports an optional keyword all
.
Examples are as follows:
// 方式 1:直接附加在选择器上
.a:extend(.b) {
color: red;
}
// 方式 2:在规则集中使用
.a {
&:extend(.b);
color: red;
}
// 上面两种方式效果完全一致
all
The use of keywords
.c:extend(.d all) {
// 扩展 `.d` 的所有相关选择器,例如 `.x.d` 或 `.d.x`
color: red;
}
.c:extend(.d) {
// 仅扩展选择器 `.d`
color: red;
}
Of course, it can also contain one or more classes to be extended, separated by commas , examples are as follows:
.e:extend(.f) {
color: red;
}
.e:extend(.g) {
color: red;
}
// 和上面两个得到的结果完全一致
.e:extend(.f, .g) {
color: red;
}
3. Attach to the selector
Extend attached to a selector looks like a normal pseudo-class with the selector as a parameter, while a selector can contain multiple extend clauses, but all extend must be at the end of the selector.
- After the selector:
pre:hover:extend(div pre)
- There can be spaces between the selector and the extension:
pre:hover :extend(div-pre)
- Multiple extensions are allowed:
pre:hover:extend(div pre):extend(.bucket tr)
, in fact, this has exactly the samepre:hover:extend(div pre, .bucket tr)
effect - The extension must come last, so this is not allowed:
pre:hover:extend(div pre).nth-child(odd)
If the ruleset contains multiple selectors, any of them can be extended, examples are as follows:
// 附加到选择器
.bag {
border: 1px solid;
}
.bucket {
margin: 10px;
}
.show {
display: block;
}
.big-division:extend(.bag),
.big-bag:extend(.bag, .show),
.big-bucket:extend(.bucket):extend(.show) {
color: red;
}
The generated result is as follows:
.bag,
.big-division,
.big-bag {
border: 1px solid;
}
.bucket,
.big-bucket {
margin: 10px;
}
.show,
.big-bag,
.big-bucket {
display: block;
}
.big-division,
.big-bag,
.big-bucket {
color: red;
}
4. Use in rule sets
In addition to being attached to the selector, it can also be used directly in the rule set. The parent selector is also supported, such as: , &:extend(selector)
and after being placed in the rule set, all selectors corresponding to the rule set will be expanded (a shortcut Way).
.ru {
top: 10;
}
pre:hover,
.some-class {
&:extend(.ru);
left: 20;
}
// 和上面写法完全一致
pre:hover:extend(.ru),
.some-class:extend(.ru) {
left: 20;
}
The generated result is as follows:
.ru,
pre:hover,
.some-class {
top: 10;
}
pre:hover,
.some-class {
left: 20;
}
5. Expand nested selectors
Extend can match nested selectors. The following less:
.bucket {
tr { // 嵌套的选择器
color: blue;
}
}
.some-class:extend(.bucket tr) {
border: 1px;
}
The generated result is as follows:
.bucket tr,
.some-class {
color: blue;
}
.some-class {
border: 1px;
}
Also, the extension ends up using css instead of the original less.
.bucket {
tr & {
color: blue;
}
}
.some-class:extend(tr .bucket) {
border: 1px;
}
The generated result is as follows:
tr .bucket,
.some-class {
color: blue;
}
.some-class {
border: 1px;
}
6. Exact match
By default, :extend(selector)
the selector will be matched exactly, that is, it needs to be exactly the same to match.
.a.class,
.class.a,
.class > .a {
color: blue;
}
.test {
border: 1px;
}
Although in the selector, *.class
and are .class
equal , extend
will not match:
*.class {
color: blue;
}
// 匹配不到任何选择器
.noStar:extend(.class) {
border: 1px;
}
The order of the pseudo-classes is also important. The selectors link:hover:visited
and link:visited:hover
do match the same set of elements, but extend
will not match:
link:hover:visited {
color: blue;
}
// 匹配不到任何选择器
.selector:extend(link:visited:hover) {
border: 1px;
}
7. nth
Expression
In selectors, the expressions 1n+3
and n+3
are equivalent, extend
but will not match them:
:nth-child(1n+3) {
color: blue;
}
// 匹配不到任何选择器
.child:extend(:nth-child(n+3)) {}
8. Attribute Selector
Interestingly, the type of quotes in the attribute selector is irrelevant
[title='identifier'] {
color: blue;
}
[title='identifier'] {
color: blue;
}
[title='identifier'] {
color: blue;
}
.noQuote:extend([title='identifier']) {
border: 1px;
}
.singleQuote:extend([title='identifier']) {
border: 1px;
}
.doubleQuote:extend([title='identifier']) {
border: 1px;
}
The generated result is as follows:
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
.noQuote {
border: 1px;
}
.singleQuote {
border: 1px;
}
.doubleQuote {
border: 1px;
}
9. all
Keywords
When specifying all
the keyword , it tells Less to match that selector as part of another selector. Matched parts are replaced to generate a new selector. Examples are as follows:
a.b.test,
.test.c {
color: orange;
}
.test {
&:hover {
color: green;
}
}
.replacement:extend(.test all) {
border: 1px;
}
The generated result is as follows:
a.b.test,
.test.c,
a.b.replacement,
.replacement.c {
color: orange;
}
.test:hover,
.replacement:hover {
color: green;
}
.replacement {
border: 1px;
}
10. Variables
extend
Will not match any variable, if the selector contains a variable, it will be ignored directly.
@variable: .bucket;
@{variable} {
color: blue;
}
// 匹配不到任何选择器
.some-class:extend(.bucket) {
border: 1px;
}
.bucket {
color: blue;
}
@variable: .bucket;
// 匹配不到任何选择器
.some-class:extend(@{variable}) {
border: 1px;
}
The official website points out: When the selector uses variables, it can be matched normally. But after I experimented, I found that it was impossible, and I left it for further study here.
11. @media
Use in:extend
@media
The in matches :extend
only @media
the selectors in the current .
@media print {
// 成功匹配
.screenClass:extend(.selector) {
left: 1;
}
// 同一个 media 中的选择器,匹配
.selector {
color: black;
}
}
// 规则集在顶层,内层 extend 会忽略
.selector {
color: red;
}
@media screen {
// 规则集在另一 media 中,仅会被当前 media 中的 extend 匹配
.selector {
color: blue;
}
}
The generated result is as follows:
@media print {
.screenClass {
left: 1;
}
.selector,
.screenClass {
color: black;
}
}
.selector {
color: red;
}
@media screen {
.selector {
color: blue;
}
}
Note that selectors within nested @media
within the same will also not match@media
@media screen {
// 匹配不到任何选择器
.screenClass:extend(.selector) {
left: 1;
}
@media (min-width: 1023px) {
// 选择器在嵌套的 media 中,无法匹配
.selector {
color: blue;
}
}
}
The top-level extend will match all levels of selectors
@media screen {
.selector-t {
color: blue;
}
@media (min-width: 1023px) {
.selector-t {
color: blue;
}
}
}
// 顶层的 extend 会去匹配所有层级的选择器
.topLevel:extend(.selector-t) {
left: 1;
}
The generated result is as follows:
@media screen {
.selector-t,
.topLevel {
color: blue;
}
}
@media screen and (min-width: 1023px) {
.selector-t,
.topLevel {
color: blue;
}
}
.topLevel {
left: 1;
}
12. Duplicate detection
Currently no duplicate detection is done as follows:
.alert-info,
.widget {
left: 1;
}
.alert:extend(.alert-info, .widget) {
top: 2;
}
The generated result is as follows:
.alert-info,
.widget,
.alert,
.alert {
left: 1;
}
.alert {
top: 2;
}
13. Example of use
13.1 Classic use cases
A typical use case is to avoid duplication of rulesets.
for example:
.animal {
background-color: black;
color: white;
}
If you want to override the background color animal
of , there are two ways:
The first one: change the HTML and write two classes
<a class="animal bear">熊</a>
.animal {
background-color: black;
color: white;
}
.bear {
background-color: brown;
}
The second: use extend
<a class="bear">熊</a>
.animal {
background-color: black;
color: white;
}
.bear {
&:extend(.animal);
background-color: brown;
}
13.2 Reduce CSS size
Using mixins is very convenient, but mixins will copy all the properties into the selector, which may cause unnecessary duplication.
Therefore, you can use extends
to replace the mixin to move the selector to the property you want to use, thereby reducing the generated CSS.
Let's see an example comparison:
- use mixins
.my-inline-block() {
display: inline-block;
font-size: 0;
}
.thing1 {
.my-inline-block;
}
.thing2 {
.my-inline-block;
}
The generated result is as follows:
.thing1 {
display: inline-block;
font-size: 0;
}
.thing2 {
display: inline-block;
font-size: 0;
}
- use extends
.my-inline-block {
display: inline-block;
font-size: 0;
}
.thing1 {
&:extend(.my-inline-block);
}
.thing2 {
&:extend(.my-inline-block);
}
The generated result is as follows:
.my-inline-block,
.thing1,
.thing2 {
display: inline-block;
font-size: 0;
}
13.3 Style composition
A more advanced usage is when the selector is more complex (mixin can no longer be implemented at this time, because mixin can only be used with simple selectors), and the rule set needs to be reused, then it can be used extends
.
li.list > a {
line-height: 20px;
}
button.list-style {
&:extend(li.list > a);
}
The generated result is as follows:
li.list > a,
button.list-style {
line-height: 20px;
}