I was using the following LESS mixins to generate css for bidi usage.
.ltr(@ltrRules) {
body[dir="ltr"] & ,
body[dir="rtl"] *[dir="ltr"] & ,
body[dir="rtl"] *[dir="ltr"]& { @ltrRules(); }
}
.rtl (@rtlRules) {
body[dir="rtl"] & ,
body[dir="ltr"] *[dir="rtl"] & ,
body[dir="ltr"] *[dir="rtl"]& { @rtlRules(); }
}
.bidi(@ltrRules,@rtlRules) {
.ltr(@ltrRules);
.rtl(@rtlRules);
}
those would be later used like this:
// padding
// ------------------------------------------
.padding-start(@p) {
.bidi(
{ padding-left: @p } ,
{ padding-right: @p }
)
}
.padding-end(@p) {
.bidi(
{ padding-right: @p } ,
{ padding-left: @p }
)
}
this way when I eventually wrote:
div.myclass {
.padding-start(10px)
}
I would get a set of rules that would style div.myclass
with padding-left:10px
if the div was in a left-to-right context or with with padding-right:10px
if the div was in a right-to-left context.
I am now trying to convert this to SCSS and I have got to the following:
@mixin ltr {
body[dir="ltr"] & ,
//body[dir="rtl"] *[dir="ltr"]&
body[dir="rtl"] *[dir="ltr"] & { @content }
}
@mixin rtl {
body[dir="rtl"] & ,
//body[dir="ltr"] *[dir="rtl"]&
body[dir="ltr"] *[dir="rtl"] & { @content}
}
/*
@mixin bidi($ltrRules,$rtlRules) {
@include ltr(@include ltrRules);
@include rtl(@include rtlRules);
}
*/
@mixin bidi-padding-start($p) {
@include ltr {
padding-left: $p;
}
@include rtl {
padding-right: $p;
}
}
but I still have several issues:
1) If I uncomment the middle selectors in the rtl and ltr mixins I then get the following error: Invalid CSS after "[dir="ltr"]": expected "{", was "&". "&" may only be used at the beginning of a compound selector.
I can live without this rule but I would prefer not to... I would expect it to compile
.myclass {
@include padding-start(10px)
}
into:
body[dir="rtl"] .myclass ,
body[dir="ltr"] *[dir="rtl"] .myclass ,
body[dir="ltr"] *[dir="rtl"].myclass
2) I can't find a way to implement @mixin bidi
because I cant find a way to pass along two content blocks to a mixin.
can someone help with this migration please
Currently SASS's functionality is limited to passing only a single @content
block into a @mixin
. There was a feature request discussion on a github issue but it was closed, and it looks like it never came to fruition.
In that discussion, someone suggested a workaround that effectively works with @extend
. It works by using %placeholders
to allow you to reference temporary rulesets. However, it seems a bit hacky and will need to be tested for more complicated rulesets with deeper nesting.
@mixin ltr {
body[dir="ltr"] & ,
//body[dir="rtl"] *[dir="ltr"]&
body[dir="rtl"] *[dir="ltr"] & { @content }
}
@mixin rtl {
body[dir="rtl"] & ,
//body[dir="ltr"] *[dir="rtl"]&
body[dir="ltr"] *[dir="rtl"] & { @content}
}
@mixin bidi {
@content;
@include ltr {
@extend %ltr !optional;
}
@include rtl {
@extend %rtl !optional;
}
}
@mixin padding-end($p) {
@include bidi {
@at-root {
%ltr {
padding-right: $p;
}
%rtl {
padding-left: $p;
}
}
}
}
.test {
@include padding-end(5px);
}
Another option that may be more readable for future devs may simply be to explicitly call both mixins in place of bidi
. It may be possible to write a script to make this migration.
@mixin padding-end($p) {
@include rtl {
padding-left: $p;
}
@include ltr {
padding-right: $p;
}
}