Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic CSS properties in LESS?

Tags:

css

less

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 ?

like image 599
Anas Nakawa Avatar asked Feb 03 '12 15:02

Anas Nakawa


3 Answers

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

  • bi-app-less
  • bi-app-sass

Credits:

inspired by my dear friend Victor Zamfir

like image 88
Anas Nakawa Avatar answered Sep 27 '22 22:09

Anas Nakawa


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
like image 38
jsgoupil Avatar answered Sep 27 '22 21:09

jsgoupil


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;
}
like image 27
Moshe Simantov Avatar answered Sep 27 '22 23:09

Moshe Simantov