0
votes

I have been provided with less files containing mixins and styles for LTR as well as RTL content on a webpage. The webpage shows only one type of content at a time, either LTR or RTL. Although I could have separate css for LTR and RTL styles and control which file is being loaded, I want them both to be in the same css file.

The mixins are controlled with an @lang variable as follows:

// file: mixins.less
.myMixin() when (@lang = ltr){
    float: left;
}

.myMixin() when (@lang = rtl){
    float: right;
}

The mixins are being used in a styles.less file:

// file : styles.less
.myDiv{
    .myMixin();
}

I want to output both the ltr and rtl styles in the same css by importing the styles.less file twice but with different value of the @lang variable for each import :

@import "mixin.less";

@lang: ltr;
@import (multiple) "styles.less";

@lang: rtl;
html{
    [dir=rtl] & {
        @import (multiple) "styles.less";
    }   
}

But this is obviously not working due to LESS's lazy loading of variables.

Expected output in the css file:

.myDiv {
  float:left;
}
[dir=rtl] html .myDiv {
  float:right;
}

Actual output in the css file:

.myDiv {
  float:right;
}
[dir=rtl] html .myDiv {
  float:right;
}

I do not have the liberty to modify the mixins.less file or the styles.less file. How would I go about achieving both ltr and rtl styles in the same css file?

Thanks in advance.


Link for @seven-phases-max : Example

1
Isolate the scope of either variable. Example. For your example above the simplest way is to move @lang: rtl; right into html {} block.seven-phases-max
@seven-phases-max Unnamed namespaces work fine as long as we are directly using the variable. But don't work with mixins. Please check this : (link too long hence added to the bottom of the question)jahackbeth
Put the mixin into the same scope (for example by importing it together with "style.less").seven-phases-max
@seven-phases-max Brilliant! It works. How do I credit you for this? Can you add your comments as an answer? It might help others looking for something similar.jahackbeth
Yes, please add an answer (honestly I'm too lazy to do it myself).seven-phases-max

1 Answers

1
votes

Posting the answer myself based on seven-phases-max's comments.

Previously the scope of the @lang variable was the same throughout and when lazy-loading kicked in, @lang was allocated the most recent value given to it. We need to isolate the scope when changing the value of @lang by adding an unnamed namespace and then importing the mixins and styles in the same scope which will produce the desired result.

Below is the code snippet:

@lang: ltr;
@import "mixin.less"; // value of @lang is ltr
@import "styles.less"; // creates ltr styles

& {
    @lang: rtl;
    html{
        [dir=rtl] & {
            @import (multiple) "mixin.less"; // value of @lang is rtl
            @import (multiple) "styles.less"; // creates rtl styles
        }   
    }
}

Output is as expected:

.myDiv {
  float: left;
}
[dir=rtl] html .myDiv {
  float: right;
}