(2 minute read)
This post outlines how to get custom fonts working reliably in React Native (tested in 0.40).
Most crucially, our font files have to be named correctly. I recommend using the following format for file names:
Place the font files in a folder, e.g:
my-react-native-project/
package.json
ios/
android/
app/
fonts/
OpenSans...
...
Then add the following to package.json:
"rnpm": {
"assets": [
"app/fonts"
]
}
Then run:
$ react-native link
Now rebuild for iOS and Android and the font files will be included correctly.
If we wish to use the OpenSans-SemiBoldItalic font for a given element this is how we would specify it in our styles:
// iOS
{
fontFamily: 'OpenSans',
fontWeight: '600',
fontStyle: 'italic'
}
// Android
{
fontFamily: 'OpenSans-SemiBoldItalic'
}
Thus, for iOS we need to map filenames to three styles. You may need to experiment to find the right mapping values for your custom font, but for Open Sans these are the values:
We can embed this information into our code and provide a helper function - fontMaker() - to help with cross-platform style generation:
// we define available font weight and styles for each font here
const font = {
OpenSans: {
weights: {
ExtraBold: '800',
Bold: '700',
SemiBold: '600',
Light: '300',
Normal: '400'
},
styles: {
Italic: 'italic'
}
},
Verdana: ...,
Tahoma: ...,
...
}
// generate styles for a font with given weight and style
export const fontMaker = (options = {}) => {
let { weight, style, family } = Object.assign({
weight: null,
style: null,
family: 'OpenSans'
}, options)
const { weights, styles } = font[family]
if (Platform.OS === 'android') {
weight = weights[weight] ? weight : ''
style = styles[style] ? style : ''
const suffix = weight + style
return {
fontFamily: family + (suffix.length ? `-${suffix}` : '')
}
} else {
weight = weights[weight] || weights.Normal
style = styles[style] || 'normal'
return {
fontFamily: family,
fontWeight: weight,
fontStyle: style
}
}
}
Now we can easily use customs font using the fontMaker method:
fontMaker({ weight: 'SemiBold', style: 'Italic' })
/*
// iOS
{
fontFamily: 'OpenSans',
fontWeight: '600',
style: 'italic'
}
// Android
{
fontFamily: 'OpenSans-SemiBoldItalic'
}
*/
fontMaker({ weight: 'Light', family: 'Verdana' })
/*
// iOS
{
fontFamily: 'Verdana',
fontWeight: '300',
fontStyle: 'normal'
}
// Android
{
fontFamily: 'Verdana-Light'
}
*/
fontMaker({ family: 'Tahoma' })
/*
// iOS
{
fontFamily: 'Tahoma',
fontWeight: 'normal',
fontStyle: 'normal'
}
// Android
{
fontFamily: 'Tahoma'
}
*/
And that's it, all done 😃.
Massive thanks to https://blog.bam.tech/developper-news/add-a-custom-font-to-your-react-native-app for helping me get this working.