Reputation: 125
I have some problems with Less' extend
function. In some cases it doesn't work and I can't figure out why. There is a piece of problematic code:
.page-header {
.bar:extend(.fixedElement) { // it works
...
}
.menu:extend(.fixedElement) { // it works
...
}
// some other stuff
.menu-list {
...
.btnStyle {
padding: 18px 20px;
min-height: 60px;
width: 100%;
display: block;
border-bottom: 1px solid @light2;
}
.linkStyle:extend(.btnStyle) { // doesn't work
//.btnStyle;
background-color: @light1;
.remCalc(14);
&:active {
background-color: transparent;
}
}
.chosen {
background-color: transparent;
&:after {
color: @primaryColor;
}
}
...
.level-2 {
& > ul {
a:extend(.linkStyle) { // doesn't work
//.linkStyle;
}
}
}
.level-3 {
...
& > ul > li {
.btn-menu {
&.shown:extend(.chosen) { // doesn't work
//.chosen;
}
}
& > a:extend(.linkStyle) { // doesn't work
//.linkStyle;
}
}
.selected {
.btn-menu:extend(.chosen) { // doesn't work
//.chosen;
}
}
}
.btn-menu:extend(.btnStyle) { // doesn't work
//.btnStyle;
...
}
}
}
And:
.gradientBg {
background: rgb(200, 200, 200);
background: -webkit-linear-gradient(295deg, rgb(200, 200, 200) 10%, rgb(255, 255, 255) 90%);
background: -o-linear-gradient(295deg, rgb(200, 200, 200) 10%, rgb(255, 255, 255) 90%);
background: linear-gradient(25deg, rgb(200, 200, 200) 10%, rgb(255, 255, 255) 90%);
border: 1px solid @light2;
}
.gr-box, .btn-1 {
&:extend(.gradientBg); //it works
}
Elements extended by .fixedElement
or .gradientBg
compile to CSS normally, but not these with .btnStyle
, .linkStyle
and .chosen
(they just aren't in CSS; now it works only by every time placed mixins). There aren't any errors during compilation.
I use Brackets 1.3 with Less Autocompile 1.1.9 extension. What am I doing wrong?
Upvotes: 2
Views: 461
Reputation: 89780
Quoting Less Website: emphasis is mine
Extend by default looks for exact match between selectors. It does matter whether selector uses leading star or not. It does not matter that two nth-expressions have the same meaning, they need to have to same form in order to be matched. The only exception are quotes in attribute selector, less knows they have the same meaning and matches them.
The following would work because the parameter to the extend
function exactly matches another selector that is already defined. (Note: I have removed some properties to keep it simple.)
.gradientBg { background: rgb(200, 200, 200); }
.gr-box, .btn-1 { &:extend(.gradientBg); }
But the below would not work because the compiled selector path of the nested selector would be .parent .gradientBg
and the parameter provided to the extend
function is not an exact match.
.parent{
.gradientBg { background: rgb(200, 200, 200); }
}
.gr-box, .btn-1 { &:extend(.gradientBg); }
Less compiler would not even throw an error in the above scenario because it fails silently when there is no match.
When using extend
feature to extend nested selectors, an exactly matching selector (full selector path) should be provided (or) the all
keyword should be used.
The below would work as the full matching selector path is provided to the extend
function.
.parent{
.gradientBg { background: rgb(200, 200, 200); }
}
.gr-box, .btn-1 { &:extend(.parent .gradientBg); }
Or, depending on your needs even this would work because the all
keyword is used.
.parent{
.gradientBg { background: rgb(200, 200, 200); }
}
.gr-box, .btn-1 { &:extend(.gradientBg all); }
But note how the output selector has the structure .parent .gr-box
and .parent .btn-1
. This is because Less replaces only the matched part of the selector with the new selector. In .parent .gradientBg
(original selector), the matched part (provided as parameter to extend
) is only .gradientBg
and hence the output selector after extend
would be .parent .gr-box
.
Here is what the Less website says about extend "all": emphasis is mine
When you specify the all keyword last in an extend argument it tells Less to match that selector as part of another selector. The selector will be copied and the matched part of the selector only will then be replaced with the extend, making a new selector.
Another thing that should also be noted when using all
keyword is that, Less would extend properties of all selectors that have a matching part. So, for example if we consider the below Less code.
.parent{
.gradientBg { background: rgb(200, 200, 200); }
}
.parent2{
.gradientBg{ color: red; }
}
.gr-box, .btn-1 { &:extend(.gradientBg all); }
the output would be as follows because .gradientBg
selector is used both within .parent
and .parent2
.
.parent .gradientBg, .parent .gr-box, .parent .btn-1 {
background: #c8c8c8;
}
.parent2 .gradientBg, .parent2 .gr-box, .parent2 .btn-1 {
color: red;
}
Upvotes: 1