Repository: kristerkari/react-native-css-modules Branch: master Commit: 0886ad1e3962 Files: 15 Total size: 64.9 KB Directory structure: gitextract_tu1r7ujt/ ├── LICENSE ├── README.md └── docs/ ├── faq.md ├── multiple-transformers.md ├── setup-css-variables.md ├── setup-css.md ├── setup-less.md ├── setup-linting.md ├── setup-postcss.md ├── setup-responsive.md ├── setup-sass.md ├── setup-stylename.md ├── setup-stylus.md ├── setup-typescript.md └── web-compatibility.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2019 Krister Kari Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # React Native CSS modules Style React Native components using CSS, PostCSS, Sass, Less or Stylus. **Quick links:** **[Features](#features)** • **[Documentation](https://github.com/kristerkari/react-native-css-modules#documentation)** • **[Example Apps](#example-apps)** • **[Development](#development)** • **[FAQ](docs/faq.md#frequently-asked-questions)** ## Features - :tada: You can share your CSS modules between React Native and React Web by using `className` property in React Native, and by using [React Native for Web](https://github.com/necolas/react-native-web) for the browser. - :ok_hand: Supports [CSS](https://github.com/kristerkari/react-native-css-transformer), [PostCSS](https://github.com/kristerkari/react-native-postcss-transformer), [Sass](https://github.com/kristerkari/react-native-sass-transformer), [Less](https://github.com/kristerkari/react-native-less-transformer) and [Stylus](https://github.com/kristerkari/react-native-stylus-transformer). - :fire: CSS Hot loading (live reloading). - :computer: Supports responsive CSS features: [CSS Media Queries](https://alligator.io/css/media-queries/) and [CSS Viewport Units](https://alligator.io/css/viewport-units/). - :sparkles: Supports [CSS variables](https://alligator.io/css/css-variables/). - :globe_with_meridians: [Platform-specific extensions](https://facebook.github.io/react-native/docs/platform-specific-code.html#platform-specific-extensions) for CSS, e.g. `styles.ios.css`, `styles.android.css`, `styles.native.css`. - :tophat: Support for `styleName` attribute that allows you to use CSS class names as strings, and allows hyphens in class names (like the [className property](https://reactjs.org/docs/faq-styling.html#how-do-i-add-css-classes-to-components) in Web React). - :package: Suppports Typescript with [React Native type definitions that add support for React Native CSS modules](https://github.com/kristerkari/react-native-types-for-css-modules) and [CSS, Sass, LESS, PostCSS, or Stylus transformers that automatically create typings for your CSS files](https://github.com/kristerkari/react-native-typed-sass-transformer). - :mag: Keep your CSS error free using [a custom stylelint config for React Native CSS modules](https://github.com/kristerkari/stylelint-config-react-native-css-modules) ## Examples Using React Native CSS modules works almost the same way as using CSS modules with a Web React project, but there are some limitations. There is no support complex CSS selectors. Only simple CSS class selector (e.g. `.myClass`) is supported. React Native also only supports a subset of browser's CSS properties for styling. For more info about the differences between using CSS modules in Web and React Native, have a look at [this explanation in the FAQ](docs/faq.md#what-is-the-difference-with-regular-css-and-react-natives-css). #### Basic example using Sass **App.scss** ```scss .container { flex: 1; justify-content: center; align-items: center; } .blue { color: blue; } .blueText { @extend .blue; font-size: 18px; } ``` **App.js** ```jsx import React from "react"; import { Text, View } from "react-native"; import styles from "./App.scss"; const App = () => ( Blue text ); export default App; ``` #### CSS media queries and CSS viewport units If you need CSS media queries or CSS viewport units, please have a look at the [responsive CSS features setup guide](docs/setup-responsive.md). ```css .wrapper { height: 10vh; width: 10vw; } @media (min-width: 800px) { .wrapper { height: 20vh; width: 20vw; } } ``` #### CSS variables CSS variables are not supported by default, but you can add support for them by using [PostCSS](https://postcss.org/) and [postcss-css-variables](https://github.com/MadLittleMods/postcss-css-variables#readme) plugin. Please have a look at the [CSS variables setup guide](docs/setup-css-variables.md). ```css :root { --text-color: blue; } .blue { color: var(--text-color); } ``` #### Exporting variables from CSS to Javascript You might also need to share you variables from a CSS/Sass/Less/Stylus file to Javascript. To do that you can use the `:export` keyword: **colors.scss** ``` $grey: #ccc; :export { grey: $grey; } ``` **App.js** ```jsx import React from "react"; import { Text, View } from "react-native"; import colors from "./colors.scss"; import styles from "./App.scss"; const App = () => ( Grey text ); export default App; ``` ## Example Apps Have a look at the example apps to see how you can use CSS modules for both React Native and Web using the same code. - **[Example app](https://github.com/kristerkari/react-native-css-modules-example)** - **[CSS Media Queries example app](https://github.com/kristerkari/react-native-css-modules-with-media-queries-example)** - **[CSS Viewport Units example app](https://github.com/kristerkari/react-native-css-modules-with-viewport-units-example)** - **[Example app with styleName syntax](https://github.com/kristerkari/react-native-css-modules-stylename-example)** - **[Typescript example app](https://github.com/kristerkari/react-native-css-modules-with-typescript-example)** ## Documentation #### :books: Setup - **[Setup CSS modules with CSS support](docs/setup-css.md)** - **[Setup CSS modules with PostCSS support](docs/setup-postcss.md)** - **[Setup CSS modules with Sass support](docs/setup-sass.md)** - **[Setup CSS modules with Less support](docs/setup-less.md)** - **[Setup CSS modules with Stylus support](docs/setup-stylus.md)** - **[Setup CSS modules with Responsive CSS support (CSS Media Queries & CSS Viewport Units)](docs/setup-responsive.md)** - **[Setup CSS modules with CSS variables support](docs/setup-css-variables.md)** - **[Setup CSS modules with Typescript support](docs/setup-typescript.md)** - **[Setup CSS modules with styleName attribute (use className as a string)](docs/setup-stylename.md)** - **[Use CSS and Sass in the same project](docs/multiple-transformers.md)** - **[Setup recommended linting (ESLint & stylelint)](docs/setup-linting.md)** - **[Setup browser compatibility](docs/web-compatibility.md)** #### :books: Other documentation - **[Frequently Asked Questions](docs/faq.md)** - **[Stylelint config for React Native CSS modules](https://github.com/kristerkari/stylelint-config-react-native-css-modules)** - **[List of CSS properties supported by React Native (out of date)](https://github.com/vhpoet/react-native-styling-cheat-sheet)** ## Development To see which new features are being planned and what is in progress, please have a look at [the development board](https://github.com/kristerkari/react-native-css-modules/projects/1). If you want to suggest a new feature or report a bug, please open a new issue. --- ## Special thanks The idea for React Native CSS modules comes from these projects that have made a lot of work for supporting CSS and CSS modules in React Native: [css-to-react-native](https://github.com/styled-components/css-to-react-native) and [react-native-sass-classname](https://github.com/daniloster/react-native-sass-classname). A big thanks to them! --- ### License [MIT](/LICENSE) ================================================ FILE: docs/faq.md ================================================ # Frequently Asked Questions ## Why was React Native CSS modules project created? React Native does not offer any kind of built-in support for loading CSS from `.css` files and using it for styling. So far the only way has been to use React Native's `style` property or any of the available CSS-in-JS libraries. Now you can use `className` property and keep your styles in separate CSS files. ## What is the difference with regular CSS and React Native's CSS? React Native's styling works a bit differently compared to regular CSS: - There is no cascade, CSS properties are not inherited from parent elements. - No complex CSS selectors. There is only support for simple CSS class selector that maps 1-to-1 with an element. - Many CSS properties are element specific, e.g. you can not give `Text` properties (`font-family`, etc.) to a `View` and vice versa. - React Native only implements a subset of CSS. The more complex CSS features are left out, and what you get is a set of CSS features that work well to do styling in both browsers and native apps. - There are some new styling properties in React Native that do not exist in regular CSS. Even with the above differences, React Native's CSS implementation is still almost fully compatible with the one in Web browsers. You can think of it as a stricter subset of the CSS that is used in browsers. The supported styling depends on the element that you want to style. You can have a look at the example apps, or this cheat sheet when writing your styles: https://github.com/vhpoet/react-native-styling-cheat-sheet If you plan to use the same CSS files for both React Native and Web, then I suggest that you build your app "React Native first". It is much easier to build the app with React Native's styling limitations, and then make it work for web using [React Native for Web](https://github.com/necolas/react-native-web). You can also use [Progressive Enhancement](https://en.wikipedia.org/wiki/Progressive_enhancement) thinking to build the common parts to be cross platform and adding some Web specific CSS styling. ## What limitations does React Native CSS modules have compared to Web CSS modules? - No support for `:global` or `:local` keywords (there is not global scope in React Native, so distinction between local and global is not needed.) - No support for `composes` keyword (probably not worth it to support because of the complexity, you can use Sass/Less/Stylus instead). - No support for `:import` keyword (you can use Sass/Less/Stylus instead), but the `:export` keyword is supported. - No support for using [classnames](https://github.com/JedWatson/classnames) module to handle multiple classnames (`classnames` outputs classnames as a string, which does not work in React Native). - No hot loading for Sass, LESS or Stylus files that are imported with `@import` yet. ## I added a new CSS file and React Native throws an error for a missing module You need to restart React Native's packager when you add a new file to your project. This is currently a limitation that will hopefully be fixed in the future. ## How do I use multiple classes for an element? You can use either the `[styles.class1, styles.class2].join` or the template literal syntax. Have a look at the documentation over here: [babel-plugin-react-native-classname-to-style#multiple-classes](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style#multiple-classes). You can also use the `styleName` syntax, which supports multiple classnames: [babel-plugin-react-native-stylename-to-style](https://github.com/kristerkari/babel-plugin-react-native-stylename-to-style) ## CSS transitions, animations and gradients are missing React Native does not currently support CSS transitions, animations or gradients. For animations and transitions you can use React Native's [Animated Javascript module](https://facebook.github.io/react-native/docs/animated.html). For linear gradients you can try to use a library like [react-native-linear-gradient](https://github.com/react-native-community/react-native-linear-gradient). ## Should I use React Native to build Web apps? Absolutely! React Native's `StyleSheet` module implements a subset of CSS. The more complex CSS features are left out, and what you get is a set of CSS features that work well to do styling in both browsers and native apps. React Native avoids many of the problems of scaling CSS. There is no CSS property inheritance between elements and no CSS selector specificity issues. You can not give a `` font properties that would get inherited, but you can give them directly to a `` element. React Native's elements like ``, `` and `` are simpler abstractions of the DOM elements that you use in browser. That means that implementing them in other platforms than React Native or the browser (e.g. React VR) is possible. Implementing the browser DOM in React Native would be way too complex. Have a look at these talks for more info: - [How Airbnb Is Using React Native](https://www.youtube.com/watch?v=8qCociUB6aQ) - [Nicolas Gallagher - Twitter Lite, React Native, and Progressive Web Apps](https://www.youtube.com/watch?v=tFFn39lLO-U) ================================================ FILE: docs/multiple-transformers.md ================================================ ### Using CSS and Sass (or some other CSS preprocessor) in the same project ### Step 1: Setup React Native CSS modules - [Setup React Native CSS modules with CSS support](setup-css.md) - [Setup React Native CSS modules with PostCSS support](setup-postcss.md) - [Setup React Native CSS modules with Sass support](setup-sass.md) - [Setup React Native CSS modules with Less support](setup-less.md) - [Setup React Native CSS modules with Stylus support](setup-stylus.md) ### Step 2: Modify Babel configuration In your project's root folder: #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add more extensions to `.babelrc` (or `babel.config.js`): ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css", "scss", "sass"] } ] ] } ``` ... or if you are using [Expo](https://expo.io/), to `babel.config.js` ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { extensions: ["css", "scss", "sass"] }, ], ], }; }; ``` --- #### For React Native v0.56 or older Add more extensions to `.babelrc`: ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css", "scss", "sass"] } ] ] } ``` --- #### For Expo SDK v30.0.0 or older Add more extensions to `.babelrc`: ```json { "presets": ["babel-preset-expo"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css", "scss", "sass"] } ] ] } ``` ### Step 3: Modify Metro bundler configuration In your project's root folder: #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Configure `metro.config.js` to use a custom transformer file and add more extensions: ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("./transformer.js"), }, resolver: { sourceExts: [...sourceExts, "css", "scss", "sass"], }, }; })(); ``` --- #### For React Native v0.56 or older Configure `rn-cli.config.js` to use a custom transformer file and add more extensions: ```js module.exports = { getTransformModulePath() { return require.resolve("./transformer.js"); }, getSourceExts() { return ["js", "jsx", "css", "scss", "sass"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older Configure `app.json` to use a custom transformer file and add more extensions: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "css", "scss", "sass"], "transformer": "./transformer.js" } } } ``` ### Step 4: configure transformer Create a `transformer.js` file: ```js // For React Native version 0.59 or later var upstreamTransformer = require("metro-react-native-babel-transformer"); // For React Native version 0.56-0.58 // var upstreamTransformer = require("metro/src/reactNativeTransformer"); // For React Native version 0.52-0.55 // var upstreamTransformer = require("metro/src/transformer"); // For React Native version 0.47-0.51 // var upstreamTransformer = require("metro-bundler/src/transformer"); // For React Native version 0.46 // var upstreamTransformer = require("metro-bundler/build/transformer"); var sassTransformer = require("react-native-sass-transformer"); var cssTransformer = require("react-native-css-transformer"); module.exports.transform = function ({ src, filename, options }) { if (filename.endsWith(".scss") || filename.endsWith(".sass")) { return sassTransformer.transform({ src, filename, options }); } else if (filename.endsWith(".css")) { return cssTransformer.transform({ src, filename, options }); } return upstreamTransformer.transform({ src, filename, options }); }; ``` ================================================ FILE: docs/setup-css-variables.md ================================================ ## Setup CSS variables support _! Please make sure that you are using the latest version of Sass, LESS, or Stylus transformer before doing the setup. !_ Using [postcss-css-variables](https://github.com/MadLittleMods/postcss-css-variables#readme) you can use most of CSS variables features, including selector cascading with some caveats, because this can only see the CSS, not the potentially dynamic HTML and DOM the CSS is applied to. If you are already using `react-native-css-transformer`, then need to switch to use `react-native-postcss-transformer` (please refer to the setup documentation) and add a PostCSS config with [postcss-css-variables](https://github.com/MadLittleMods/postcss-css-variables#readme) plugin. ### For Typescript users If you are using the typed transformers (e.g. generates `mystyles.d.scss` typings for Sass files), then you can use the normal transformers for Sass/Less/Stylus and a typed transformer for PostCSS. This is because with CSS variables you are using two transformers together and only one of the transformers needs to create the types file. For example when using Sass: `react-native-sass-transformer` + `react-native-typed-postcss-transformer`. ### Step 1: Setup React Native CSS modules - [Setup React Native CSS modules with CSS support](setup-css.md) - [Setup React Native CSS modules with PostCSS support](setup-postcss.md) - [Setup React Native CSS modules with Sass support](setup-sass.md) - [Setup React Native CSS modules with Less support](setup-less.md) - [Setup React Native CSS modules with Stylus support](setup-stylus.md) ### Step 2: Install PostCSS dependencies Install [PostCSS](https://postcss.org/), [postcss-css-variables](https://github.com/MadLittleMods/postcss-css-variables#readme) plugin, and [react-native-postcss-transformer](https://github.com/kristerkari/react-native-postcss-transformer). ```sh yarn add postcss postcss-css-variables react-native-postcss-transformer --dev ``` ### Step 3: Configure PostCSS Add `postcss-css-variables` to your PostCSS configuration with [one of the supported config formats](https://github.com/michael-ciniawsky/postcss-load-config), e.g. `package.json`, `.postcssrc`, `postcss.config.js`, etc. ### Step 4: Setup `transformer.js` _This example is for Sass, if you are using Less or Stylus, switch `react-native-sass-transformer` to `react-native-less-transformer`/`react-native-stylus-transformer` and change the file extensions `.scss` and `.sass` to `.less`/`.styl`._ To make CSS variables work, we first need to render Sass to CSS, and then pass that to PostCSS. Create a `transformer.js` file to your project's root and do the following: ```js // For React Native version 0.59 or later var upstreamTransformer = require("metro-react-native-babel-transformer"); // For React Native version 0.56-0.58 // var upstreamTransformer = require("metro/src/reactNativeTransformer"); // For React Native version 0.52-0.55 // var upstreamTransformer = require("metro/src/transformer"); // For React Native version 0.47-0.51 // var upstreamTransformer = require("metro-bundler/src/transformer"); // For React Native version 0.46 // var upstreamTransformer = require("metro-bundler/build/transformer"); var sassTransformer = require("react-native-sass-transformer"); var postCSSTransformer = require("react-native-postcss-transformer"); module.exports.transform = function ({ src, filename, options }) { if (filename.endsWith(".scss") || filename.endsWith(".sass")) { return sassTransformer .renderToCSS({ src, filename, options }) .then((css) => postCSSTransformer.transform({ src: css, filename, options }) ); } else { return upstreamTransformer.transform({ src, filename, options }); } }; ``` ### Step 5: Setup Metro config In `metro.config.js` point the `babelTransformerPath` to `transformer.js` file: ```diff -babelTransformerPath: require.resolve("react-native-sass-transformer") +babelTransformerPath: require.resolve("./transformer.js") ``` ================================================ FILE: docs/setup-css.md ================================================ ## Setup CSS modules for React Native (with CSS support) Following libraries are needed: - [react-native-css-transformer](https://github.com/kristerkari/react-native-css-transformer) - Transforms CSS to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-classname-to-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style) - Transforms `className` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-css-transformer --dev ``` ### Step 4: Setup Babel configuration #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", ["react-native-platform-specific-extensions", { extensions: ["css"] }], ], }; }; ``` ### Step 5: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("react-native-css-transformer"), }, resolver: { sourceExts: [...sourceExts, "css"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "css"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("react-native-css-transformer"); }, getSourceExts() { return ["js", "jsx", "css"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "css"], "transformer": "node_modules/react-native-css-transformer/index.js" } } } ``` ### Step 6: Add some CSS to your project and use it inside a React component `styles.css`: ```css .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.css"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 7: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-less.md ================================================ ## Setup CSS modules for React Native (with Less support) Following libraries are needed: - [react-native-less-transformer](https://github.com/kristerkari/react-native-less-transformer) - Transforms Less to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-classname-to-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style) - Transforms `className` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-less-transformer less --dev ``` ### Step 4: Setup Babel configuration #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["less"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["less"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", ["react-native-platform-specific-extensions", { extensions: ["less"] }], ], }; }; ``` ### Step 5: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("react-native-less-transformer"), }, resolver: { sourceExts: [...sourceExts, "less"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "less"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("react-native-less-transformer"); }, getSourceExts() { return ["js", "jsx", "less"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "less"], "transformer": "node_modules/react-native-less-transformer/index.js" } } } ``` ### Step 6: Add some Less to your project and use it inside a React component `styles.less`: ```less .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.less"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 7: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-linting.md ================================================ ## Setup recommended linting (ESLint & stylelint) Setup [ESLint](https://eslint.org) and [stylelint](https://stylelint.io/) in your project to avoid common problems and to keep CSS consistent. - ESLint is used to warn for unused CSS. - stylelint is used to make sure that the CSS is compatible with both Web and React Native, and to warn for duplicate properties, vendor prefixes, incompatible units, etc. ### Step 1: Install ESLint, stylelint and plugins ```sh yarn add eslint eslint-plugin-css-modules stylelint stylelint-react-native stylelint-config-react-native-css-modules --dev ``` ### Step 2: Add configs Add these configs to your project's `package.json` (or use `.stylelintrc` and `.eslintrc` files). **ESlint:** ```json "eslintConfig": { "parserOptions": { "sourceType": "module", "ecmaVersion": 2017, "ecmaFeatures": { "jsx": true } }, "plugins": [ "css-modules" ], "extends": [ "plugin:css-modules/recommended" ] }, ``` **stylelint:** ```json "stylelint": { "extends": "stylelint-config-react-native-css-modules", "rules": { "declaration-block-no-duplicate-properties": true, "no-duplicate-selectors": true, "no-extra-semicolons": true, "no-eol-whitespace": true, "no-missing-end-of-source-newline": true } } ``` ### Step 3: Add npm script to run linters In your project's `package.json`, add a new command called `lint` to `scripts`, so that it looks like this: ```json "scripts": { "lint": "eslint . && stylelint '**/*.@(css|scss|sass|less|styl)'" } ``` _You can remove file extensions that you don't use from the stylelint command._ ### Step 4: Run linters Run `yarn lint` in a terminal window to see if there are any linting errors or warnings. ================================================ FILE: docs/setup-postcss.md ================================================ ## Setup CSS modules for React Native (with PostCSS support) Following libraries are needed: - [react-native-postcss-transformer](https://github.com/kristerkari/react-native-postcss-transformer) - Uses [PostCSS](https://github.com/postcss/postcss) to transform CSS to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-classname-to-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style) - Transforms `className` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-postcss-transformer postcss --dev ``` ### Step 4: Add your PostCSS config and install your PostCSS plugins Add your PostCSS configuration to [one of the supported config formats](https://github.com/michael-ciniawsky/postcss-load-config), e.g. `package.json`, `.postcssrc`, `postcss.config.js`, etc. ### Step 5: Setup Babel configuration > Remember to add additional extensions if needed. #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css", "pcss"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["css", "pcss"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { extensions: ["css", "pcss"] }, ], ], }; }; ``` ### Step 6: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("./postcss-transformer.js"), }, resolver: { sourceExts: [...sourceExts, "css", "pcss"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "css", "pcss"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("./postcss-transformer.js"); }, getSourceExts() { return ["js", "jsx", "css", "pcss"]; // <-- Add other extensions if needed. }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "css", "pcss"], "transformer": "./postcss-transformer.js" } } } ``` Create `postcss-transformer.js` file to your project's root and specify supported extensions: ```js // For React Native version 0.59 or later var upstreamTransformer = require("metro-react-native-babel-transformer"); // For React Native version 0.56-0.58 // var upstreamTransformer = require("metro/src/reactNativeTransformer"); // For React Native version 0.52-0.55 // var upstreamTransformer = require("metro/src/transformer"); // For React Native version 0.47-0.51 // var upstreamTransformer = require("metro-bundler/src/transformer"); // For React Native version 0.46 // var upstreamTransformer = require("metro-bundler/build/transformer"); var postcssTransformer = require("react-native-postcss-transformer"); var postCSSExtensions = ["css", "pcss"]; // <-- Add other extensions if needed. module.exports.transform = function ({ src, filename, options }) { if (postCSSExtensions.some((ext) => filename.endsWith("." + ext))) { return postcssTransformer.transform({ src, filename, options }); } return upstreamTransformer.transform({ src, filename, options }); }; ``` ### Step 7: Add some CSS to your project and use it inside a React component `styles.css`: ```css .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.css"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 8: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-responsive.md ================================================ ## Setup CSS modules for React Native (with CSS Media Queries & CSS Viewport Units support) Following library needs to be taken into use: - [babel-plugin-react-native-classname-to-dynamic-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-dynamic-style) - Transforms `className` property to `style` property and matches dynamic styles (media queries and viewport units) at runtime with React Native. ### Step 1: Setup React Native CSS modules - [Setup React Native CSS modules with CSS support](setup-css.md) - [Setup React Native CSS modules with PostCSS support](setup-postcss.md) - [Setup React Native CSS modules with Sass support](setup-sass.md) - [Setup React Native CSS modules with Less support](setup-less.md) - [Setup React Native CSS modules with Stylus support](setup-stylus.md) ### Step 2: Change the className Babel plugin to a dynamic one Remove old one: ```sh yarn remove babel-plugin-react-native-classname-to-style ``` Add new one: ```sh yarn add babel-plugin-react-native-classname-to-dynamic-style --dev ``` ### Step 3: Change Babel configuration `.babelrc` (or `babel.config.js`) ```diff "plugins": [ - "react-native-classname-to-style", + "react-native-classname-to-dynamic-style", ``` ### Step 4: Add some CSS with Media Queries and Viewport Units to your project and use it inside a React component `styles.css`: ```css .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 3vmax; } @media (orientation: landscape) { .blue { color: red; font-size: 10px; } } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.css"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 5: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-sass.md ================================================ ## Setup CSS modules for React Native (with Sass support) Following libraries are needed: - [react-native-sass-transformer](https://github.com/kristerkari/react-native-sass-transformer) - Transforms Sass to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-classname-to-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style) - Transforms `className` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-sass-transformer sass --dev ``` ### Step 4: Setup Babel configuration #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["scss", "sass"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["scss", "sass"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { extensions: ["scss", "sass"] }, ], ], }; }; ``` ### Step 5: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("react-native-sass-transformer"), }, resolver: { sourceExts: [...sourceExts, "scss", "sass"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "scss", "sass"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("react-native-sass-transformer"); }, getSourceExts() { return ["js", "jsx", "scss", "sass"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "scss", "sass"], "transformer": "node_modules/react-native-sass-transformer/index.js" } } } ``` ### Step 6: Add some Sass to your project and use it inside a React component `styles.scss`: ```scss .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.scss"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 7: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-stylename.md ================================================ ## Setup CSS modules for React Native (with styleName syntax) The `styleName` attribute and syntax are based on [babel-plugin-react-css-modules](https://github.com/gajus/babel-plugin-react-css-modules#conventions). _This example only shows how to setup CSS support using the CSS transformer. Have a look at the setup documentation if you need PostCSS, Sass, Less or Stylus support (you need to use a different transformer and file extensions)._ Following libraries are needed: - [react-native-css-transformer](https://github.com/kristerkari/react-native-css-transformer) - Transforms CSS to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-stylename-to-style](https://github.com/kristerkari/babel-plugin-react-native-stylename-to-style) - Transforms special `styleName` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-stylename-to-style babel-plugin-react-native-platform-specific-extensions react-native-css-transformer --dev ``` ### Step 4: Setup Babel configuration #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ [ "react-native-stylename-to-style", { "extensions": ["css"] } ], [ "react-native-platform-specific-extensions", { "extensions": ["css"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ [ "react-native-stylename-to-style", { "extensions": ["css"] } ], [ "react-native-platform-specific-extensions", { "extensions": ["css"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ [ "react-native-stylename-to-style", { extensions: ["css"], }, ], [ "react-native-platform-specific-extensions", { extensions: ["css"], }, ], ], }; }; ``` ### Step 5: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("react-native-css-transformer"), }, resolver: { sourceExts: [...sourceExts, "css"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "css"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("react-native-css-transformer"); }, getSourceExts() { return ["js", "jsx", "css"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "css"], "transformer": "node_modules/react-native-css-transformer/index.js" } } } ``` ### Step 6: Add some CSS to your project and use it inside a React component `styles.css`: ```css .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue-text { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import "./styles.css"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 7: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-stylus.md ================================================ ## Setup CSS modules for React Native (with Stylus support) Following libraries are needed: - [react-native-stylus-transformer](https://github.com/kristerkari/react-native-stylus-transformer) - Transforms Stylus to a React Native compatible style object and handles live reloading - [babel-plugin-react-native-platform-specific-extensions](https://github.com/kristerkari/babel-plugin-react-native-platform-specific-extensions) - Transforms ES6 `import` statements to platform specific `require` statements if the platform specific files exist on disk. - [babel-plugin-react-native-classname-to-style](https://github.com/kristerkari/babel-plugin-react-native-classname-to-style) - Transforms `className` property to `style` property. ### Step 1: Install depencies to run React Native Make sure that you have `react-native-cli` installed (`npm install -g react-native-cli`) and [XCode](https://developer.apple.com/xcode/) (for iOS development) / [Android Studio](https://developer.android.com/studio/index.html) (for Android development) installed and working. - Go to "Building Projects with Native Code" tab and follow the guide: https://facebook.github.io/react-native/docs/getting-started.html ### Step 2: Create a new React Native app and test that it works e.g. ```sh react-native init AwesomeProject cd AwesomeProject ``` Start packager: ```sh yarn start ``` Run project on iOS simulator: ```sh react-native run-ios ``` ### Step 3: Install dependencies for React Native CSS modules ```sh yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-stylus-transformer stylus --dev ``` ### Step 4: Setup Babel configuration #### For React Native v0.57 or newer `.babelrc` (or `babel.config.js`) ```json { "presets": ["module:metro-react-native-babel-preset"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["styl"] } ] ] } ``` --- #### For React Native v0.56 or older `.babelrc` ```json { "presets": ["react-native"], "plugins": [ "react-native-classname-to-style", [ "react-native-platform-specific-extensions", { "extensions": ["styl"] } ] ] } ``` --- #### For Expo `babel.config.js` (older Expo versions use `.babelrc`) ```js module.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: [ "react-native-classname-to-style", ["react-native-platform-specific-extensions", { extensions: ["styl"] }], ], }; }; ``` ### Step 5: Setup Metro bundler configuration #### For React Native v0.57 or newer / Expo SDK v31.0.0 or newer Add this to `metro.config.js` in your project's root (create the file if you don't have one already): ```js const { getDefaultConfig } = require("metro-config"); module.exports = (async () => { const { resolver: { sourceExts }, } = await getDefaultConfig(); return { transformer: { babelTransformerPath: require.resolve("react-native-stylus-transformer"), }, resolver: { sourceExts: [...sourceExts, "styl"], }, }; })(); ``` If you are using [Expo](https://expo.io/), you also need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "config": "metro.config.js", "sourceExts": ["js", "jsx", "styl"] } } } ``` --- #### For React Native v0.56 or older If you are using React Native without Expo, add this to `rn-cli.config.js` in your project's root (create the file if you don't have one already): ```js module.exports = { getTransformModulePath() { return require.resolve("react-native-stylus-transformer"); }, getSourceExts() { return ["js", "jsx", "styl"]; }, }; ``` --- #### For Expo SDK v30.0.0 or older If you are using [Expo](https://expo.io/), instead of adding the `rn-cli.config.js` file, you need to add this to `app.json`: ```json { "expo": { "packagerOpts": { "sourceExts": ["js", "jsx", "styl"], "transformer": "node_modules/react-native-stylus-transformer/index.js" } } } ``` ### Step 6: Add some Stylus to your project and use it inside a React component `styles.styl`: ```styl .container { flex: 1; justify-content: center; align-items: center; background-color: #f5fcff; } .blue { color: blue; font-size: 30px; } ``` Add style import and `BlueText` component to `App.js`: ```jsx import React, { Component } from "react"; import { Text, View } from "react-native"; import styles from "./styles.styl"; const BlueText = () => { return Blue Text; }; export default class App extends Component<{}> { render() { return ( ); } } ``` ### Step 7: Restart packager and clear cache Restart React Native packager and clear it's cache (important) to see the styles that you added. ```sh yarn start --reset-cache ``` ================================================ FILE: docs/setup-typescript.md ================================================ _Have a look at the example app to see how you can use CSS modules and Typescript for both React Native and web browsers using the same code._ :point_right: [react-native-css-modules-with-typescript-example](https://github.com/kristerkari/react-native-css-modules-with-typescript-example) ## Setup CSS modules for React Native + Typescript ### Step 1: Setup React Native CSS modules _If you want Typescript types (`.d.ts` files) being generated your CSS/Sass/Less/Stylus files, then follow any of the guides below, but install a "typed" transformer instead of the regular one. E.g. `react-native-sass-transformer` -> `react-native-typed-sass-transformer`. That way you can avoid unused CSS classes in your app._ - [Setup React Native CSS modules with CSS support](setup-css.md) - [Setup React Native CSS modules with PostCSS support](setup-postcss.md) - [Setup React Native CSS modules with Sass support](setup-sass.md) - [Setup React Native CSS modules with Less support](setup-less.md) - [Setup React Native CSS modules with Stylus support](setup-stylus.md) ### Step 2: Install Typescript dependencies #### For React Native v0.57 or newer ``` yarn add typescript --dev ``` #### For React Native v0.56 or older ``` yarn add react-native-typescript-transformer typescript --dev ``` ### Step 3: Install custom `@types/react-native` package with `className` support This package is needed to get the `className` property to work correctly: - https://github.com/kristerkari/react-native-types-for-css-modules#installation ### Step 4: Check project's `tsconfig.json` Make sure that `jsx` property is set to `react-native` in Typescript's `compilerOptions`. This is important so that `className` property can be mapped to `style` property (won't work if `jsx` option is set to `react`). `tsconfig.json`: ```json "compilerOptions": { ... "jsx": "react-native" } ``` ### Step 5: Setup transformer to support CSS modules and Typescript #### For React Native v0.57 or newer _This step is not needed if you are using React Native v0.57 or newer._ #### For React Native v0.56 or older (Typescript is supported by default on React Native 0.57+) _This example only shows how to setup CSS support. Have a look at the setup documentation if you need PostCSS, Sass, Less or Stylus support._ In your project's root folder: `rn-cli.config.js` ```js module.exports = { getTransformModulePath() { return require.resolve("./transformer.js"); }, getSourceExts() { return ["ts", "tsx", "css"]; }, }; ``` `transformer.js` ```js // For React Native version 0.56 or later var upstreamTransformer = require("metro/src/reactNativeTransformer"); // For React Native version 0.52-0.55 // var upstreamTransformer = require("metro/src/transformer"); // For React Native version 0.47-0.51 // var upstreamTransformer = require("metro-bundler/src/transformer"); // For React Native version 0.46 // var upstreamTransformer = require("metro-bundler/build/transformer"); var cssTransformer = require("react-native-css-transformer"); var typescriptTransformer = require("react-native-typescript-transformer"); module.exports.transform = function ({ src, filename, options }) { if (filename.endsWith(".css")) { return cssTransformer.transform({ src, filename, options }); } else if (filename.endsWith(".ts") || filename.endsWith(".tsx")) { return typescriptTransformer.transform({ src, filename, options }); } return upstreamTransformer.transform({ src, filename, options }); }; ``` ================================================ FILE: docs/web-compatibility.md ================================================ ## Setup browser compatibility for a project that uses React Native CSS modules What you need is: - [Webpack](https://webpack.js.org/) (or some other bundler) - [React Native for Web](https://github.com/necolas/react-native-web) ### Step 1: Setup React Native CSS modules - [Setup React Native CSS modules with CSS support](setup-css.md) - [Setup React Native CSS modules with PostCSS support](setup-postcss.md) - [Setup React Native CSS modules with Sass support](setup-sass.md) - [Setup React Native CSS modules with Less support](setup-less.md) - [Setup React Native CSS modules with Stylus support](setup-stylus.md) ### Step 2: Install Webpack + React Native for Web #### Install Webpack dependencies for React Native v0.56 or newer (uses Babel 7): ```sh yarn add babel-loader babel-core@7.0.0-bridge.0 @babel/preset-env babel-preset-react@7.0.0-beta.3 webpack webpack-cli css-loader react-hot-loader style-loader webpack-dev-server --dev ``` for React Native v0.55 or older (uses Babel 6): ```sh yarn add babel-loader babel-core babel-preset-env babel-preset-react webpack webpack-cli css-loader react-hot-loader style-loader webpack-dev-server --dev ``` #### Install React Native for Web dependencies ```sh yarn add react-art react-dom react-native-web --save ``` ### Step 3: Add Webpack config In your project's root folder, add a file called `webpack.config.js`: **For React Native v0.56:** Use the config below, but change `babel-loader`'s presets to: ```js presets: ["@babel/preset-env", "react", "react-native"]; ``` **For React Native v0.55 or older:** Use the config below, but change `babel-loader`'s presets to: ```js presets: ["babel-preset-env", "react", "react-native"]; ``` **For React Native v0.57 or newer:** ```js const webpack = require("webpack"); module.exports = { entry: ["react-hot-loader/patch", "./index.web.js"], devServer: { hot: true, }, plugins: [ new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin(), ], module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: "babel-loader", query: { babelrc: false, configFile: false, presets: [ "@babel/preset-env", "react", "module:metro-react-native-babel-preset", ], plugins: ["react-hot-loader/babel"], }, }, { test: /\.css$/, use: [ { loader: "style-loader", }, { loader: "css-loader", options: { modules: true, localIdentName: "[path]___[name]__[local]___[hash:base64:5]", }, }, ], }, ], }, resolve: { alias: { "react-native": "react-native-web", }, extensions: [".web.js", ".js", ".web.jsx", ".jsx"], mainFields: ["browser", "main"], }, }; ``` If you need support for Sass or other CSS pre/post processors, have a look at the documentation for a specific webpack loader, e.g. https://github.com/webpack-contrib/sass-loader ### Step 4: Add index.html and index.web.js In your project's root folder, add a file called `index.web.js`: ```js import { AppRegistry } from "react-native"; import App from "./App"; AppRegistry.registerComponent("AwesomeProject", () => App); AppRegistry.runApplication("AwesomeProject", { rootTag: document.getElementById("react-app"), }); if (module.hot) { module.hot.accept(); } ``` Also add a file called `index.html` to your project's root folder: ```html AwesomeProject
``` ### Step 5: Add npm script to start Webpack development server In your project's `package.json`, add a new command called `web` to `scripts`, so that it looks like this: ```json "scripts": { "web": "NODE_ENV=development webpack-dev-server --mode development" } ``` ### Step 6: Start Webpack development server and open the project in a browser Run `yarn web` in a terminal window and if there are no warnings, open `http://localhost:8080` in a web browser to see your React Native project running in a browser environment.