We’ve been using React Native for over a year now and we’re loving how quickly we can create feature-rich and performant apps for iOS and Android. So far we’ve put 4 React Native apps into production. With each project we tried things out and learned lots along the way. We want to share some of that in this series of posts about React Native.
At first, styling in React Native appeared to be pretty simple. There were so many other things to figure out with React Native; making apps look pretty seemed to entail just writing CSS rules in camelCase rather than whatever-case-this-is (kebab-case?)
…looks like this in a React Native stylesheet:
For us, this made writing React Native stylesheets feel very familiar. But after we scratched the surface it became clear that styling in React Native is very different to styling on the web. In fact, rule names and flexbox are just about the only thing that CSS and React Native styles have in common.
Stylesheets are scoped to components
In the browser, stylesheets are scoped at the page level. For a single page web app, this means that each stylesheet impacts the entire app. Individual styles rules are applied to DOM elements by scoping them within selector blocks. There are many different ways of selecting DOM elements, and complex rules that define which selectors take precedence over others.
With React Native, styles have no effect on your app unless you specifically pass them to your components. There is no concept of a ‘selector’ because components and styles are tightly coupled. It means you can use the same name for styles across multiple stylesheets without causing side effects, so this is fine:
React Native style names are literally just the names given to sets of styling rules, so there is much less to consider when naming them.
Styles aren’t inherited by default
On the web, DOM elements inherit some of their parent’s style by default. These are mostly text-related styles, and it means you can do things like this:
The equivalent in React Native works like this:
Components can of course be designed to pass style props down to child components. React Native’s <Text/> component does this. A <Text/> component that is the child of another <Text/> component, will inherit its styles:
In practice, sharing text styles by nesting <Text/> components has limited usage as <Text/> doesn’t allow most other React Native components to be its children.
Stylesheets are completely programmable
Fewer styling options
Compared to CSS, React Native’s styling options are pretty sparse right now. Measurement units are all in pixels, there are no gradient options, no animations and no media queries.
Some of these may never become part of React Native’s styles — animations, for example, are supported separately. Viewport dimensions can be queried with the Dimensions object and these can be used to declare styles conditionally.
On top of that, the only layout model available is flexbox. There is no ‘display’ rule, so you can’t use a table layout, floats or the new grid layout.
New Styling Patterns
It’s taken some effort to unlearn the concepts and habits of web development, but we’ve realised these differences also provide an opportunity. Many of the norms and tools around CSS are designed to solve problems that React Native doesn’t have. By setting them aside, we can develop new practices that keep styling from becoming brittle, making apps maintainable, consistent and understandable. These are practices that can also translate back to web development too with CSS-in-JS.
Coming soon, in Part 2, I'll talk about some patterns, conventions and tools we’ve tried out, what we’ve found useful and what we’ve tried to avoid.
Illustrations by Sam Russell Walker
We’re excited to be running a very different type of workshop at the Digital Content Summit 2017 in London next Tuesday 23 May.
Machine Learning, Artificial Intelligence, Deep Learning — I’m constantly being told that one (or all) of these will soon replace me in my job.