LESS - target div and anchor within - less

How can I achieve .div, .div a{color: #fff;} in LESS syntax?
.div{
&a{ color: #fff;}
}
Above code won't work.
Below code works!
.div {
&, a {color: #fff}
}

Related

Eliminate need for & inside less wrapper to prepend to selector without adding space

Here is my code:
.html-default-tag-color {color: #99cdff}
.html_specific-tag-colors() {
.cm-m-xml.cm-tag- {
&img {color: #909}
&table, &th, &td, &tr {color: #099}
&form {color: orange; font-weight: bold}
}
}
... Above used latter in the following mixin ...
Only interested in eliminating "&" in ABOVE
#makeImportant()
{
.HTML {
&.cm-m-xml.cm-tag {.html-default-tag-color};
.html_specific-tag-colors();
}
// important required to override usage in code outside my control
} & { #makeImportant() !important}
Must be done in less -- runs inside Dreamweaver configured less environment.

How can I use ampersand-prefixed selector as mixin? [duplicate]

In Less, I can write:
.outer {
.inner {
color: red;
}
}
.test {
.outer .inner;
}
But when I write:
.outer {
&-inner {
color: red;
}
}
.test {
.outer-inner;
}
When I remove the .test, the .outer-inner output properly, but when I add it back, the compiler says
.outer-inner is undefined.
Is there anyway to re-use the styles of .outer-inner?
Calling a mixin whose selector is formed by concatenation is currently not possible with Less. However the same is possible for selectors formed at compilation time using interpolation (also referred to as dynamically formed selectors).
The below (interpolated/dynamically formed selector) would work fine.
#selector: .box;
#{selector}{
color: red;
.child{
color:blue;
}
}
.demo{
.box; /* will create both parent & child */
}
.container{
    &.box{
    background: black;
}
}
.demo2{
    .container.box;
}
whereas, the following example will not work.
.container{
&-box{
color: blue;
}
}
.demo2{
.container-box; /* this will not work */
}
Currently, one work-around to the scenario in question is to create two separate Less files.
In the first file (test.less) add the below code and compile it into a CSS file.
.outer {
&-inner {
color: red;
}
}
In the second file, import the CSS created from the first file with the (less) directive and then call/re-use the mixin.
#import (less) "test.css";
.test {
.outer-inner;
}
Note: As mentioned in comments by seven-phases-max, this issue is similar to this item. However both these issues are not the same as extend will not work with both interpolated selector (dynamically formed) and concatenated selector.
Option 2: Another option would be to write a dummy mixin or a separate detached ruleset with common properties and make use of it like below.
#dummy: {color: red}; // detached ruleset
.outer{
&-inner{
#dummy();
}
}
.test{
#dummy();
}
or
.dummy() {color: blue}; // dummy mixin and would produce no extra selector in output as it has parentheses.
.outer{
&-inner{
.dummy;
}
}
.test{
.dummy;
}

LESS Variable Interpolation

I'm trying to simplify my CSS even further than I already have with LESS by using functions and variable interpolation. I was completely unaware of variable interpolation until I took a look at Hover.css' less files which is no surprise as to why I'm screwing up now.
I'm working on Reddit to make a flair system and I am encountering problems using variable interpolation.
I am currently using the below as a test:
.flair.flair-one { color: red; }
.flair.flair-two { color: green; }
.flair.flair-three { color: blue; }
.custom(#a; #b; #c) {
&::before { .flair.flair-#{a}; }
.flair.flair-#{b};
&::after { .flair.flair-#{c}; }
}
.this-flair {
.custom(one; two; three);
}
That's the basic structure of what I'm doing. While testing in online compilers, .this-flair isn't working.
Is someone able to tell me what I can do to resolve this? I'm looking through the LESS functions and it appears as though this is the correct way to do it.
As mentioned in comments above you can't interpolate either mixin or function calls. In a quick glance, parametric mixins (with pattern matching) are what you actually need to use for such snippets:
.flair-flair(one) {color: red}
.flair-flair(two) {color: green}
.flair-flair(three) {color: blue}
.custom(#a, #b, #c) {
.flair-flair(#b);
&::before {.flair-flair(#a)}
&::after {.flair-flair(#c)}
}
.this-flair {
.custom(one, two, three);
}

How to re-use a mixin whose selector is formed using concatenation

In Less, I can write:
.outer {
.inner {
color: red;
}
}
.test {
.outer .inner;
}
But when I write:
.outer {
&-inner {
color: red;
}
}
.test {
.outer-inner;
}
When I remove the .test, the .outer-inner output properly, but when I add it back, the compiler says
.outer-inner is undefined.
Is there anyway to re-use the styles of .outer-inner?
Calling a mixin whose selector is formed by concatenation is currently not possible with Less. However the same is possible for selectors formed at compilation time using interpolation (also referred to as dynamically formed selectors).
The below (interpolated/dynamically formed selector) would work fine.
#selector: .box;
#{selector}{
color: red;
.child{
color:blue;
}
}
.demo{
.box; /* will create both parent & child */
}
.container{
    &.box{
    background: black;
}
}
.demo2{
    .container.box;
}
whereas, the following example will not work.
.container{
&-box{
color: blue;
}
}
.demo2{
.container-box; /* this will not work */
}
Currently, one work-around to the scenario in question is to create two separate Less files.
In the first file (test.less) add the below code and compile it into a CSS file.
.outer {
&-inner {
color: red;
}
}
In the second file, import the CSS created from the first file with the (less) directive and then call/re-use the mixin.
#import (less) "test.css";
.test {
.outer-inner;
}
Note: As mentioned in comments by seven-phases-max, this issue is similar to this item. However both these issues are not the same as extend will not work with both interpolated selector (dynamically formed) and concatenated selector.
Option 2: Another option would be to write a dummy mixin or a separate detached ruleset with common properties and make use of it like below.
#dummy: {color: red}; // detached ruleset
.outer{
&-inner{
#dummy();
}
}
.test{
#dummy();
}
or
.dummy() {color: blue}; // dummy mixin and would produce no extra selector in output as it has parentheses.
.outer{
&-inner{
.dummy;
}
}
.test{
.dummy;
}

Referencing parent with multiple levels of nesting in LESS

I have the following LESS:
.container {
.column, .columns {
.one& {
width: 40px;
}
}
}
When I compile I'm getting the following for my CSS:
.one.container .column,
.one.container .columns {
width: 40px;
}
But I expected to get:
.container .one.column,
.container .one.columns {
width: 40px;
}
It appears the parent operator (&) in LESS is actually referencing what I'd expect to be the grandparent. Am I nesting things properly? The docs don't show any examples of nesting more than one level deep. Can I achieve my desired output with nesting?
I'm using lessc 1.3.3 installed via npm.
It's important to think of & as more of a "parentage" combinator, rather than a "parent" combinator. That is, it takes the whole nested string of selectors up to that point (no matter how many levels deep) and acts as the equivalent of a string replacement holder. So with a reduced version of your example...
.container {
.column {
.one& {
width: 40px;
}
}
}
...the selector string at that level is .container .column. This is what is "replaced" in the position of the &, so when you concatenate to the beginning as you do above, it gets attached at the beginning of the whole selector string and you end up with your:
.one.container .column {width 40px;}
But if you concatenate from the end (no space between & and .) then...
.container {
.column {
&.one {
width: 40px;
}
}
}
...becomes:
.container .column.one {width 40px;}
This last one is really the class combination you want, though just not quite in the same order you were hoping for. But order does not matter to the browser, .one.column or .column.one are the same, it just means an element that has both individual classes applied to it like so:
<div class="column one"></div>
<div class="one column"></div>
Both of those are equivalent, and either .one.column or .column.one as a selector is going to select both elements, because both elements have both classes.
If order is absolutely vital to you (you just must have your generated CSS be as you are seeking), then you would need to do a bit of repetition like this:
.container {
.column {
...generic column code here...
}
.one {
&.column {
width: 40px;
...any other code dependent on combination of .one.column here...
}
}
}