I'm using create-react-app for a multi-language project. I want to use some library like "cssJanus" or "rtlcss" to convert the Sass generated CSS file into a separate file and then use that newly generated file when I switch to another language.
Here's how my index.js looks like ...
import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import App from "./App";
import { configureStore } from "./store/configureStore";
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
And here's how my "App.js" looks like ...
import React, { Component } from "react";
import "./App.scss";
import { Route, Switch } from "react-router-dom";
import SignIn from "./features/signin/SignIn";
class App extends Component {
render() {
return (
<>
<Switch>
<Route path="/" exact component={SignIn} />
</Switch>
</>
);
}
}
export default App;
As you can see I'm using "./App.scss" file that simply have a bunch of @import statements to another ".scss" files in the "./src/css/" directory ...
/* autoprefixer grid: on */
@import "css/reset";
@import "css/variables";
@import "css/global";
I need your advice on how to do that. How to convert the generated CSS from App.scss to RTL into their own .css file and switch between them and the original generated CSS based on a change in the global state.
I searched a lot for something like this but with no luck.
Or if you have a better approach I'm all ears.
UPDATE: If your application is RTL at all, just add dir="rtl" in <html> tag, but if user can chose different languages that may be RTL or LTR you can do it like above example, and handle other things with CSS... Just check User chosen language is RTL and document.
Introduction: We can use SASS in React using a package called node-sass. Using node-sass we can just create sass files and use them as the normal CSS files in our React application and node-sass will take care of compiling sass files. Modules: To compile sass code, node-sass can be used.
To add a global CSS file to your Next. js app, you need to import the file inside pages/_app. js file.
Here is a simple solution that requires ejecting and adding a lightweight webpack-rtl-plugin
.
After running
npx create-react-app react-rtl
cd react-rtl
yarn eject
yarn add -D webpack-rtl-plugin @babel/plugin-transform-react-jsx-source
Go to config/webpack.config.js
and make some tweaks:
// import the plugin
const WebpackRTLPlugin = require('webpack-rtl-plugin')
// ...
module: { ... }
plugins: [
// ...,
// use the plugin
new WebpackRTLPlugin({ diffOnly: true })
].filter(Boolean),
// ...
On this stage, if you run yarn build
and look up build/static/css
folder, you should hopefully see additional .rtl.css
file that contains your rtl styles.
Then we need to tell webpack
to use MiniCssExtractPlugin.loader
for development as well so it will serve styles through link
tags instead of inline styles:
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && { loader: MiniCssExtractPlugin.loader }, // <-- use this
// isEnvDevelopment && require.resolve('style-loader'), <-- instead of this
and don't forget the plugin, lol:
module: { ... }
plugins: [
// ...,
// isEnvProduction && <-- comment this out
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// ...
].filter(Boolean),
And from here you can finally grab your default stylesheet href
and use to insert rtl styles. Here's how you could implement it:
class RtlCssBundleService {
constructor() {
this.rtlApplied = false
this.rtlStyles = [];
this.ltrStyles = Array.from(
document.querySelectorAll('link[rel="stylesheet"]')
)
}
insert = () => {
if (this.rtlApplied) { return }
this.rtlApplied = true
if (this.rtlStyles.length) {
return this.rtlStyles.forEach(style => {
document.body.appendChild(style)
})
}
this.rtlStyles = this.ltrStyles.map(styleSheet => {
const link = document.createElement("link")
link.href = styleSheet.href.replace(/\.css$/, '.rtl.css')
link.rel = "stylesheet"
document.body.appendChild(link)
return link
})
}
detach = () => {
this.rtlApplied = false
this.rtlStyles.forEach(style => {
document.body.removeChild(style)
})
}
toggle = () => {
return this.rtlApplied
? this.detach()
: this.insert()
}
}
const rtlStyles = new RtlCssBundleService()
export default rtlStyles
Then use this from any of your components. So anyway, I'm sure I've missed something and maybe that is a terrible approach, but it seems to work and here is the demo
If you use flexbox and css grid they have RTL support built in. Then use CSS Logical Properties for margin, padding, border, etc. If that is not enough, then you can use [dir="rtl"] .your-class
as a fallback.
Now you don't have two separate css files to maintain.
Here is a cross browser margin-right
example.
-webkit-margin-end: 25px;
margin-inline-end: 25px;
@supports (not (-webkit-margin-end: 0)) and (not (margin-inline-end: 0)) {
margin-right: 25px;
}
You could wrap that up into a mixin
for easier use across your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With