Enabling bidirectional support on tailwindcss framework

  • By Twentylives
  • Last update: Jan 8, 2023
  • Comments: 16

tailwindcss-rtl

Total Downloads Latest Release

Introduction

Internationalization in semitic languages needs more than just translating texts, you would also need to mirror the layout horizontally. This can be done by adding dir="rtl" the the layout body tag, but this is propably not be enough and you will need to create a different style for RTL.

With tailwindcss-rtl plugin you will be able to support both RTL and LTR in the same style.

Live demo

Full live demo based on the official tailwindcss course project is available here:

Workcation live demo

Workcation-nuxt-i18n-rtl

Usage

Replace all utilities based on Right/Left with the new utilities specified below.

for example when you create an LTR layout and you would like to add left padding to an element you would normaly use pl-6, left is the start direction in LTR so you will replace it with ps-6.

Now add dir="rtl" or dir="ltr" attribute to your top level layout element:

<body dir="rtl">

Adding dir="ltr" is optional, because unless specified otherwise, LTR is assumed to be the default.

Installation

Install tailwindcss-rtl package:

# Yarn
yarn add tailwindcss-rtl --dev

# NPM
npm install tailwindcss-rtl --save-dev

Require tailwindcss-rtl in the project tailwind.config.js file:

plugins: [
  require('tailwindcss-rtl'),
],

Utilities

*tailwindcss-rtl adds the start and end notations as substitue for left and right.

Class Description
ps-[X] padding on start direction
pe-[X] padding on end direction
ms-[X] margin on start direction
me-[X] margin on end direction
text-start text aligned at the start direction
text-end text aligned at the end direction
float-start float to start direction
float-end float to end direction
start-[X] placement of positioned elements on start
end-[X] placement of positioned elements on end
clear-start clear to start direction
clear-end clear to end direction
rounded-s-[X] rounded borders on start direction
rounded-e-[X] rounded borders on end direction
rounded-ts-[X] rounded borders on top start direction
rounded-te-[X] rounded borders on top end direction
rounded-bs-[X] rounded borders on bottom start direction
rounded-be-[X] rounded borders on bottom end direction
border-s-[X] border width on start direction
border-e-[X] bordern width on end direction
space-s-[X] space between child
divide-s-[X] border width between child elements

Github

https://github.com/20lives/tailwindcss-rtl

Comments(16)

  • 1

    Cannot create 1px borders with border-s and border-e

    First, thanks for this tailwind plugin. I like the approach for making tailwind support right to left languages.

    I ran into an issue creating 1px width borders using border-s and border-e.

    In tailwind I can use border-l to create a 1px border on the left of a container. Similar with border-r. However, border-s and border-e does not behave this way.

    My options are:

    • Create 2px border with border-s-2
    • Use this to set border and remove other sides "border border-e-0 border-t-0 border-b-0"
  • 2

    Not working with Craco and React during production

    I am using tailwindcss with React using CRACO. The Rtl to Ltr switching is working fine during dev. But during production (Netlify) All of the classes which were supposed to be coming from rtl plugin are not there. I went through the code several time. On the inspector, It looks like during prod those classes don't get generated.

    Here is my Tailwind config file

    module.exports = {
    	purge: ["./src/pages/**/*.{js,ts,jsx,tsx}", "./src/components/**/*.{js,ts,jsx,tsx}"],
    	darkMode: "class", // or 'media' or 'class'
    	theme: {
    		extend: {
    			colors: {
    				background: "var(--color-background)",
    				backgroundSoft: "var(--color-background-soft)",
    				backgroundSofter: "var(--color-background-softer)",
    				accent: "var(--color-accent)",
    				accentSoft: "var(--color-accent-soft)",
    				accentSofter: "var(--color-accent-softer)",
    				accentSoftest: "var(--color-accent-softest)",
    				secondary: "var(--color-secondary)",
    				secondarySoft: "var(--color-secondary-soft)",
    				secondarySofter: "var(--color-secondary-softer)",
    				secondarySoftest: "var(--color-secondary-softest)",
    				online: "var(--color-online)",
    				away: "var(--color-away)",
    				offline: "var(--color-offline)",
    			},
    		},
    	},
    	variants: {
    		extend: { backgroundColor: ["checked"], borderColor: ["checked"], outline: ["focus", "checked"] },
    	},
    
    	plugins: [require("@tailwindcss/forms"), require("tailwindcss-rtl")],
    };
    
    
  • 3

    :not([dir="rtl"]) is breaking everything

    the change you did in the 0.8.0 is not working as you would expect. You can see a screen shot here where :not([dir="rtl"]) and [dir="rtl"] are both valid.

    Although [dir="rtl"] matches the tag selector, :not([dir="rtl"]) will match the selector.

    Screen Shot 2022-01-02 at 5 50 04 PM

  • 4

    Generator for insetUtilities doesn't seem to work

    We're using tailwindcss-rtl, but for some reason the insetUtilities aren't being loaded. As a result, when we apply the start-0 modifier in our CSS, the build phase will throw the following error:

    (49:0)@applycannot be used with.start-0because.start-0either cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that.start-0exists, make sure that any@importstatements are being properly processed *before* Tailwind CSS sees your CSS, as@applycan only be used for classes in the same CSS tree.

    For other classes, like the padding utilities, it all works fine and as expected. Any idea where to look?

  • 5

    Plugin doesn't work with Tailwind v3

    Running this plugin with Tailwind 3 in a Nuxt project gives the following error:

    TypeError: Cannot read properties of undefined (reading 'parent')
    

    The plugins documentation on Tailwind mentions different parameters to the plugin() function between v2 and v3, notably the absence of variants param (which makes sense considering that all variants are enabled by default in the JIT engine).

  • 6

    tailwind-rtl not working when the parent dir="rtl" in version 0.8.0

    I had a problem with tailwind-rtl version 0.8.0.

    everything works fine in LTR mode but when I change the direction the pseudo selector :not([dir="rtl"]) keep working and cause the element to apply CSS to both directions - start and end - .

    I manage to have a fixed solution by going to the previous version 0.7.2

    I noticed that in version 0.8.0 the CSS class are like that :

    
    @media (min-width: 768px) {
        :not([dir="rtl"]) .md\:rounded-ts-huge {
            border-top-left-radius: 150px;
        }
    }
    @media (min-width: 768px) {
        [dir="rtl"] .md\:rounded-ts-huge {
            border-top-right-radius: 150px;
        }
    }
    

    but in version 0.7.2

    @media (min-width: 768px) {
        ([dir="ltr"]) .md\:rounded-ts-huge {
            border-top-left-radius: 150px;
        }
    }
    @media (min-width: 768px) {
        [dir="rtl"] .md\:rounded-ts-huge {
            border-top-right-radius: 150px;
        }
    }
    

    I believe that this causes the problem.

    my env is: angular version 13. scss [email protected]

  • 7

    There is a need to change flex-row -> flex-row-reverse

    Hi,

    To make right arrangement of flex items when there is a flex-row parent, it needs to convert flex-row-reverse as a good sample you can check this component :

    https://tailwindcomponents.com/component/tailwindcss-flow-chart

    This manual modification to final css created by tailwind did the job for me:

    [dir="ltr"] .flex-row { flex-direction: row; }

    [dir="ltr"] .flex-row-reverse { flex-direction: row-reverse; }

    [dir="rtl"] .flex-row { flex-direction: row-reverse; }

    [dir="rtl"] .flex-row-reverse { flex-direction: row; }

    of course I made these change to all other flex-row classes for sm, md, lg, xl and 2xl

    Thanks,

  • 8

    end-0 cannot be applied

    Hi,

    The utility class end-0 won't work if used in an apply directive. It works when used in the html.

    image

    Other utilities like pe-0 or ms-10 works when applied.

    Is this something known ?

  • 9

    TypeError after Tailwind v2.0.1

    Description

    I keep receiving a TypeError when using this plugin, and I think it's because Tailwind has recently dropped support for IE11.

    Stack Trace

    TypeError: target is not a function
        at generators (\node_modules\tailwindcss-rtl\src\paddingUtilities.js:4:3)
        at module.exports (\node_modules\tailwindcss-rtl\src\paddingUtilities.js:18:20)
        at \node_modules\tailwindcss-rtl\src\index.js:16:16
        at \node_modules\tailwindcss\lib\util\processPlugins.js:69:5
        at Array.forEach (<anonymous>)
        at _default (\node_modules\tailwindcss\lib\util\processPlugins.js:63:11)
        at \node_modules\tailwindcss\lib\processTailwindFeatures.js:60:54
        at LazyResult.runOnRoot (\node_modules\postcss\lib\lazy-result.js:276:16)
        at LazyResult.runAsync (\node_modules\postcss\lib\lazy-result.js:328:26)
        at LazyResult.async (\node_modules\postcss\lib\lazy-result.js:178:30)
    
  • 10

    The RTL classes can't be applied to @apply

    I'm trying to add custom rtl classes to @apply variable and I get this error

    @apply cannot be used with .ps-4 because .ps-4 either cannot be found, or its actual definition includes a pseudo-selector like :hover, :active, etc. If you're sure that .ps-4 exists, make sure that any @import statements are being properly processed *before* Tailwind CSS sees your CSS, as @apply can only be used for classes in the same CSS tree.

  • 11

    Tailwind 3.0 RTL Search Patterns

    Now that Tailwind 3.0 supports RTL I wanted to migrate my codebase to use it.

    Instead of manually changing every class this plugin provides I came up with the following regex patterns and replacements:

    # Paddings
    ([ '"])([a-z]+:)*ps-(px|[.0-9]+)\b                       $1ltr:$2pl-$3 rtl:$2pr-$3
    ([ '"])([a-z]+:)*pe-(px|[.0-9]+)\b                       $1ltr:$2pr-$3 rtl:$2pl-$3
    
    # Margins
    ([ '"])([a-z]+:)*([-])?ms-(auto|px|[.0-9]+)\b            $1ltr:$2$3ml-$4 rtl:$2$3mr-$4
    ([ '"])([a-z]+:)*([-])?me-(auto|px|[.0-9]+)\b            $1ltr:$2$3mr-$4 rtl:$2$3ml-$4
    
    # Text
    ([ '"])([a-z]+:)*text-start\b                            $1ltr:$2text-left rtl:$2text-right
    ([ '"])([a-z]+:)*text-end\b                              $1ltr:$2text-right rtl:$2text-left
    
    # Floats
    ([ '"])([a-z]+:)*float-start\b                           $1ltr:$2float-left rtl:$2float-right
    ([ '"])([a-z]+:)*float-end\b                             $1ltr:$2float-right rtl:$2float-left
    
    # Positional
    ([ '"])([a-z]+:)*([-])?start-(auto|full|px|[./0-9]+)\b   $1ltr:$2$3left-$4 rtl:$2$3right-$4
    ([ '"])([a-z]+:)*([-])?end-(auto|full|px|[./0-9]+)\b     $1ltr:$2$3right-$4 rtl:$2$3left-$4
    
    # Clears
    ([ '"])([a-z]+:)*clear-start\b                           $1ltr:$2clear-left rtl:$2clear-right
    ([ '"])([a-z]+:)*clear-end\b                             $1ltr:$2clear-right rtl:$2clear-left
    
    # Rounded
    ([ '"])([a-z]+:)*rounded-s(-[-./0-9a-z]+)?\b             $1ltr:$2rounded-l$3 rtl:$2rounded-r$3
    ([ '"])([a-z]+:)*rounded-e(-[-./0-9a-z]+)?\b             $1ltr:$2rounded-r$3 rtl:$2rounded-l$3
    ([ '"])([a-z]+:)*rounded-ts(-[-./0-9a-z]+)?\b            $1ltr:$2rounded-tl$3 rtl:$2rounded-tr$3
    ([ '"])([a-z]+:)*rounded-te(-[-./0-9a-z]+)?\b            $1ltr:$2rounded-tr$3 rtl:$2rounded-tl$3
    ([ '"])([a-z]+:)*rounded-bs(-[-./0-9a-z]+)?\b            $1ltr:$2rounded-bl$3 rtl:$2rounded-br$3
    ([ '"])([a-z]+:)*rounded-be(-[-./0-9a-z]+)?\b            $1ltr:$2rounded-br$3 rtl:$2rounded-bl$3
    
    # Borders
    ([ '"])([a-z]+:)*border-s(-[-./0-9a-z]+)?\b              $1ltr:$2border-l$3 rtl:$2border-r$3
    ([ '"])([a-z]+:)*border-e(-[-./0-9a-z]+)?\b              $1ltr:$2border-r$3 rtl:$2border-l$3
    

    I didn't cover space-s-[X] and divide-s-[X] classes as there doesn't seem to be any left / right classes for those. 🤷‍♂️

    I also used the following regex to look for usages of the classes provided by this plugin (probably not super exhaustive):

    ([ '"])([a-z]+:)*([-]?(start|end|m[se])[-]|\b((clear|float|text)[-](start|end)|(divide|space)[-]s|border-[se]|p[se][-]|rounded-[tb]?[se])\b)
    

    Perhaps this will be useful for others looking to do the same too.

  • 12

    dependency conflict when install tailwindcss-rtl package

    Hello everyone I have a problem with install tailwindcss-rtl in my angular v12 project with this npm error:

    npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: @fullcalendar/[email protected] npm ERR! Found: @angular/[email protected] npm ERR! node_modules/@angular/common npm ERR! peer @angular/[email protected]"^12.0.0 || ^13.0.0-0" from @angular/[email protected] npm ERR! node_modules/@angular/cdk npm ERR! peer @angular/[email protected]"12.2.1" from @angular/[email protected] npm ERR! node_modules/@angular/material npm ERR! peer @angular/[email protected]"12.2.1" from @angular/[email protected] npm ERR! node_modules/@angular/material-moment-adapter npm ERR! @angular/[email protected]"12.2.1" from the root project npm ERR! 1 more (the root project) npm ERR! @angular/[email protected]"12.2.1" from the root project npm ERR! peer @angular/[email protected]"12.2.1" from @angular/[email protected] npm ERR! node_modules/@angular/forms npm ERR! peer @angular/[email protected]"^12.0.0 || ^13.0.0-0" from @angular/[email protected] npm ERR! node_modules/@angular/material npm ERR! peer @angular/[email protected]"12.2.1" from @angular/[email protected] npm ERR! node_modules/@angular/material-moment-adapter npm ERR! @angular/[email protected]"12.2.1" from the root project npm ERR! 1 more (the root project) npm ERR! peer @angular/[email protected]"^10.0.0 || ^11.0.0 || ^12.0.0" from [email protected] npm ERR! node_modules/ngx-quill npm ERR! [email protected]"14.2.0" from the root project npm ERR! 1 more (the root project) npm ERR! 8 more (@angular/material, @angular/platform-browser, ...) npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer @angular/[email protected]"^9.0.0" from @fullcalendar/[email protected] npm ERR! node_modules/@fullcalendar/angular npm ERR! @fullcalendar/[email protected]"4.4.5-beta" from the root project npm ERR! npm ERR! Conflicting peer dependency: @angular/[email protected] npm ERR! node_modules/@angular/common npm ERR! peer @angular/[email protected]"^9.0.0" from @fullcalendar/[email protected] npm ERR! node_modules/@fullcalendar/angular npm ERR! @fullcalendar/[email protected]"4.4.5-beta" from the root project npm ERR! npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force, or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

    how can I fix it?

  • 13

    Add support for `before`, `after` and right or left values

    When trying to use content in before and after, I found no solution. Is it something that tailwind supports by itself or this package needs to implement this?

  • 14

    inset

    Hi, thank you for your plugin. please consider adding following as well:

    inset-inline-start // "left" in ltr and "right" in rtl inset-inline-end inset-block-start inset-block-end

  • 15

    Negative values not being generated

    "tailwindcss": "^3.0.24",
    "tailwindcss-rtl": "^0.9.0"
    

    When using negative values (like -ms-16) the proper CSS is not being generated. I've just updated from Tailwind 2 and the plugin in version 0.7 where everything worked like charm.

  • 16

    Support for arbitrary values?

    Hi,

    I am not sure if this is because I have a prefix configured, but when I try to generate the following with arbitrary values:

    class="tw-start-[var(--inset-start)]"
    

    The associated class is not generated. Is this expected ?

    Thanks!