react-native, extended stylesheet and bootstrap

Learning how to use styles with react-native

I’ve learned that in order to apply styles to react-native, I would use StyleSheet as such:

// src/components/Header.jsx

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

function Header() {
  return (
    <View>
      <Text style={styles.heading}>Heading</Text>
    </View>
  )
}

const styles = StyleSheet.create({
  heading: {
    fontSize: 20,
    textAlign: 'center'
  }
})

In keeping with my goal of reusing as much of the existing app as possible, I want to use Bootstrap for basic styles. This can be achieved with StyleSheet.compose. (I’m also splitting the styles into its own module.)

// src/components/Header.jsx

import React from 'react';
import { View, Text } from 'react-native';
import styles from './Header.style.js';

function Header() {
  return (
    <View>
      <Text style={styles.heading}>Heading</Text>
    </View>
  )
}

// src/components/Header.style.js
import { StyleSheet } from 'react-native';
import BootstrapStyleSheet from 'react-native-bootstrap-styles';

const { bs } = new BootsrtapStyleSheet();

const styles = StyleSheet.create({
  heading: {
    fontSize: 20,
    textAlign: 'center'
  }
});
export default {
  ...styles,
  heading: StyleSheet.compose(bs.s1, styles.heading)
}

So far, it’s pretty straightforward.

Next, I want to use CSS features such as rem units and custom properties, in order to keep the native design as consistent with the web design as possible. From some searching around, the way to use those features is with react-native-extended-stylesheet. A simple example of its usage would look like so:

// src/components/Header.jsx
import React from 'react';
import { View, Text } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';

function Header() {
  return (
    <View>
      <Text style={styles.heading}>Heading</Text>
    </View>
  )
}

const styles = EStyleSheet.create({
  heading: {
    fontSize: '1.5rem',
    color: '$colorGreen'
  }
});

// src/index.jsx

import EStyleSheet from 'react-native-extended-stylesheet';

EStyleSheet.build({
  $rem: 16,
  $colorGreen: '#4caf50'
});

The EStyleSheet.build() is important to to define the variables, as well as “calculate” the stylesheets. However, because of that step, we can’t use EStyleSheet as a drop-in replacement for StyleSheet when it comes to style composition. At import time, the styles have not been “calculated” yet.

// This does NOT work

// src/components/Header.style.js
import { StyleSheet } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
import BootstrapStyleSheet from 'react-native-bootstrap-styles';

const { bs } = new BootsrtapStyleSheet();

const styles = EStyleSheet.create({
  heading: {
    fontSize: '1.5rem',
    color: '$colorGreen'
  }
});
export default {
  ...styles,
  heading: StyleSheet.compose(bs.s1, styles.heading)
}

In order to combine extended stylesheet with bootstrap styles, the styles need to be dynamically generated at component runtime:

// src/components/Header.jsx

import React from 'react'
import { View, Text } from 'react-native';
import getStyles from './Header.style.js';

function Header() {
  const styles = getStyles();
  return (
    <View>
      <Text style={styles.heading}>Heading</Text>
    </View>
  )
}

// src/components/Header.style.js

import { StyleSheet } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
import BootstrapStyleSheet from 'react-native-bootstrap-styles';

const { bs } = new BootstrapStyleSheet();

const styles = EStyleSheet.create({
  heading: {
    fontSize: '1.5rem',
    color: '$colorGreen'
  }
});

export default function () {
  return {
    ...styles,
    heading: StyleSheet.compose(bs.h1, styles.heading)
  }
}

There is a bit more wrapping layers in this workaround, but it achieves the goal of keeping the styles consistent with the usage of Bootstrap and CSS features.

comments powered by Disqus