Makes supporting CSS for left-to-right (LTR) and right-to-left (RTL) easy with Sass.

  • By Tyson Matanich
  • Last update: Aug 23, 2022
  • Comments: 5

Directional-SCSS

Makes supporting both left-to-right (LTR) and right-to-left (RTL) easy. By including directional.scss into your project and using its Sass variables, functions, and mixins, you can create an LTR and RTL CSS bundle for your site.

Article: http://www.matanich.com/2013/09/06/rtl-css-with-sass/

Demos:

Features

Variables

  • $dir - defaults to ltr but can be set to rtl
  • $left - set to left when $dir equals ltr and right when $dir equals rtl
  • $right - set to right when $dir equals ltr and left when $dir equals rtl

Functions

  • if-ltr($if) - returns $if param when $dir equals ltr otherwise returns nothing
  • if-ltr($if, $else) - returns $if param when $dir equals ltr otherwise returns $else param
  • if-rtl($if) - returns $if param when $dir equals rtl otherwise returns nothing
  • if-rtl($if, $else) - returns $if param when $dir equals rtl otherwise returns $else param
  • side-values($values) - switches the left and right values of the $values list when $dir equals rtl
  • corner-values($values) - switches the left and right values of the $values list when $dir equals rtl

Mixins

  • @include if-ltr { /*content*/ } - returns the @content when $dir equals ltr otherwise returns nothing
  • @include if-rtl { /*content*/ } - returns the @content when $dir equals rtl otherwise returns nothing

Example

'); } &:after { content: if-rtl('>', '<'); } @include if-ltr { strong { padding-left: 0.5em; } } @include if-rtl { em { margin-right: 0.5em; } } } .icon.icon-star { background-image: url(sprite-#{$dir}.png); }">
// Import helpers from directional.scss
@import "directional";

// Use the helpers enable creating CSS bundles for LTR and RTL
body {
    text-align: $left;
}

p {
    padding-#{$right}: 1em;
    margin: side-values(0 2em 0 1em) if-ltr(!important);
    background-image: url(sprite#{if-rtl('-rtl')}.png);

    &:before {
        content: if-ltr('<', '>');
    }

    &:after {
        content: if-rtl('>', '<');
    }

    @include if-ltr {
        strong {
            padding-left: 0.5em;
        }
    }

    @include if-rtl {
        em {
            margin-right: 0.5em;
        }
    }
}

.icon.icon-star {
    background-image: url(sprite-#{$dir}.png);
}

To bring it all together your project should look something like the following:

site-ltr.scss

@import 'site.scss';

site-rtl.scss (overrides $dir)

$dir: rtl;
@import 'site.scss';

site.scss

@import 'directional.scss';

// Your site styles here using directional-scss variables, functions, and mixins

Then reference the appropriate bundle (site-ltr.css or site-rtl.css) needed for the current page:

">
>
<html>
<head>
    <link href="/site-ltr.css" rel="stylesheet"/>
head>
<body>
body>
html>

Github

https://github.com/tysonmatanich/directional-scss

Comments(5)

  • 1

    Dynamically changing pseudo elements (i.e. before -> after)

    Hi! Is there a way to change 'before' pseudo element to 'after'? Currently syntax like

    icon:#{if-ltr('before', 'after')} {
          ...
    }
    

    produces syntax error

    Thank you so much for this awesome .scss!

  • 2

    Border values shorthand list

    border-radius shorthand property, and maybe a few others, is ordered as top-left, top-right, bottom-left, bottom-right. So new order would be 2,1,4,3.

    This may be pretty edge-case though. I just made an adaption of your dir-values function called border-values:

    @function border-values($values) {
      @if $text-direction == rtl and length($values) == 4 {
        // border shorthand is defined as tl, tr, br, bl, so new order is 2,1,4,3
        @return nth($values, 2) nth($values, 1) nth($values, 4) nth($values, 3);
      }
      @else {
        @return $values;
      }
    }
    
  • 3

    HTML dir attribute

    How can directional-scss detect HTML dir attribute value? or, how can we pass HTML dir attribute value to scss file?

    maybe:

    @if(html[dir]=="rtl") {$dir: rtl;} @else {$dir: ltr;}

  • 4

    Override default value for $dir - html[dir="rtl"]

    Hi, I'm trying to change the $dir parameter by the html "dir" attribute without success. I want to work with one css file and not with an css-rtl so what is the right way to handle it?

    Wanted situation: // Override default value for $dir in directional.scss html[dir="rtl"] { $dir: rtl; }

  • 5

    Fixed error - dir-values to side-values function

    @tysonmatanich I see that there is no dir-values function which is being used in the example.scss. So, I changed it to side-values which does the job 😃 Please take a look.

    Cheers 🍻