Skip to content

1.3 Styling

Learning Objectives

  • Organize styles using StyleSheet.create() for maintainability and performance
  • Understand why TypeScript helps catch invalid style properties through IDE autocomplete
  • Apply array-based style composition for conditional and dynamic styling
  • Discover how IDE support prevents style-related errors before runtime

In the previous lesson, we used inline styles which are JavaScript objects passed directly to components:

// Inline styles: works, but doesn't scale
<View
style={{
flex: 1,
backgroundColor: '#fff',
padding: 20,
borderRadius: 8,
}}
/>

Inline styles work fine for small examples, but as your app grows, you’ll notice two problems:

  1. You end up copying the same style object to multiple components.
  2. If you typo a property name, you won’t know until the app runs.

Using StyleSheet 1 solves both problems. It’s a React Native function that lets you define styles in one place, and references them by name.

import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
padding: 20,
borderRadius: 8,
},
});
// Now use styles.container, styles.card, etc.
<View style={styles.container}>{/* ... */}</View>;

StyleSheet.create() takes an object where keys are style names and values are style objects:

import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
// Key: your style name | Value: style object
container: {
flex: 1,
backgroundColor: '#fff',
padding: 20,
},
header: {
fontSize: 20,
fontWeight: 'bold',
color: '#333',
marginBottom: 16,
},
button: {
backgroundColor: '#536DFE',
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
},
});

The keys (container, header, button) are arbitrary. Choose names that describe the component or purpose. The values are the same style objects you’d write inline, but now they’re named and validated at startup. Once you’ve created a StyleSheet, reference the styles by name using dot notation:

Real apps need conditional styling: apply one style when a button is active, a different style when it’s inactive; apply hover styles in one context, a different style in another. React Native lets you compose styles using arrays. Pass [baseStyle, conditionalStyle] instead of a single style object.

In the array [styles.button, isActive && styles.buttonActive]:

  • styles.button is always applied
  • styles.buttonActive is only applied if isActive is true
  • If isActive is false, the && expression evaluates to false, which React Native ignores

By using TypeScript, your editor knows which style properties are valid. When you type styles. inside a component, your editor autocompletes all available style names. And if you make a typo, the editor catches it instantly.

const styles = StyleSheet.create({
card: {
padding: 16,
backgroundColor: '#fff',
borderRadius: 8,
},
});
// ✅ Your editor shows: [card]
<View style={styles.card} />
// ❌ Your editor shows an error: property 'caard' does not exist
<View style={styles.caard} />

TypeScript looks at your StyleSheet.create() call, infers the shape of the styles object, and tells your editor which properties are available. This prevents typos and wrong style names from ever reaching production.

We’ll formally introduce TypeScript in the next chapter, but the core idea is that types help your editor guide you toward correct code. StyleSheet is your first taste of that power.

Deeper Dive: Platform-Specific Styles

Mobile apps run on iOS and Android, and sometimes you need different styles for each platform. React Native provides a Platform 2 module to write platform-specific code:

import { StyleSheet, Platform } from 'react-native';
const styles = StyleSheet.create({
text: {
fontSize: 16,
fontFamily: Platform.OS === 'ios' ? 'Helvetica' : 'Roboto',
marginTop: Platform.OS === 'ios' ? 8 : 12,
},
});

You can also use Platform.select() for cleaner syntax:

import { StyleSheet, Platform } from 'react-native';
const styles = StyleSheet.create({
text: {
fontSize: 16,
fontFamily: Platform.select({
ios: 'Helvetica',
android: 'Roboto',
default: 'System', // Fallback for web
}),
},
});

This is useful when iOS and Android have different default fonts, touch targets, or spacing conventions.

To complete these exercises, follow these steps:

  1. Open the Snack by clicking the icon in the toolbar.
  2. If not already logged in, create a free Expo account and sign in.
  3. Click the blue Save button to fork the Snack to your account.
  4. Make changes to the code and save your work.
  5. Submit on Moodle by copy-pasting the Snack URL into the submission box.

Challenge: Refactor the inline styles to use StyleSheet.create().

  1. Create a styles constant at the bottom of your file using StyleSheet.create()
  2. Move all inline style objects into named style definitions
  3. Replace inline style props with style={styles.yourName}
  4. Test that the app still looks the same and that only the code structure changed
  5. Verify you can type styles. and see autocomplete in your editor
Hint

Look for all the inline style objects (between style={{ ... }}). Extract each one into a named key in StyleSheet.create():

const styles = StyleSheet.create({
container: { /* copy the inline object here */ },
card: { /* copy the inline object here */ },
text: { /* copy the inline object here */ },
});

Then replace each style={{ ... }} with style={styles.yourKey}.

  • StyleSheet.create() organizes styles into reusable, named objects defined once at app startup.
  • Validation during development prevents typos in style property names from reaching production.
  • TypeScript helps you in your IDE by showing you all valid style names when you type styles..
  • Array composition ([baseStyle, conditionalStyle]) enables conditional and dynamic styling.
  • Named styles are easier to find, update, and reuse across components.
  1. https://reactnative.dev/docs/stylesheet

  2. https://reactnative.dev/docs/platform