A Year of React Native: Styling Part 1
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?)
React Native uses Facebook’s Yoga layout engine, which implements the flexbox spec and borrows CSS rule names, so CSS like this:
…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:
This also demonstrates how a style name is different to a class name (or any other selector name). In the browser, a class name needs to have meaning in the context of your whole webpage or application. That meaning may also need to represent more than just the element’s appearance but also its behaviour and purpose, particularly if it is reused for applying JavaScript logic.
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
As a stylesheet language, CSS is very limited in its ability to compute values. There are a few functions you can use such as calc(), and CSS variables are mostly supported in modern browsers. Beyond that, logic to compute styles dynamically needs to take place elsewhere, either by compiling stylesheets from another language (such as SASS) or in JavaScript in the browser.
In React Native, styles are defined in JavaScript. Having a programming language at your fingertips when styling opens up a wealth of possibilities.
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.
In Part 2, read about some patterns, conventions and tools we’ve tried out, what we’ve found useful.
If you have any questions or comments, you can find me @samueljmurray or @madebymany
Illustrations by Sam Russell Walker
Continue reading
Why Slack’s new search functionality is my favourite machine intelligence case study
Machine Learning, Artificial Intelligence, Deep Learning — I’m constantly being told that one (or all) of these will soon replace me in my job.