less Learning Notes 3 - Language Extension

Keywords: less Java Attribute Asterisk

I really don't know how to explain this part of extend. No wonder there is no translation in this part of less. Looking at a part of it, I feel like I can't get down to it. In many places, I feel that it's against each other and I can't explain clearly. So all the extends used in this article are in English. In the third reading, I suddenly found that extension has some sense of inheritance in Java, so I finally decided to translate extension into inheritance. A small partner who has a little knowledge of the simple concept of Java inheritance should easily understand the role and principle of extension. It also defines two selectors A and B by itself. The introduction of selectors A and B facilitates the interpretation and expression of the text. So it is better to remember the definition of selectors A and B first and then look at the following content. Of course, the best way is to learn together with the original English text. If you have a better understanding, you are welcome to put forward more. Some of the explanations are not clear enough, so try to reorganize them after all the study.

Extend

Extend can be understood as a less pseudo-Class in the form of A:extend(B). Its function is to use this pseudo-Class selector (A) to refer to the style rules of the qualified selector (B) for its own use, that is, A will have the style rules of B.

(A:extend (B)) below will use A to refer to the selector using extended pseudo-class, and B to refer to the selector matched by extended pseudo-class.

Published in v1.4.0

nav ul{
    &:extend(.inline);
    background: blue;
}

In the rule set above, the pseudo-Class extension will have. inline rules for nav ul. If the. inline selector does not exist, the declaration block of A selector will remain the same, but the extension statement will be invalid (because extension is not css)

nav ul{
    &:extend(.inline);
    background: blue;
}
.inline{
    color: red;
}

//Compile to:

nav ul{
    background: blue;
}
.inline,nav ul{
    color: red;
}

Notice the process of compiling the nav ul:extend(.inline) selector into navul - before compiling, the statement of the extended pseudoclass in the selector will be removed, and the remaining statements will remain the same. If the B selector in extension has no style, then extension will be removed during compilation (but extension may affect other selectors).

Extend syntax

Extend is either followed by a selector or placed in a rule. It looks like a pseudo-Class selector and has an optional parameter all

.a:extend(.b){ ... }
//The above code is compiled in accordance with the following code
.a{
    &:extend(.b);
}

.c:extend(.d all){
    //Includes all instances of ".d", such as ".x.d" or ".d.x"
}
.c:extend(.d){
    //With only one instance, the selector will only be compiled into an instance of ".d"
}

Extend can contain one or more classes, separated by commas

.e:extend(.f){...}
.e:extend(.g){...}
//The compilation results of the above and below code are the same.
.e:extend(.f,.g){...}

Extend usage

Extend is used like a common pseudo class. A selector can contain multiple Extends, but all Extends are placed at the end of the selector.

  • Extend is placed behind the selector: pre:hover:extend(div pre)
  • Spacing spaces between selector and Extend are allowed: pre: hover: extend (div pre)
  • Allow multiple Extend: pre: hover: extend (div pre): extend (.bucket tr) = pre: hover: extend (div pre,.Bucket tr);
  • The following usage is wrong: pre:hover:extend(div pre).nth-child(odd),Extend must be placed at the end.

When multiple selectors have the same style rule, each selector can have its own Extend keyword. The following is the case where multiple selectors have a rule:

.big-division,
.big-bag:extend(bag),
.big-bucket:extend(bucket){
  ...
}

Extend in Rules

Extend can place extends inside rules by using the syntax &: extend (selector). Placing Extend inside a rule is a simplified form in which Extend acts solely on each selector.

Inside:
pre:hover,.some-class{
    &:extend(div pre);
    ...
}

Equivalent to adding Extend separately in each selector:
pre:hover:extend(div pre),
.some-class:extend(div pre){...}

Use nested selectors in Extend

Extend allows the use of nested selectors (i.e. B selectors are nested selectors):

.bucket{
    tr{
        color: blue;
    }
}
.some-class:extend(.bucket tr){ ... }

//Compile to:
.bucket tr,
.some-class{
    color: blue;
}

Extend matches accurately

By default, Extend finds the selector that matches the B selector in all selectors, regardless of whether the B selector uses * (asterisk). If two descendant expressions (see the next paragraph in detail) correspond to the same element, matching is also done according to the format in the descendant expression. The only exception is the attribute selector, which less knows they mean the same thing and can match.

.a.class,.class.a,.class>.a{
    color: blue;
}
.test:extend(.class){ ... }//Not matching any of the selectors above

* It can be considered as an arbitrary selector. * Class and. class correspond to the same element array, but when Extend matches, they are not considered the same.

*.class{
    color: blue;
}
.test:extend(.class){ ... }//The selector *. class will not match

//Compile to:
*.class{
    color: blue;
}

The matching will be based on the order of pseudo-classes. The selectors link:hover:visited and link:visited:hover match the same element, but Extend distinguishes them.

link:visited:hover{
    color: blue;
}
.selector:extend(link:hover:visited){ ... }

//Compile to:
link:visited:hover{
    color: blue;
}

Descendant expression

Matching is done according to the form of the descendant expression. The descendant expressions 1n+3 and n+3 are equal, but Extend does not match them.

:nth-child(1n+3){
    color: blue;
}
.child:extend(:nth-child(n+3)){ ... }

//Compile to:
:nth-child(1n+3){
    color: blue;
}

The reference type of the property selector does not match. The following are all equal.

[title=identifier]{
    color: blue;
}
or
[title='identifier']{
    color: blue;
}
or
[title="identifier"]{
    color: blue;
}
.noQuote:extend([title=identifier]){}
.singleQuote:extend([title='identifier']){}
.doubleQuote:extend([title="identifier"]){}

//Compile to:
[title=indentifier],
.noQuote,
.singleQuote,
.doubleQuote{
    color: blue;
}
or
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}
or
[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

Extend"all"

When you specify that the last parameter of Extend is all, less will match some C selectors whose names contain the names of B selectors, similar to fuzzy matching. When matched to the selector, the C selector will be copied, and the part matched in the C selector name will be replaced by the name of the B selector to become a new selector.

.a.b.test,
.test.c{
    color: green;
}
.test{
    &:hover{
        color: red;
    }
}
.replace:extend(.test all){}

//Compiled into:

.a.b.test,
.test.c,
.a.b.replace,
.replace.c{
    color: green;
}
.test:hover,
.replace:hover{
    color: red;
}

You can think of this as a non-destructive search and match

Use Selector Interpolation with Extend in Extend

Extend cannot match the selector with variables, and if the selector contains variables, Extend will ignore them.
This is an undetermined feature, but it won't change easily. But extend can connect to the insertion selector (selector A containing variables).

Selectors containing variables will not be matched:

@var: .bucket;
@{var}{  //Insertion selector
    color: blue;
}
.some-class:extend(.bucket){}//Do nothing

Using variables in the target selector extension will not be matched:

.bucket{
    color: blue;
}
.some-class:extend(@{var}){}//Unmatched selector
@var: .bucket;

Both of the above will be compiled into:

.bucket{
    color: blue;
}

However, extension can be connected to an insertion selector:

.bucket{
    color: blue;
}
@{var}:extend(.bucket){}
@var: .test;

//Compile to:
.bucket,.test{
    color: blue;
}

Summary: A selector can contain variables, but B selector can not contain variables.

Extension in Scope /@media

Extended written in a media declaration can only match selectors in the same media:

@media print{
    .screenClass:extend(.selector){}
    .selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

//Compile to:

@meida print{
    .screenClass,.selector{
        color: black;
    }
}
.selector{
    color: red;
}
@media screen{
    .selector{
        color: blue;
    }
}

Extended written in a media declaration does not match the selector nested in the media declaration:

@media screen{
    .selectorClass:extend(.selector){}
    @media (min-width: 768px){
        .selector{
            color: blue;
        }    
    }
}

//Compile to:

@media screen and (min-width: 768px){
    .selector{
        color: blue;
    }
}

External extend s can match unlimited ranges, including selectors in internal nested media:

@media screen{
    .selector{
        color: blue;
    }
    @media (min-width: 768px){
        .selector{
            color: red;
        }
    }
}
.topLevel:extend(.selector){}
//Compile to:
@media screen{
    .selector,
    .topLevel{
        color: blue;
    }
}
@media screen and (min-width: 768px){
    .selector,
    .topLevel{
        color: red;
    }
}

Repeated detection

Now there is no duplicate detection function.

.alert,.widget{ ... }
.test:extend(.alert, .widget){}

Compile to:

.alert,.widget,.test,.test{ ... }

So you need to be careful not to use extends as selectors with the same rules when using extends

Extended usage

  • Typical usage

Typical usage is to avoid adding a class:

If you have a class animal
.animal{
    background-color: black;
    color: white;
}
//Then you want to get a subclass of animal by copying the background-color attribute, and HTML becomes like this:
<a class="animal bear">bear</a>
css Styles will become like this:
.animal{
    background-color: black;
    color: white;
}
.bear{
    background-color: grey;
}
//Otherwise, you can use extend in less, and your HTML will become very simple:
<a class="bear">bear</a>
less It will be:
.animal{
    background-color: black;
    color: white;
}
.bear{
    &:extend(.animal);
    background-color: grey;
}
  • Reduce css size

Mixin copies all attributes into a new selector, resulting in unnecessary duplication. So you can use extend instead of mixin to add attributes you want to use to the new selector, thereby reducing the css code.
Using mixin:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    .mine;
}
.test2{
    .mine;
}

//Compile to:
.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    color: #fff;
    font-size: 16px;
}
.test2{
    color: #fff;
    font-size: 16px;
}

Use extend:

.mine{
    color: #fff;
    font-size: 16px;
}
.test1{
    &:extend(.mine);
}
.test2{
    &:extend(.mine);
}

//Compile to:
.mine,
.test1,
.test2{
    color: #fff;
    font-size: 16px;
}
  • Combination Style/More Advanced Mixing

Another usage is as an alternative to mixins, because mixins can only be used in the archive selector. If there are two different blocks in HTML, but you need to apply the same style, then you can use extend s to link two block elements.

li.list >a{ ... }
button.list-style{
    &:extend(li.list>a);
}

Posted by n8w on Mon, 27 May 2019 13:17:40 -0700