I have developed an application in angular and is completed which includes approx. 80 modules. Now I need to convert the language to arabic which is RTL. I used SCSS as a CSS library. Is there any easy way to convert my LTR application to RTL because many styles are affecting while using direction=rtl;
I don't want to convert every .scss files in the module.
I'm using css logical properties which should be supported in most of the browsers.
Instead of using margin-left you write margin-inline-start.
The cool part is that if you are using postcss with postcss-preset-env you just can use the new syntax, it will convert it to css that supports by all the browsers based on the dir attribute.
For example:
// some.css
.my-class {
float: inline-start;
margin-inline-start: 10px;
}
it will produce
// some.output.css
[dir="ltr"] .my-class {
float: left
}
[dir="rtl"] .my-class {
float: right
}
[dir="ltr"] .my-class {
margin-left: 10px
}
[dir="rtl"] .my-class {
margin-right: 10px
}
With this output css you can just set the dir attribute of you html element to
rtl, and the browser will use the proper styles.
I'm using this approach in a large code base, it works like a charm.
Another approach is to use rtl-css, which is a tool that creates new css files with flipped directions.
It has several webpack plugins as well, such as rtlcss-webpack-plugin
I have written a crud python tool that can mass-convert all CSS and SCSS files from physical to logical in one go. To use, save that file somewhere, e.g. to-logical.py. Requires python3. Can be used on a single file or whole dirs, and even recursive. Can handle scss expressions. The tool currently handles left, right, top, bottom, margin-*, border-*, padding-*, min-width, max-width, min-height, max-height, text-align.
python3 to-logical.py -r <path-to-dir>
Since I am using SCSS it becomes easy by adding mixins. Below are the mixins for common rtl to ltr properties and I replaced all the border, margin, padding, position and border-radius to generate from this mixins, and it worked fine. Took some long process but perfect.
#mixin rtl-value($property, $ltr-value, $rtl-value, $imp:null) {
#{$property}: $ltr-value;
:host-context([dir=rtl]) & {
#{$property}: $rtl-value;
}
}
#mixin border-radius-gen($tl, $tr, $br, $bl, $imp:null) {
#include rtl-value(border-top-left-radius, $tl, $tr, $imp);
#include rtl-value(border-top-right-radius, $tr, $tl, $imp);
#include rtl-value(border-bottom-right-radius, $br, $bl, $imp);
#include rtl-value(border-bottom-left-radius, $bl, $br, $imp);
}
#mixin margin-gen($top:null, $right:null, $bottom:null, $left:null, $imp:null) {
margin-top: $top $imp;
#include rtl-value(margin-right, $right, $left, $imp);
margin-bottom: $bottom $imp;
#include rtl-value(margin-left, $left, $right, $imp);
}
#mixin padding-gen($top:null, $right:null, $bottom:null, $left:null, $imp:null) {
padding-top: $top $imp;
#include rtl-value(padding-right, $right, $left, $imp);
padding-bottom: $bottom $imp;
#include rtl-value(padding-left, $left, $right, $imp);
}
#mixin border-gen($top:null, $right:null, $bottom:null, $left:null, $imp:null) {
border-top: $top $imp;
#include rtl-value(border-right, $right, $left, $imp);
border-bottom: $bottom $imp;
#include rtl-value(border-left, $left, $right, $imp);
}
#mixin position-gen($top:null, $right:unset, $bottom:null, $left:unset, $imp:null) {
top: $top $imp;
#include rtl-value(right, $right, $left, $imp);
bottom: $bottom $imp;
#include rtl-value(left, $left, $right, $imp);
}
Examples
.style{
#include margin-gen($left: 1px, $right: 1px, $top: 1px, $bottom: 1px, $imp: !important)
#include padding-gen($left: 1px, $right: 1px, $top: 1px, $bottom: 1px, $imp: !important)
#include border-gen($left: 1px solid #ccc, $right: 1px solid #ccc, $top: 1px solid #ccc, $bottom: 1px solid #ccc, $imp: !important)
}
Related
I am using the Bourbon modal reset. Its close button comes with the following styling:
.modal-close {
#include position(absolute, ($modal-padding /2) ($modal-padding /2) null null);
#include size(1.5em);
background: $modal-background;
cursor: pointer;
&:after,
&:before {
#include position(absolute, 3px 3px 0 50%);
#include transform(rotate(45deg));
#include size(0.15em 1.5em);
background: $modal-close-color;
content: '';
display: block;
margin: -3px 0 0 -1px;
}
&:hover:after,
&:hover:before {
background: darken($modal-close-color, 10%);
}
&:before {
#include transform(rotate(-45deg));
}
}
This makes it look like a grey × in the upper right of the modal. However, I would like to change it to look like a button that says "Save and Close". I'm wondering what the best method of overriding these styles is. On properties like margin, I can simply set it to whatever I want. However on #include position(....);, I am not really sure how I can reset that to none, initial, or unset. What is the best method for doing something like this? I don't want to simply remove the properties in the original refill file; I would like to keep a separate _modalOverride.scss, so I can include it where I want, but keep the original in tact. How can I override these "custom" #include properties?
Refills was designed to be overwritten so I'd just do the following to the HTML:
...
<div class="modal-close" for="modal-1">Close and Save</div>
...
and for the Scss:
...
.modal-close {
#include position(absolute, ($modal-padding /2) ($modal-padding /2) null null);
#include size(8em 1.5em);
background: tomato;
cursor: pointer;
}
...
But if you want to do an overwrite file it might be a bit trickier. You could do something like this in a file that comes after the modal.scss:
.modal-close {
position: inherit;
&:after,
&:before {
background: transparent;
}
&:hover:after,
&:hover:before {
background: transparent;
}
}
I am looking to develop this mixin further, so I can pass multiple arguements through the mixin without having to re-create the include every time e.g:
NOT THIS:
#include main-container(red);
#include main-container(blue);
BUT THIS:
#include main-container(red, blue);
Current Code
#mixin main-container-bg($name){
&.#{$name}-bg{
background:url("/images/"#{$name}"-angle-bg.png") center 78px no-repeat;
}
}
I believe I need a for statement alongside an each statement to loop my mixin though all of the arguments in the #include later in the scss.
Any idea's?
Any help is welcomed.
-Neil
You could use the #each directive and pass a list to the mixin in this way
#mixin main-container-bg($listcolours) {
#each $colour in $listcolours {
&.#{$colour}-bg{
background:url(/images/#{$colour}-angle-bg.png) center 78px no-repeat;
}
}
}
div {
#include main-container-bg((red, blue));
}
The generated CSS is
div.red-bg {
background: url(/images/red-angle-bg.png) center 78px no-repeat;
}
div.blue-bg {
background: url(/images/blue-angle-bg.png) center 78px no-repeat;
}
I'm new to Sass, so if this isn't the best way of doing this type of thing, I apologise!
So, I've got a mixin for button style, like so:
#mixin button ($bg, $color, $padding, $display: inline, $radius: 0, $transition: 0.2s) {
background: $bg;
#if $radius > 0 {
#include border-radius($radius)
}
color: $color;
#if $display != inline {
display: $display;
}
#if $padding > 0 {
padding: $padding;
}
text-decoration: none;
#include transition(all, $transition, linear);
&:hover {
#if lightness($bg) > 50% {
background: darken($bg, 10%);
} #else {
background: lighten($bg, 10%);
}
}
}
and a button, like so:
.btn {
#include button(#095d94, #fff, 10px, inline-block);
}
But, now I need another button with a different background colour. So what I'm wondering is: is there a way to extend a class, and also just change an argument of the mixin that that class includes, without having to do this:
.btn2 {
#extend .btn;
background: #bad78d;
&:hover {
background: darken(#bad78d, 10%);
}
}
Is it possible to feed in another background colour? Something like,
.btn2 {
$bg: #bad78d; //i know this doesn't work
#extend .btn;
}
or like,
.btn2 ($bg: #bad78d) {
#extend .btn; //this one doesn't even make sense, but I think I'm explaining what I need... ish.
}
I think you have two options here.
Also you try to keep it dry, there is nothing too wrong about repading sometimes. So if your mixin is not too huge it'll be ok to this:
.btn {
#include button(#095d94, #fff, 10px, inline-block);
}
.btn2 {
#include button(#bad78d, #fff, 10px, inline-block);
}
But This will only be required if the difference between .btn and .btn2 is big.
If you just want to change certain properties, you may also just use the classig cascading.
.btn,.btn2 {
#include button(#095d94, #fff, 10px, inline-block);
}
.btn2 {
background-color:#bad78d;
...
}
Succinctly, By using Susy's at-breakpoint responsive mixin, is there a way or function to include an external CSS file in the body of the breakpoint call?
Something like this:
.page {
border: 1px dashed #000;
height: 650px;
#include container;
.content {
color: red;
text-align: center;
border: 1px dashed red;
height: 400px;
#include span-columns(4 omega, 6);
.main {
color: green;
border: 1px dashed green;
text-align: center;
#include span-columns(1, 2);
}
.secondary {
color: blue;
border: 1px dashed blue;
#include span-columns(2, 3);
}
}
#include at-breakpoint(800px 8 250px) {
#include container;
.content {
#include span-columns(1, 1);
}
//IMPORT or INCLUDE CSS FILE HERE somehow...
} //end of breakpoint
}
I was hoping it was possible, because that'd be a whole lot cleaner than writing all the CSS rules I wish to be applied right there inline. Let me know if it's possible or what's the best practice in this case.
Thank you!
Sure. This isn't really a question about Susy, so much as a question about Sass. The same answers are true for working in the context of any wrapping mixin.
You can only import files at the root level (for now, at least) — but that's not your only option. I've seen people write all their site styles inside mixins, and then simply include those mixins as needed:
#mixin medium-layout {
// your medium css
}
.page {
#include at-breakpoint($medium) {
#include medium-layout;
}
}
You can use as many mixins as you like, call them whatever you want, and put them in other files (as long as you #include those files before calling the mixins).
I use a different approach. Rather than nesting everything under a .page selector, with big groups for each breakpoint, I break things up into modules, and keep the breakpoint styles attached to each module as needed.
// _main.scss
.main {
color: green;
#include at-breakpoint($medium) { /* changes to main */ }
}
// _secondary.scss
.secondary {
color: blue;
#include at-breakpoint($medium) { /* changes to secondary */ }
}
From a mobile-first perspective, where breakpoint styles may need to override or build on existing styles, this keeps all the related code in one place.
everyone.
I start to learn how to use SASS and Compass and whant to ask advice in better organizing this snippet of code
.main-link.first-item {
#include background(image-url($bg-sprite) no-repeat -27px -39px,
linear-gradient(#4b4e58, #3f424a));
&:hover {
#include background(image-url($bg-sprite) no-repeat -27px -1px,
linear-gradient(#4b4e58, #3f424a));
}
How can I use linear gradient without repeting, but only changing position of image?
You just need to adjust the background position of the first image.
&:hover {
background-position: -27px -1px, 0 0;
}
I agree with #cimmanon's answer.
Although if you want to use the same thing over and over again on different elements in different stylesheets I would propose to create a mixin and put it into a separate sass file. Than you can import that into the files where you need it:
# mixin.css.scss
#mixin custom-background($bg-sprite, $position-vertical, $position-horizontal) {
#include background(image-url($bg-sprite) no-repeat $position-vertical $position-horizontal,
linear-gradient(#4b4e58, #3f424a));
}
# some.css.scss
#import "mixin.css.scss"
.main-link.first-item {
#include custom-background($bg-sprite, -27px, -39px);
&:hover {
#include custom-background($bg-sprite, -27px, -1px);
}
}