react-native-webview: [iOS]: Custom Font not working

Bug description: On iOS, custom fonts are not used within the WebView. I followed the instructions on a few prior bug reports but I can’t get the custom font running on iOS.

To Reproduce:

To generate the html for a WebView, I created this function

export const generateHtml = (content, textColor, fontFileName = 'NeuzeitOffice-Regular', fileFormat = 'ttf') => {

  const fileUri = Platform.select({
    ios: `${fontFileName}.${fileFormat}`,
    android: `file:///android_asset/fonts/${fontFileName}.${fileFormat}`
  })

  return (
    `
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
          <style media="screen" type="text/css">

            html, body {
              height: 100%;
              width: 100%;
              margin: 0;
              background-color: transparent;

              @charset "UTF-8";
              @font-face {
                font-family: ${fontFileName};
                src: url('${fileUri}'), local('${fontFileName}'), format('${fileFormat === 'ttf' ? 'truetype' : 'opentype'}');
              };

              font-size: 15px;
              line-height: 22px;
              text-align: left;
              color: ${textColor};
            }

          </style>
      </head>
      <body>
        ${content}
      </body>
    `
  )
}

I use it like this:

import { ActivityIndicator, View } from 'react-native'
import { WebView } from 'react-native-webview'

const html = generateHtml(content, '#FFF')

<WebView
            pointerEvents='none'
            scrollEnabled={false}
            source={{ html }}
            renderLoading={() => <View style={{ flex: 1 }} ><ActivityIndicator size='small' color='#FFF' /></View>}
            startInLoadingState

            allowFileAccess
            allowUniversalAccessFromFileURLs
            allowingReadAccessToURL='file:///assets/fonts'

          />

I tried to use the last 3 properties to get using the custom font on iOS running but it didn’t help.

I also tried it on a real Device - not only on the Simulator.

Expected behavior:

As this code works perfectly fine on Android, I would like to know what I have to do to make it run on iOS too. It would be great to include an example in the documentation. I’d like to contribute it to the documentation if I learn how to do it.

Environment:

  • OS: iOS
  • OS version: iOS 13.0 and iOS 13.2
  • react-native version: 0.61.2
  • react-native-webview version: 7.4.2

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 7
  • Comments: 53 (3 by maintainers)

Most upvoted comments

Here is a Hello World app with custom font in react-native-webview that works both on Android and iOS. Hope this will help.

https://github.com/mohammad-haque/react-native-webview-custom-font

I have a solution, you guys can use this tool https://transfonter.org to transform the font to base64 and add the generated css to html, I have tested and it working https://imgur.com/MMhMrQg

Using base64 coded font is really a hacky way of achieving which supposed to be a very simple thing.

It turns out (for me at least) all I need is to use baseUrl along with html:

<WebView
 originWhitelist={['*']}
 source={{
    baseUrl: '', // this makes it to work for ios, for android it works without this
    html: htmlContent, }}
/>
export const generateAssetsFontCss = (
	fontFamily: string,
	fileFormat: fontFormats = "ttf"
) => {
	const fileName = Platform.select({
		ios: `${fontFamily}.${fileFormat}`,
		android: `file:///android_asset/fonts/${fontFamily}.${fileFormat}`
	});

	return `
	@font-face {
        	font-family: '${fontFamily}';
        src: local('${fontFamily}'), url('${fileName}') format('${
		fileFormat === "ttf" ? "truetype" : "opentype"
	}');
	}
	`;
};

just checked, we have changed generateAssetsFontCss this way. local has been changed. local('${fontFamily}')

@brandtnewww i basically declared a font-face like this:

@font-face { font-family: 'Apple Chancery'; src: url(data:application/font-woff;charset=utf-8;base64,YourFontInBase64Format) format('woff'); font-weight: normal; font-style: normal; }

and it works both on android and ios. I guess the reason that custom fonts aren’t rendered on WebView is that the WebView cannot seem to recognize dependencies of the css file which is already a dependency from the html or whatever you’re using. In conclusion i think WebView just can’t reach nested imports like this. With this way we completely embedded the font to css. So it can be seen by WebView.

@punksta I got my current solution from there (https://github.com/react-native-community/react-native-webview/issues/326#issuecomment-510005798) but it was written for React Native 0.57 - maybe something changed? It doesn’t work for me on iOS.

I code, i think right but not work, until i copy https://github.com/mohammad-haque/react-native-webview-custom-font/blob/master/App.tsx that work perfect 😄

I use this tool for generating base64 font-face then it’s working fine https://amio.github.io/embedded-google-fonts/

Is there any workaround to load custom fonts in IOS? facing the same issue.

@brandtnewww Did you find a solution for this?