React Native course ยท Module 2: Lists and styles

StyleSheet - Advanced Styling

4 min read ยท
In this lesson4

StyleSheet is the foundation of styling in React Native. Let's explore advanced techniques!

Creating Styles

import { View, Text, StyleSheet } from 'react-native';

export default function StyleExample() {
  return (
    <View style={styles.container}>
      {/* Single style */}
      <Text style={styles.title}>Title</Text>

      {/* Combining styles (array) */}
      <Text style={[styles.text, styles.bold]}>Bold text</Text>

      {/* Conditional styles */}
      <Text style={[styles.text, isActive && styles.active]}>
        Conditional style
      </Text>

      {/* Inline + StyleSheet */}
      <Text style={[styles.text, { color: 'red' }]}>
        Inline override
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
  },
  text: {
    fontSize: 16,
  },
  bold: {
    fontWeight: 'bold',
  },
  active: {
    color: '#3498db',
  },
});

Flexbox in React Native

Flexbox works similarly to CSS, but with a few differences:

import { View, Text, StyleSheet } from 'react-native';

export default function FlexboxExample() {
  return (
    <View style={styles.container}>
      {/* Flex direction - column by default! */}
      <View style={styles.column}>
        <View style={styles.box1} />
        <View style={styles.box2} />
        <View style={styles.box3} />
      </View>

      {/* Row direction */}
      <View style={styles.row}>
        <View style={styles.box1} />
        <View style={styles.box2} />
        <View style={styles.box3} />
      </View>

      {/* Flex grow */}
      <View style={styles.row}>
        <View style={[styles.box1, { flex: 1 }]} />
        <View style={[styles.box2, { flex: 2 }]} />
        <View style={[styles.box3, { flex: 1 }]} />
      </View>

      {/* Justify & Align */}
      <View style={styles.centered}>
        <Text style={styles.text}>Centered</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    gap: 20,
    backgroundColor: '#1a5276',
  },
  column: {
    flexDirection: 'column', // Default in RN
    gap: 10,
  },
  row: {
    flexDirection: 'row',
    gap: 10,
  },
  centered: {
    flex: 1,
    justifyContent: 'center', // Main axis
    alignItems: 'center',      // Cross axis
    backgroundColor: '#2c3e50',
    borderRadius: 12,
  },
  box1: {
    width: 60,
    height: 60,
    backgroundColor: '#e74c3c',
    borderRadius: 8,
  },
  box2: {
    width: 60,
    height: 60,
    backgroundColor: '#2ecc71',
    borderRadius: 8,
  },
  box3: {
    width: 60,
    height: 60,
    backgroundColor: '#3498db',
    borderRadius: 8,
  },
  text: {
    color: '#fff',
    fontSize: 18,
  },
});

Position: absolute

import { View, Text, StyleSheet } from 'react-native';

export default function PositionExample() {
  return (
    <View style={styles.container}>
      <View style={styles.card}>
        <Text style={styles.cardTitle}>Treasure card</Text>

        {/* Badge in the top right corner */}
        <View style={styles.badge}>
          <Text style={styles.badgeText}>NEW</Text>
        </View>

        {/* Icon in the bottom left corner */}
        <View style={styles.icon}>
          <Text>โ—†</Text>
        </View>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#1a5276',
  },
  card: {
    width: 250,
    height: 150,
    backgroundColor: '#2c3e50',
    borderRadius: 16,
    padding: 20,
  },
  cardTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#fff',
  },
  badge: {
    position: 'absolute',
    top: -10,
    right: -10,
    backgroundColor: '#e74c3c',
    paddingHorizontal: 10,
    paddingVertical: 4,
    borderRadius: 12,
  },
  badgeText: {
    color: '#fff',
    fontSize: 12,
    fontWeight: 'bold',
  },
  icon: {
    position: 'absolute',
    bottom: 10,
    left: 10,
    width: 40,
    height: 40,
    backgroundColor: '#f39c12',
    borderRadius: 20,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

Shadows

import { View, Text, StyleSheet, Platform } from 'react-native';

export default function ShadowExample() {
  return (
    <View style={styles.container}>
      {/* iOS shadow */}
      <View style={styles.cardIOS}>
        <Text style={styles.text}>iOS Shadow</Text>
      </View>

      {/* Android shadow (elevation) */}
      <View style={styles.cardAndroid}>
        <Text style={styles.text}>Android Elevation</Text>
      </View>

      {/* Cross-platform shadow */}
      <View style={styles.cardCrossplatform}>
        <Text style={styles.text}>Cross-platform</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 30,
    backgroundColor: '#ecf0f1',
  },
  cardIOS: {
    width: 200,
    padding: 20,
    backgroundColor: '#fff',
    borderRadius: 12,
    // iOS only
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.3,
    shadowRadius: 8,
  },
  cardAndroid: {
    width: 200,
    padding: 20,
    backgroundColor: '#fff',
    borderRadius: 12,
    // Android only
    elevation: 8,
  },
  cardCrossplatform: {
    width: 200,
    padding: 20,
    backgroundColor: '#fff',
    borderRadius: 12,
    // Both platforms
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 4 },
        shadowOpacity: 0.3,
        shadowRadius: 8,
      },
      android: {
        elevation: 8,
      },
    }),
  },
  text: {
    textAlign: 'center',
    fontSize: 16,
  },
});
Code for this lesson: App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.card}>
        <Text style={styles.emoji}>{'><>'}</Text>
        <Text style={styles.name}>Coral fish</Text>
        <Text style={styles.description}>Resident of the Atlantis reefs</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#aed6f1',
  },
  card: {
    width: 220,
    padding: 20,
    backgroundColor: '#fff',
    alignItems: 'center',
    // TODO: add borderRadius: 16 to round the card corners
    // TODO: add the iOS shadow:
    //   shadowColor: '#000',
    //   shadowOffset: { width: 0, height: 4 },
    //   shadowOpacity: 0.25,
    //   shadowRadius: 8,
    // TODO: add the Android shadow: elevation: 8,
  },
  emoji: {
    fontSize: 48,
    marginBottom: 8,
  },
  name: {
    fontSize: 18,
    fontWeight: '600',
    color: '#2c3e50',
  },
  description: {
    fontSize: 14,
    color: '#7f8c8d',
    marginTop: 4,
  },
});

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Which justifyContent value distributes items evenly with equal spacing between them?

  2. 2. What does position: 'absolute' do in React Native?

Hands-on tasks in the game

  • Vertical ordering

    Arrange justifyContent values from smallest to largest spacing at the edges:

  • Click in order

    Click the shadow properties in the correct order (iOS):

  • Code editor

    Complete the styles for a card with a shadow effect.

Useful articles