Daniel Idaszak React Native Developer at Netguru.

Why you should use Tailwind CSS with React Native

5 min read 1567

Tailwindcss React Native

When it comes to styling, React Native is in a pretty good spot. The built-in StyleSheet approach allows you to easily decouple the styles outside of JSX.

Sticking with React Native is usually a good idea, however it’s not without its own flaws. For one, it can be difficult to maintain styles in some external locations to reuse them. Another issue is managing proper naming conventions throughout the whole codebase. These issues can be resolved by using Tailwind in React Native.

Tailwind CSS completely changes the common approach to structuring CSS. While learning good code practices, developers quickly understand the importance of separation of concerns and splitting HTML and CSS between two files. Utility-first CSS seems completely different.

While there is some dissatisfaction with utility-first CSS coming from the developer community, it’s hard not to notice that Tailwind CSS is spiking in popularity. As a testament to its capabilities, Tailwind won an award for being the most adopted technology in The State of CSS 2020 survey.

So, what’s all the fuss about?

The utility-first class approach

In React Native, utility-first classes apply specific CSS properties to an element via its class or style property. The previous approach was to apply the style object to the element inline or reference the keys of the StyleSheet object with custom names applied.

The utility-first class approach allows you to simply add a class name to the element without needing to write custom styles. The decision to implement colors, typography, and structure, as well as provide a meaningful name to every styled element, is already made.

Tailwind gives you default values based on a solid design system, which results in consistency throughout the whole codebase. The learning curve may seem steep at first, but a developer who is proficient with that type of styling is able to work faster and in a more unified way. In addition, when a team uses a curated set of limited options, it’s easier to onboard a new developer and maintain consistency in your styling approach.

Lastly, because StyleSheets are reused, the codebase will stop growing and therefore easier to maintain.

Comparing the styled-components approach

Using styled-components is a great approach to styling for many reasons. However, not knowing at first glance whether a given component is React or a dumb-styled one can really slow things down. There is also a case of premature abstraction when we create components that are never reused.

We made a custom demo for .
No really. Click here to check it out.

Considering inline styles

When it comes to mixing code with Tailwind classes, one downside is that our code can quickly become verbose. Usually, we avoid inline styles at all costs because they negatively impact the readability of the code and may impair overall performance. There has been some suggestion from the developer community that StyleSheet approach is more performant than inline styles because it sends the whole object through the bridge at once. This is further clarified in the React Native Source Code.

Using Tailwind in React Native

While there are a few Tailwind packages well suited for React Native, I chose to use tailwind-react-native-classnames over tailwind-rn. tailwind-react-native-classnames is based on Classnames, a JavaScript utility that is used to improve Tailwind code on the Web, and therefore should be more familiar to developers using Tailwind CSS.

You can feel free to use different libraries as you please, but to me, the tagged template function approach is more visually appealing than styles passed to the array like in react-native-tailwindcss. You may also choose to simply import React Native components from the react-native-tailwind library and pass classes to the className prop.

There are two approaches to apply Tailwind classes to the element using the tailwind-react-native-classnames library. The basic one uses the ES6 tagged template function, which simply wraps class names in backticks like in the View element below. The second approach, which uses the Classnames package, allows for combining classes and handling more complex cases. Notice it in the Text element below:

import tw from 'tailwind-react-native-classnames';

const MyComponent = () => (
 <View style={tw`bg-blue-100`}>
   <Text style={tw.style('text-md', invalid && 'text-red-500')}>Hello</Text>
 </View>
);

React Native specific classes

We have two React Native classes for using platform-specific styles, which can be safely used with the tagged template function:

tw`ios:pt-4 android:pt-2`;

Tailwind class names

If you look at the menu on the left side of the Tailwind homepage, you’ll see several sections. Only some of these are relevant to React Native, but if you already know how to style components in React Native, you’ll quickly grasp what you can use. The most interesting sections for you to read are:

  • Layout: handles things like size and position
  • Flexbox: positioning elements with Flexbox
  • Spacing: classes for paddings and margins
  • Sizing: width and size classes
  • Typography: everything related to fonts, letter spacings, and text
  • Backgrounds: classes such as background color, image, and background opacity
  • Borders: radius, width, and color classes

There is also the Effects section where you can find opacity, but it is also possible to use classes. Use shadow in tailwind-react-native-classnames, which is located in the Box Shadow part of this section.

I also found this cheat sheet very useful. When trying to specify values, you can check for the proper code for element attributes. For example, when you set element width, you can use the w- class name and set the number w-40 to get 160px.

Comparing the StyleSheet and Tailwind CSS approach

Now, let’s build a simple layout using both approaches to compare Tailwind code to React Native code. For this example, I decided to create ScrollView with cards. A selected variable is passed to the component, which determines different backgrounds and colors of the title set.

Scrollview Cards Simple Layout Tailwind React-native

The whole code example for this article is located in the Git repository TailwindCssReactNative. You can also run the example from Expo. To start, we’ll build the component above using the StyleSheet approach:

const ListItem = ({
 uri,
 selected = false,
 text=""
}) => {
 return (
   <View style={[styles2.container, { ...(!selected && { backgroundColor: '#FFFFFF'})}]}>
     <View style={styles2.logoBackground}>
       <Image
         style={styles2.logo}
         source={ uri }
       />
     </View>
     <Text style={[styles2.text, { ...(!selected && { color: 'black'})}]}>{ text }</Text>
     <TouchableOpacity style={styles2.button}>
       <Text style={styles2.buttonText}>Details</Text>
     </TouchableOpacity>
   </View>
 )
}

As you can see, there are three props passed: uri for the image, text for the card title, and information about whether the component is selected or not. Based on whether selected is true or false, there are additional styles added like backgroundColor in the main view and color in Text component.

StyleSheet is used to style this component:

const styles2 = StyleSheet.create({
 container: {
   height: 256,
   width: 160,
   backgroundColor: 'rgba(59,130,246,1)',
   borderRadius: 12,
   padding: 15,
   margin: 5,
   alignItems: 'center',
   justifyContent: 'center',
   shadowColor: "#000",
   shadowOffset: {
     width: 0,
     height: 3,
   },
   shadowOpacity: 0.27,
   shadowRadius: 4.65,
   elevation: 6,
 },
 logoBackground:{
   width: 112,
   height: 112,
   borderRadius: 55,
   backgroundColor: '#E4F0FE'
 },
 logo: {
   width: 110,
   height: 110,
   borderRadius: 55
 },
 text: {
   color: 'white',
   fontSize: 18,
   fontWeight: 'bold',
   marginVertical: 10
 },
 button: {
   height: 40,
   width:'100%',
   backgroundColor: 'white',
   borderRadius: 20,
   alignItems: 'center',
   justifyContent: 'center',
   borderWidth: 1,
   borderColor: 'rgba(59,130,246,1)'
 },
 buttonText: {
   color: 'rgba(59,130,246,1)',
   fontSize: 17,
   fontWeight: 'bold'
 }
});

Now, we can build the same component with the Tailwind CSS approach and the tailwind-react-native-classnames library.

import React from 'react';
import { Text, View, TouchableOpacity, Image } from 'react-native';
import tw from 'tailwind-react-native-classnames';

export const ListItemTW = ({
 uri,
 selected = false,
 text=""
}) => (
 <View style={tw.style(
   'h-64 w-40 bg-blue-500 rounded-xl p-4 m-1 items-center justify-center shadow-lg',
   !selected && 'bg-white'
 )}>
   <View style={tw`w-28 h-28 rounded-full bg-indigo-50`}>
     <Image
       style={tw`w-28 h-28 rounded-full`}
       source={ uri }
     />
   </View>
   <Text style={tw.style(
     'text-white text-lg font-bold my-4',
     !selected && 'text-black'
   )}>
     { text }
   </Text>
   <TouchableOpacity
     style={
       tw`h-10 w-full bg-white rounded-full items-center justify-center border border-blue-500`
     }
   >
     <Text style={tw`text-lg text-blue-500 font-bold`}>
       Details
     </Text>
   </TouchableOpacity>
 </View>
)

So, what’s the difference? Notice that the Tailwind component has 36 lines compared to the normal component with StyleSheet that has 76 lines. The biggest drawback is that there are several long lines of code. Two of these are even multi-line on account of using Classname’s tw.style to join classes with conditionally added styles.

Using predefined styles has its pros and cons. As mentioned, benefits include faster development time and ease of maintenance. The biggest downside is that if you use some uncommon value, like a size or color that is not included in standard values, you would have to customize your styles. I think that the simplest approach would be to pass the style object to the tw.style, which should be recognized without any problem.

Summary

Using Tailwind CSS in your project provides unification of the whole codebase. Instead of giving custom names to the styles in StyleSheet, you can apply class names from the predefined list that is well known by many developers.

Additionally, the speed of development should be improved because it’s easier to style components and to assess what styles are applied to particular elements. This approach also has its downsides, like making some components too verbose. I believe that these problems can be resolved by either exporting some of the longer, reusable parts as styled-components or exporting them to the external file, but it’s up to you to decide the best approach for your project.

 

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Daniel Idaszak React Native Developer at Netguru.

3 Replies to “Why you should use Tailwind CSS with React Native”

  1. Is there any data comparing performance of this approach vs using StyleSheets? The code looks nice and like something I would like to try but without any performance comparison it is hard to decide if it’s a good idea to use it on a big project.

Leave a Reply