Front-end web developers are already comfortable using CSS to make web pages beautiful, and some of the techniques they use will transfer over to helping them build beautiful mobile apps in React Native. But as I’ll show you, a lot of your web-based style thinking will have to be altered to work in the React Native world. RN is a different ecosystem, and as such it requires a number of new approaches to make your app’s presentation layer succinct and tidy.
Some differences between web-based CSS and React Native styling
Firstly, React Native doesn’t have CSS in the same way the web does. You apply a subset of CSS properties using JSON objects like so:
Documentation examples often have these object literals being placed into style objects, which makes things a touch better:
Now you’ve got a separation of concerns, at least. And the “markup” (aka the render() method) is much cleaner.
But quite often in real-world projects, we’ll want to have lots of reusable styles to give our app a consistent look and feel. React Native does give us a simple way of simulating CSS “cascading” by applying multiple style objects inside brackets:
But as you can see, the more modular you get, the faster things get cluttered. Your code starts to become unwieldy, fast.
So now I’ll show you some architectural patterns you can use to make your styles a lot more modular, reusable, and easy to find, without making files like the one above into a complete mess.
A modular approach to React Native styling
The approach we currently use at ATTCK involves a few simple but clever guidelines that achieve a few things:
- separating global styles from those specific to components and screens allowing those global styles to be applied in components and screens, then built upon with more specificity if necessary
- keeping the render() methods from getting cluttered.
Have a style guide
When we create visual designs, we tend to put together visual design palettes first, including colors, typography, and so on. When this happens, those style guidelines should go directly into shared styles for the application.
In our React Native applications, we place these core styles into centrally located files that are structured a lot like SASS or LESS files.
Here’s what a sample project’s file structure looks like:
We export these as constants so we can share them across the app for reusability and style consistency.
Expanding on React Native “cascading”
The concept of cascading styles in RN is nowhere near as flexible as its web counterpart, and when used heavily, it clutters your render() method big-time.
Here’s what a failed attempt at using the RN cascade in a modular way might look like for a simple Card component:
Messy, right? It does achieve some level of DRYness by having reusable code in separate modules — Typography, Styles, Colors, and so on. But in order to actually apply those styles to different elements as needed, we fill the style attribute of each element with multiple style objects. This can get out of hand quickly.
An alternative approach to cascading
Our current approach declutters this mess by adding a middle tier. Reusable style objects still go into shared files, but then each component and screen has its own style file in which it maps all of its own styles to any combination of shared styles. It’s a small extra step that goes a long way in keeping things readable.
Typography.js / Color.js / etc. (core styles)
Card.style.js (component-specific styles)
Now we’ve got the benefits we seek in a good styling system:
- clean, readable components
- centralized, consistent styles
- an easy way to customize the component or screen as needed.
So this is the approach we’re currently using for styling React Native applications, and it’s given us great benefits in terms of readability, flexibility, and reuse of code. Let us know if you try it out!