Reputation: 2015
I am writing a less stylesheet for a bi-directional website, and I need to write a single less file and produce two different stylesheets one for left-to-right layouts (ltr) and the other for right-to-lef layouts (rtl)
so when i am styling for rtl layouts, i want to convert every left value to be right, wither it is a float, padding or margin,
to do so, I have defined the required variables at the top of my less file as follows:
@left: right;
@right: left;
simply, i can float elements dynamically like this
float: @left; // this will be floated to left in ltr layout while it will be right in rtl layout.
but my problem is that I want be able also to use these variables to produce dynamic properties, for example when positioning elements absolutely, or relatively, i want to be able to write the left
or right
property dynamically depending on the value of the @left
variable as follows
position: relative;
@left: 10px;
but this gives an error on compiling, any clue how to do that, Note that I have done this using SASS, but till now I couldn't get it to work with LESS ?
Upvotes: 6
Views: 6541
Reputation: 4503
You may check this library: https://github.com/DevelopmentIL/direction.less
It has large support for many css-rules. For example:
@direction: rtl; // use `rtl` or `ltr`
@import "direction.less";
body {
.direction();
}
.float {
.float();
}
.box {
display: inline-block;
.margin-left(4px);
.padding-right(1em);
}
Will output:
body {
direction: rtl;
}
.float {
float: right;
}
.box {
display: inline-block;
margin-right: 4px;
padding-left: 1em;
}
Upvotes: 1
Reputation: 3997
If you are using DotLess, there is something more interesting that can be used instead of defining a finite number of mixins here.
It is built-in as the RTL plugin.
https://github.com/dotless/dotless/wiki/Plugins
dotless.Compiler.exe -p:Rtl:forceRtlTransform=true,onlyReversePrefixedRules=false file.less
Upvotes: 2
Reputation: 2015
Below is the solution that lets you write your styles once using LESS, then compile them to be two different css stylesheets for both rtl, and ltr layouts.
basically we'll have three LESS files (they can be more!):
style-ltr.less // this where we hold the rtl variables
style-rtl.less // rtl variables
main.less // here we'll write our styles
in style-ltr.less
define the following variables:
@left: left;
@right: right;
@import "main.less";
while in style-rtl.less
they will have the following values:
// reflect variables
@left: right;
@right: left;
@import "main.less";
now in main.less
, we'll define the following mixins
.left(@distance) when (@left = left) {
left: @distance;
}
.left(@distance) when (@left = right) {
right: @distance;
}
.right(@distance) when (@right = right) {
right: @distance;
}
.right(@distance) when (@right = left) {
left: @distance;
}
// now we can style our elements using these mixins
div.something {
position: relative;
.left(10px);
float: @left;
}
now all we have to do is to include style-rtl.less
in rtl pages include (or the compiled css version),
as well to include style-ltr.less
in ltr pages, and div.something
will be floated to the left on ltr pages, while it will be floated to the right on the rtl pages
Note that you can define padding, margin, border-radius ...etc.
using the same way here.
UPDATE
I created two projects on github to help building a bi-directional applications
Credits:
inspired by my dear friend Victor Zamfir
Upvotes: 9
Reputation: 1364
Update: Take a look at Guard Expressions in LESS - maybe this can help a bit, you can create kinda conditional statements but you have to use mixins..
I understand your point, but on the other hand I'd approach this problem differently. Here's another simplified take - you define variables for differences in both cases, and then import as you wish - for example, place in master-ltr/master-rtl and import the rest of stylesheet after:
// master-ltr.less
// LTR:
@sidebar-pos-left: 10px;
@sidebar-pos-right: 0px;
@content-float: left;
...
@import 'styles.less';
// your styles.less would have:
.content {
float: @content-float;
...
}
.sidebar {
position: relative;
left: @sidebar-pos-left;
right: @sidebar-pos-right;
...
}
.. or maybe more effective - create separate file with vars-ltr/rtl, and then import into your master-ltr/rtl.
Not sure how really complicated the layout is, but maybe this gives you something you can use?
I've tried this using String Interpolation but it looks like the variables can be only embedded on the "variable" side of the definition. I might be wrong here, maybe folks know how to achieve it.
I'd do that bit different, not because it's not possible with LESS, but because of organization of code and general more-sane approach (it's not good to name something "left" when sometimes it's going to be actually "right" :)
For your second problem with position:relative
, here's my take:
<div class="element element-ltr">...</div>
.element {
position: relative;
&.element-ltr {
left: @element-side-position;
}
&.element-rtl {
right: @element-side-position;
}
}
That solution is kinda OK, but if you're stylesheet is huge, you're going to end up with lots of additional classes for -ltr and -rtl. Not really a big pain but you could actually make it even more useful by broadening the scope of the -ltr/-rtl to the parent containers (like header/content/sidebar/footer) and then adjust from there. They may have lots in common, like background, colors, font-size.. and you will just work on the differences in their -ltr/-rtl versions.
Also, read up on LESS Namespaces, they can offer you even more organizational powers.
Hope this helps!
Upvotes: -1