Why we are using scss/sass:
Over the years, SCSS and SASS (collectively known as Sass) have won the hearts of many web developers. At its core, Sass is a powerful CSS extension, making stylesheets more maintainable, organized, and efficient. With features like variables and nested rules, it simplifies repetitive tasks and streamlines CSS. Given its advantages, many naturally wonder if they can harness its power in React Native — a popular mobile app development framework.
Integrate scss with React Native isn’t straightforward. React Native doesn’t directly support CSS, let alone its preprocessors. Instead, it uses StyleSheet
, a method to style apps using JavaScript. While this allows for dynamic and platform-specific styles, it means conventional Sass files can't be directly used.
Furthermore, React Native relies on a Flexbox-based layout engine, different from traditional CSS. So, even if we transform Sass into React Native styles, additional tweaks are often necessary to ensure layouts look right.
Steps of the integration of SCSS with React Native
Before diving into the steps, it’s pivotal to understand the significance of the two primary packages we’ll be using: react-native-sass-transformer
and node-sass
.
react-native-sass-transformer
: React Native doesn't inherently understand SCSS or SASS. That's wherereact-native-sass-transformer
comes into play. This package acts as a bridge, allowing React Native to interpret and utilize Sass styles. It transforms our SCSS/SASS files into a format that React Native'sStyleSheet
can comprehend and apply. Essentially, it's the heart of our Sass-to-React Native integration.node-sass
: Serving as the backbone to our transformer,node-sass
is a library that compiles .scss and .sass files into CSS. It's the underlying force that powers the transformation, making sure that our Sass code gets correctly processed and ready for the next stage, which is handled by thereact-native-sass-transformer
.
By utilizing these two packages in tandem, we can seamlessly integrate Sass into our React Native workflow, ensuring our styles remain dynamic, reusable, and, most importantly, compatible.
Let’s Start by Creating A new React Native project
npx react-native@latest init ReactNativeScssSampleApp
After creating the project, go into App.tsx or App.js under the project root directory.
type SectionProps = PropsWithChildren<{
title: string;
}>;
function Section({children, title}: SectionProps): JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
</Text>
<Text
style={[
styles.sectionDescription,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{children}
</Text>
</View>
);
}
function App(): JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode ? Colors.black : Colors.white,
}}>
<Section title="Step One">
Edit <Text style={styles.highlight}>App.tsx</Text> to change this
screen and then come back to see your edits.
</Section>
<Section title="See Your Changes">
<ReloadInstructions />
</Section>
<Section title="Debug">
<DebugInstructions />
</Section>
<Section title="Learn More">
Read the docs to discover what to do next:
</Section>
<LearnMoreLinks />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
export default App;
From above code, it tells, React Native can define the style sheet inside .tsx or .js file using const styles = StyleSheet.create
method. Now let’s move the styles into another scss file under styles directory.
In your project root directory, use the following command:
mkdir styles
touch styles/App.scss
Now, rewrite styles into styles/App.scss
, you can either write margin-top:32px
or margin-top:32
.
.sectionContainer {
margin-top: 32px;
padding-left: 24px;
padding-right: 24px;
}
.sectionTitle {
font-size: 24px;
font-weight: 600;
}
.sectionDescription {
margin-top: 8px;
font-size: 18px;
font-weight: 400;
}
.highlight {
font-weight: 700;
}
Now you can safely remove the following styles from your App.tsx or App.js
// remove all of these styles from App.tsx or App.js
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
Install react-native-sass-transformer and node-sass (you can either install them separately Or install them together using the following command)
npm install --save react-native-sass-transform node-sass
Now, you will need make some additional config.
In project root directory, find and modify your metro.config.js
as following:
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
module.exports = (async () => {
const defaultConfig = await getDefaultConfig(__dirname);
const config = {
transformer: {
babelTransformerPath: require.resolve('react-native-sass-transformer'),
},
resolver: {
sourceExts: [...defaultConfig.resolver.sourceExts, 'scss', 'sass'],
},
};
return mergeConfig(defaultConfig, config);
})();
The configuration script above enhances React Native’s Metro bundler to support Sass files.
getDefaultConfig
: Imported from@react-native/metro-config
, this gets the default Metro bundler settings.- Asynchronous Function: A function fetches the default Metro configuration and returns a customized configuration object.
transformer
: Specifies a new transformer for Metro, usingreact-native-sass-transformer
to process Sass files, converting them to a React Native-friendly format.resolver
: Adjusts how files are resolved:
- Excludes ‘svg’ from asset extensions.
- Adds ‘scss’ and ‘sass’ to source file extensions, allowing Metro to handle these types.
This configuration ensures Metro understands and properly bundles Scss files in a React Native project.
After you have modified and saved the above metro.config.js
, if your project is using typescript, in your project root directory, create a new file named declarations.d.ts
and write the following line
declare module "*.scss";
Now your directory structure should be as following (only includes the files that changed or created in this artical)
project/
├── App.tsx | App.js
├── styles (created)
│ └── App.scss (created)
├── declarations.d.ts (created only for typescript project)
├── metro.config.js (modified)
Make sure you have followed all steps above.
Now, go into your App.js or App.tsx file, make sure you have removed all the in file styles. Put the following line into your import. Make sure for a second time that your structure is following the above directory structure.
import styles from './styles/App.scss';
Now you should be able to run your react native application with scss/sass integrated.
Start the application and play with some simple Scss/Sass
I am assuming that you have followed the official guid and already set up your development environment.
Now let’s type npm run start
in your command line from your root directory. And run it on a device emulator.
In order to verify the mobile view is rendered based on the Scss but not the React Native styling object, we can modify a little bit in styles/App.scss
. Let’s give a background color to the description.
.sectionContainer {
margin-top: 32px;
padding-left: 24px;
padding-right: 24px;
}
.sectionTitle {
font-size: 24px;
font-weight: 600;
}
.sectionDescription {
margin-top: 8px;
font-size: 18px;
font-weight: 400;
background-color: #800080;
}
.highlight {
font-weight: 700;
}
After reloading the application, you can see, the sectionDescription
has been appened with a #800080
background color with the change above.
Conclusion:
In the ever-evolving landscape of mobile application development, integrating SCSS/SASS with React Native offers a unique blend of style and efficiency. SCSS and SASS, renowned for their organized and efficient stylesheets, have traditionally been constrained to web development. However, through a methodical integration process, it’s now possible to harness their full potential within React Native. The article provides a detailed step-by-step guide on achieving this integration using react-native-sass-transformer
and node-sass
. By the end, developers are not only equipped to implement SCSS in React Native but also appreciate the dynamism and reusability it brings to the table.