Less immediate parent selector without root selector - less

This LESS:
.parent {
.child {
h1& {
color: red;
}
}
}
Compiles to:
h1.parent .child {color:red};
What I need is:
.parent h1.child {color:red};
Suggestion appreciated.
My question is similar to the question Less Immediate Parent Selector but not quite the same. As the selector is composed from the element and class name. The question is about how to qualify the class name with its element without affecting the root selector.

This will work for this specific example. Although I appreciate it doesn't answer your general question.
.parent {
h1 {
&.child {
color: red;
}
}
}

Related

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: how to convert a list of called mixins to a for loop with a unique call

I crated many mixins to generate different kinds of classes for various purposes. Specifically I have to use a unique colorizer set using the standard bootstrap variable name, such as (only an example):
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
#type-default: #000;
#type-warning: #0f0;
#type-danger: #0ff;
Actually I created my mixins in the following form, with a "mother" as prefix to which I attached various suffixes
.text
{
&-primary { .color_text(#type-primary); }
&-success { .color_text(#type-success); }
&-info { .color_text(#type-info); }
&-default { .color_text(#type-default); }
&-warning { .color_text(#type-warning); }
&-danger { .color_text(#type-danger); }
}
After this, I can then create the final called mixin such as (so simple because it's only an example)
.color_text (#color)
{
color:#color;
}
I woud like to automate and optimize .text mixin to avoid many repeated rows, I think with a for loop. How could be possible?
Final results should be (in this case)
.text-primary {
color: #fff;
}
.text-success {
color: #f00;
}
.text-info {
color: #ff0;
}
.text-default {
color: #000;
}
.text-warning {
color: #0f0;
}
.text-danger {
color: #0ff;
}
In PSEUDO-CODE something like this could be ideal
#type-primary: #fff;
#type-success: #f00;
#type-info: #ff0;
.createContextClass("classNamePrefix",{#type-primary,#type-success,#type-info},mixinToBeCalled);
// Another call could be
.createContextClass("otherClassNamePrefix",{#type-primary,#type-success},otherMixinToBeCalled);
where, in relation to my original code, classNamePrefix should be the name of first part of final CSS class, then is passed an array with all kind of suffix that I wish in final CSS code, and mixinToBeCalled is the mixin that creates all css rules for final .text-primary, .text-success, .text-info.
For the moment, following Seven-Phases-Max' suggestion, I improved his solution in the following way

Defining a:focus selector

I have the below HTML structure.
<html>
<a class="customcssstyle" href="#'>Link</a>
</html>
Now I need to have a style, such that on focus on the link , it should appear in red.
For that in normal CSS, we write it as:
a.customcssstyle:focus
{
color:red;
}
May I know how we can write it using Less CSS.
CSS syntax is valid in less. But also you can do something like:
.customcssstyle
{
a {
&:focus {
color:red;
}
}
}
First of all: a is an inline element and should be inside a block element (not html). Then in css for calling a class you need a dot, e.g. .customcssstyle and not the value of the attribute class only. At least to select the focus state of this element just call the class with the pseudo selector :focus.
.customcssstyle:focus {
color: red;
}

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...
}
}
}