I also have been pondering this use further since we encountered it in that question you referenced. While I cannot answer definitively that this is a "bug" use for &
(BoltClock seems to make a good argument that it is not a bug), I want to argue for the value of it (which argues it is not a bug from a logical standpoint).
However, before the logical argument, I did find another short, simple quote (in the "nested rules" section) that seems to indicate it is at least not unintended: "&
represents the current selector parent." That's it. As BoltClock argues, whether prepending or appending seems irrelevant. All that was intended was that it be a placeholder for that "selector parent" that is current up to that point. The fact that it is always mentioned in conjunction with the "nesting" use of the language implies it is designed to designate the full selector string of the nest up to the point of the nest that it resides within. How that string is used (to pre- or append) would seem up to the coder.
Now, you mention (and previously mentioned) that you "would never code this way," and yet I find myself seeing what appears to be a very valuable use for this. Consider the following argument.
The HTML Setup for the Illustration
Assume, for the sake of illustration, there is a dynamic setting of three possible classes ('light', 'medium', 'dark' themes) on the body
element that change the "look" of the site. We have
two columns, and some various types of links we want to style (textLink
, picLink
, textWithIconLink
) differently in each column for each theme.
<body class="light">
<div class="leftCol">
<a class="textLink"></a>
<a class="picLink"></a>
<a class="textWithIconLink"></a>
</div>
<div class="rightCol">
<a class="textLink"></a>
<a class="picLink"></a>
<a class="textWithIconLink"></a>
</div>
</body>
Now the questions to ask are, just looking at the links, of the two following methods, which...
- Is less code in LESS
- Best organzies the code in LESS
- Outputs less code in CSS
- Best organizes the outputted CSS
"Best" may be somewhat subjective. I'll let you weigh that evidence yourself from below.
Option #1 Typical Nesting
LESS (approx. 99 lines of code)
/*Light Color Theme */
.light {
.leftCol {
.textLink {
color: fooL1;
&:hover { color: barL1;}
}
.picLink {
background-image: url(/fooL1.jpg);
&:hover { background-image: url(/barL1.jpg);}
}
.textWithIconLink {
color: fooL2;
background-image: url(/fooL2.jpg);
&:hover { color: barL2; background-image: url(/barL2.jpg);}
}
}
.rightCol {
.textLink {
color: fooL3;
&:hover { color: barL3;}
}
.picLink {
background-image: url(/fooL3.jpg);
&:hover { background-image: url(/barL3.jpg);}
}
.textWithIconLink {
color: fooL4;
background-image: url(/fooL4.jpg);
&:hover { color: barL4; background-image: url(/barL4.jpg);}
}
}
}
/*Medium Color Theme */
.medium {
.leftCol {
.textLink {
color: fooM1;
&:hover { color: barM1;}
}
.picLink {
background-image: url(/fooM1.jpg);
&:hover { background-image: url(/barM1.jpg);}
}
.textWithIconLink {
color: fooM2;
background-image: url(/fooM2.jpg);
&:hover { color: barM2; background-image: url(/barM2.jpg);}
}
}
.rightCol {
.textLink {
color: fooM3;
&:hover { color: barM3;}
}
.picLink {
background-image: url(/fooM3.jpg);
&:hover { background-image: url(/barM3.jpg);}
}
.textWithIconLink {
color: fooM4;
background-image: url(/fooM4.jpg);
&:hover { color: barM4; background-image: url(/barM4.jpg);}
}
}
}
/*Dark Color Theme */
.dark {
.leftCol {
.textLink {
color: fooD1;
&:hover { color: barD1;}
}
.picLink {
background-image: url(/fooD1.jpg);
&:hover { background-image: url(/barD1.jpg);}
}
.textWithIconLink {
color: fooD2;
background-image: url(/fooD2.jpg);
&:hover { color: barD2; background-image: url(/barD2.jpg);}
}
}
.rightCol {
.textLink {
color: fooD3;
&:hover { color: barD3;}
}
.picLink {
background-image: url(/fooD3.jpg);
&:hover { background-image: url(/barD3.jpg);}
}
.textWithIconLink {
color: fooD4;
background-image: url(/fooD4.jpg);
&:hover { color: barD4; background-image: url(/barD4.jpg);}
}
}
}
CSS Output (approx. 87 lines of output, organized by theme of course)
/*Light Color Theme */
.light .leftCol .textLink { color:fooL1; }
.light .leftCol .textLink:hover { color:barL1; }
.light .leftCol .picLink { background-image:url(/fooL1.jpg); }
.light .leftCol .picLink:hover { background-image:url(/barL1.jpg); }
.light .leftCol .textWithIconLink {
color:fooL2;
background-image:url(/fooL2.jpg);
}
.light .leftCol .textWithIconLink:hover {
color:barL2;
background-image:url(/barL2.jpg);
}
.light .rightCol .textLink { color:fooL3; }
.light .rightCol .textLink:hover { color:barL3; }
.light .rightCol .picLink { background-image:url(/fooL3.jpg); }
.light .rightCol .picLink:hover { background-image:url(/barL3.jpg); }
.light .rightCol .textWithIconLink {
color:fooL4;
background-image:url(/fooL4.jpg);
}
.light .rightCol .textWithIconLink:hover {
color:barL4;
background-image:url(/barL4.jpg);
}
/*Medium Color Theme */
.medium .leftCol .textLink { color:fooM1; }
.medium .leftCol .textLink:hover { color:barM1; }
.medium .leftCol .picLink { background-image:url(/fooM1.jpg); }
.medium .leftCol .picLink:hover { background-image:url(/barM1.jpg); }
.medium .leftCol .textWithIconLink {
color:fooM2;
background-image:url(/fooM2.jpg);
}
.medium .leftCol .textWithIconLink:hover {
color:barM2;
background-image:url(/barM2.jpg);
}
.medium .rightCol .textLink { color:fooM3; }
.medium .rightCol .textLink:hover { color:barM3; }
.medium .rightCol .picLink { background-image:url(/fooM3.jpg); }
.medium .rightCol .picLink:hover { background-image:url(/barM3.jpg); }
.medium .rightCol .textWithIconLink {
color:fooM4;
background-image:url(/fooM4.jpg);
}
.medium .rightCol .textWithIconLink:hover {
color:barM4;
background-image:url(/barM4.jpg);
}
/*Dark Color Theme */
.dark .leftCol .textLink { color:fooD1; }
.dark .leftCol .textLink:hover { color:barD1; }
.dark .leftCol .picLink { background-image:url(/fooD1.jpg); }
.dark .leftCol .picLink:hover { background-image:url(/barD1.jpg); }
.dark .leftCol .textWithIconLink {
color:fooD2;
background-image:url(/fooD2.jpg);
}
.dark .leftCol .textWithIconLink:hover {
color:barD2;
background-image:url(/barD2.jpg);
}
.dark .rightCol .textLink { color:fooD3; }
.dark .rightCol .textLink:hover { color:barD3; }
.dark .rightCol .picLink { background-image:url(/fooD3.jpg); }
.dark .rightCol .picLink:hover { background-image:url(/barD3.jpg); }
.dark .rightCol .textWithIconLink {
color:fooD4;
background-image:url(/fooD4.jpg);
}
.dark .rightCol .textWithIconLink:hover {
color:barD4;
background-image:url(/barD4.jpg);
}
Option #2 End Target Grouping
I've named it "End Target Grouping," because that's really how I see using the &
in this other way of adding parent selectors. One is now coding based off the final end target element that is actually being styled.
LESS (approx. 88 lines of code)
/*Links */
/*Text Links*/
.textLink {
.light .leftCol & {
color: fooL1;
&:hover { color: barL1;}
}
.light .rightCol & {
color: fooL3;
&:hover { color: barL3;}
}
.medium .leftCol & {
color: fooM1;
&:hover { color: barM1;}
}
.medium .rightCol & {
color: fooM3;
&:hover { color: barM3;}
}
.dark .leftCol & {
color: fooD1;
&:hover { color: barD1;}
}
.dark .rightCol & {
color: fooD3;
&:hover { color: barD3;}
}
}
/*Picture Links */
.picLink {
.light .leftCol & {
background-image: url(/fooL1.jpg);
&:hover { background-image: url(/barL1.jpg);}
}
.light .rightCol & {
background-image: url(/fooL3.jpg);
&:hover { background-image: url(/barL3.jpg);}
}
.medium .leftCol & {
background-image: url(/fooM1.jpg);
&:hover { background-image: url(/barM1.jpg);}
}
.medium .rightCol & {
background-image: url(/fooM3.jpg);
&:hover { background-image: url(/barM3.jpg);}
}
.dark .leftCol & {
background-image: url(/fooD1.jpg);
&:hover { background-image: url(/barD1.jpg);}
}
.dark .rightCol & {
background-image: url(/fooD3.jpg);
&:hover { background-image: url(/barD3.jpg);}
}
}
/*Text with Icon Links */
.textWithIconLink {
.light .leftCol & {
color: fooL2;
background-image: url(/fooL1.jpg);
&:hover { color: barL2; background-image: url(/barL1.jpg);}
}
.light .rightCol & {
color: fooL4;
background-image: url(/fooL3.jpg);
&:hover { color: barL4; background-image: url(/barL3.jpg);}
}
.medium .leftCol & {
color: fooM2;
background-image: url(/fooM1.jpg);
&:hover { color: barM2; background-image: url(/barM1.jpg);}
}
.medium .rightCol & {
color: fooM4;
background-image: url(/fooM3.jpg);
&:hover { color: barM4; background-image: url(/barM3.jpg);}
}
.dark .leftCol & {
color: fooD2;
background-image: url(/fooD1.jpg);
&:hover { color: barD2; background-image: url(/barD1.jpg);}
}
.dark .rightCol & {
color: fooD4;
background-image: url(/fooD3.jpg);
&:hover { color: barD4; background-image: url(/barD3.jpg);}
}
}
CSS (approx. 88 lines of output [due to one extra comment], organized by end target element; but notice, there is still a suborganization by theme because of the class structure)
/*Links*/
/*Text Links*/
.light .leftCol .textLink { color:fooL1; }
.light .leftCol .textLink:hover { color:barL1; }
.light .rightCol .textLink { color:fooL3; }
.light .r