Building Stylistic UIs with EmotionCSS for React Native
Building Stylistic UIs with Emotion-JS for React Native
Styling is an essential aspect of any mobile application. You can’t put enough emphasis on how important it is for mobile apps to have pleasing designs and effective uses of colors, in terms of continually engaging app users over the long run.If you’re into React Native development, by now you probably know there are different ways to style a React Native application. Common methods using StyleSheet to create to styles for each component screen, or encapsulating all of your styles in one file for the whole application.Using third-party libraries for styling is another way that can save you a lot of time in developing your React Native application. Some CSS-in-JS libraries, such as styled components and Emotion-JS are already regularly used among web developers. This tutorial is going to discuss and showcase how you can use Emotion-JS in a React Native application.Table of ContentsWhat is Emotion-JS?Installing Emotion-JSWriting your first Emotion StyleUsing Props in Emotion-JSInline StylingBuilding the Grocery UIAdding the user avatar imageAbsolute Positioning in React NativeMapping through a list of categoriesAdding Horizontal ScrollViewAdding a Vertical ScrollViewBuilding a card componentConclusionWhat is Emotion-JS 👩‍🎤?Emotion is a flexible CSS-in-JS library that follows the same blueprint to define styles inside a component’s file and use JavaScript and not CSS. In React Native, this is natively done by using theStyleSheet object.React Native tends to follow a certain convention when it comes to app styling. A CSS property for a background-color on the web is going to be:But in React Native, all CSS property names should be in camelCase. Thus, to write background color to React Native, you’ll need to write it as: backgroundColor: ...Developers coming from a web background—don’t worry about these new conventions! Using a third party library like Emotion-JS can help. You don’t have to switch between the context of conventions, apart from the properties and React Native’s own flexbox rules.Installing Emotion-JSTo get started, you’ll need to create a new React Native project. To quickly scaffold one, let’s use the power of Expo. Run the following command to install expo-cli and create a new React Native project using the same cli.When running the last command, the command line prompt will ask you a few questions. First one is, Choose a template. I chose expo-template-blank. Next, enter the display name of your app, and then either use npm or yarn to install dependencies. I’m going with yarn.Once all the dependencies are installed, you can open this project in your favorite code editor. The next step is to install the latest version of the emotion library.Guidelines in the Emotion npm package instruct that you need prop-types as the package installed with your project since the Emotion package itself depends on it. The next two packages in the above command are necessary in order to use the library itself. Also, make sure when you install these dependencies, you’re inside the React Native project directory.Writing your first Emotion Styled ComponentTo start the application in a simulator, run expo start. On successfully starting the application, you’ll be prompted with the default Expo app. Modify the App.js file as shown below to get started.Make changes to the component's render function (also shown below). Replace both View and Text with Container and Title. These new elements are going to be custom used of semantics from Emotion.Emotion-JS utilizes tagged template literals to style your components using back-ticks. When creating a component in React or React Native using this styling library, each component is going to have styles attached to it. Define the below styles in the same file after the App component.Notice the Container is a React Native View and has styling attached to it. Similarly, Title is utilizing the Text component from React Native. You will get the following result.Here’s the complete code for the App.js file:In the above snippet, note that we aren’t importing React Native core components such as View, Text, or a StyleSheet object. It’s that simple. It uses the same flexbox model that React Native Layouts use. The advantage here is that you get to apply similar context and an understandable syntax that you’ve been using in Web Development to style a React Native application.Using Props in Emotion-JSYou’ll often find yourself creating custom components for your apps. This does give you the advantage to stay DRY. Leveraging Emotion-JS is no different. You can use this programming pattern by building custom components that require their parent components. props are commonly known as additional properties to a specific component. To demonstrate this, create a new file called CustomButton.js.Inside this file, we’re going to create a custom button that requires props such as backgroundColor, textColor, and the text itself for the title of the button. You’re going to use TouchableOpacity and Text to create this custom button but without importing the react-native library and create a functional component namedCustomButton.The important thing to notice in the above snippet is that you can pass an interpolated function ${props => props...} to an Emotion-JS template literal to extend it to the component's style and keep the component re-usable.To see this custom button in action, import it to the App.js file, as shown below:On running the simulator, you’ll get the following result.Inline StylingAs a React Native developer, you’ve almost certainly used inline styling, and you know how beneficial they can be, especially in the prototype stage of an application.To leverage this technique using Emotion-JS, open CustomButton.js file and add an inline style like below. Do note that we aren’t modifying the existing styles defined previously.The style tag in the above snippet uses the css prop from @emotion/native library to allow us to add inline styles.Building the Grocery UIFrom this section on, you’re going to use what you’ve just learned about Emotion-JS to build a better UI in terms of complexity than a simple test and a button.Open up the App.js file. Declare a new ContainerView using the styled prop from Emotion-JS. Inside the back-ticks, you can write pure CSS code with the exact same syntax. The View element is like a div in HTML or web programming in general.You’ll also need to create another view called Titlebar inside Container. Inside Titlebar, there will be three new elements. One is going to be an image Avatar and the other two are text: Title and Name.You will get the following result in the simulator:Right now, everything is in the middle of the screen. We need the Titlebar and its contents at the top of the mobile screen. So styles for Container can be modified as below.You will get the following result:Adding the user avatar imageI’m going to use an image stored in the assets folder in the root of our project. You’re free to use your own image, but you can also download the assets for this project below:To create an image with Emotion-JS, you need the Image component from React Native core. You can use the source props to reference the image based on where it’s located.The styling for Avatar will begin with a width and a height 44 pixels each.You’ll get the following result:Absolute Positioning in React NativeNow notice that the avatar image and the text are piling up. They’re taking up the same space on the screen. To avoid this, you’re going to use the position: absolute CSS property.CSS properties such as padding and margin are used to add space between UI elements in relation to one another. This is the default layout position. However, you’re currently in a scenario where it will be beneficial to use absolute positioning of UI elements and place the desired UI element at the exact position you want.In React Native and CSS in general, if the position property is set to absolute, then the element is laid out relative to its parent. CSS has other values for position, but React Native only supports absolute.Modify the Avatar styles as below.Usually, with the position: absolute property, you’re going to use a combination of the following properties:topleftrightbottomIn the case above, we use top and left and both are set to 0 pixels. You’ll get the following output.Mapping through a list of categoriesInside the components/ folder, create a new file called Categories.js. This file is going to render a list of category items for the Grocery UI app.All the data is static right now. Import this component in App.js and place it after Titlebar.You will get the following result.There can be a number of categories. To make the names of categories dynamic, we can send it through the App.js file.In the above snippet, you are using map function from JavaScript to iterate through an array render a list of items, in this category names. Adding a key prop is required. To make this work, also modify Categories.js.There is no change in the UI:Adding Horizontal ScrollViewThis list is currently not scrollable. To make it scrollable, let’s place it inside a ScrollView. Open up the App.js file to place the categories inside a ScrollView. But first, import it from React Native core.You’ll notice not a single change in the UI. By default, scrollable lists in React Native using ScrollView are vertical. Make this horizontal by adding the prop horizontal.It works!To spruce it up a bit, add some inline styling using css prop.Now it looks better. Notice that there is an equal margin at the start of this horizontal list (before Fruits) as well as the end of the list ( Paper Goods).Adding a vertical ScrollViewNext step is to add a ScrollView that acts as a wrapper inside the Container view, such that the whole area becomes vertically scrollable. There’s a reason to do this. You’re now going to add items separated into two columns as images with text related to a particular category.Modify the App.js file:Notice that you’re adding another emotion component called Subtitle, which is nothing but text. It renders like below.Building a card componentIn this section, we’re going to create a card component that will hold an item’s image, the name of the item, and the price as text. Each card component is going to have curved borders and a box shadow. This is how it’s going to look.Create a new component file called Card.js inside the components directory. The structure of the Card component is going to be:Currently, it has static data, such as the image, title, and content. Let’s add the styles for each styled UI element in this file:The Container view has a default background color of white. This is useful in scenarios where you’re fetching images from third-party APIs. Also, it provides a background to the text area below the image.Inside the Container view, add an Image and wrap it inside a Cover view. In React Native, there two ways you can fetch an image.If you’re getting an image from the static resource, as in our case, you can use the source prop with the keyword require, which contains the relative path to the image asset stored in the project folder. In the case of networking images, or when getting an image from an API, you can use the same prop with a different keyword called uri. Here’s an example of an image being fetched from an API.The Cover view uses rounded corners with the overflow property. This is done to reflect the rounded corners. iOS clips the images if coming from a child component. In our case, the image is coming from a Card component, which is a child to the App component.The Image component takes the width and height of the entire Cover view.Now let’s import this component inside the App.js file after the Subtitle and see what results we get.After Subtitle, you’ll need to add a new view called ItemsLayout. This is going to be a layout that allows different cards to be divided between two columns in each row. This can be done by giving this view a flex-direction property of value row. ColumnOne and ColumnTwo are two empty views.On rendering the final result, it looks like this:ConclusionYou’ve completed the tutorial for creating a UI with Emotion-JS and integrating it into a React Native and Expo application. Now go ahead and create those beautiful UIs for your applications.You can find the complete code for this article in the GitHub repo 👇If you enjoyed reading this tutorial, please leave a 👏. You can always connect with me on Twitter.Editor’s Note: Heartbeat is a contributor-driven online publication and community dedicated to providing premier educational resources for data science, machine learning, and deep learning practitioners. We’re committed to supporting and inspiring developers and engineers from all walks of life.Editorially independent, Heartbeat is sponsored and published by Comet, an MLOps platform that enables data scientists & ML teams to track, compare, explain, & optimize their experiments. We pay our contributors, and we don’t sell ads.If you’d like to contribute, head on over to our call for contributors. You can also sign up to receive our weekly newsletters (Deep Learning Weekly and the Comet Newsletter), join us on Slack, and follow Comet on Twitter and LinkedIn for resources, events, and much more that will help you build better ML models, faster.