Custom Font Not Working in WKWebView Swift
Reading the answers in the linked thread in DonMag's comment:
Using
@font-face
is mandatoryYou need multiple
@font-face
declarations to use multiple font files as a single font familyYou need to provide
baseURL
to make relative urls likeurl(OpenSans-Regular.ttf)
work
So, try this:
let htmlString = """
<style>
@font-face
{
font-family: 'Open Sans';
font-weight: normal;
src: url(OpenSans-Regular.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: bold;
src: url(OpenSans-Bold.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 900;
src: url(OpenSans-ExtraBold.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 200;
src: url(OpenSans-Light.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 500;
src: url(OpenSans-Semibold.ttf);
}
</style>
(Utils.aboutUsText)
"""
webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL) //<-
Or you can use a separate css file if you prefer:
let htmlString = """
(Utils.aboutUsText)
"""
webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
open-sans.css:
@font-face
{
font-family: 'Open Sans';
font-weight: normal;
src: url(OpenSans-Regular.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: bold;
src: url(OpenSans-Bold.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 900;
src: url(OpenSans-ExtraBold.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 200;
src: url(OpenSans-Light.ttf);
}
@font-face
{
font-family: 'Open Sans';
font-weight: 500;
src: url(OpenSans-Semibold.ttf);
}
Swift. Custom font for WebKit
To apply a custom font to an external HTML loaded in WKWebView (forced) Use the WKWebView HTML in the app if you want to display a custom font was added to the app in the CSS as shown below can be referred to (likely).
@font-face {
font-family: 'CustomFontFamily';
src: url('CustomFontFile.otf') format('opentype');
}
============================================
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
@IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
let url = URL(string: "https://example.com/")
let request = URLRequest(url: url!)
webView.load(request)
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
//to encode the font data in the app in the Base64
let yuGothicMedium = getDataString(otf: "YuGothic-Medium")
let yuGothicBold = getDataString(otf: "YuGothic-Bold")
//embedded encoded font data in the Data URI scheme CSS
let cssString = """
@font-face {
font-family: 'YuGothic';
src: url('data:font/otf;base64,\(yuGothicMedium)') format('opentype');
font-weight: normal;
}
@font-face {
font-family: 'YuGothic';
src: url('data:font/otf;base64,\(yuGothicBold)') format('opentype');
font-weight: bold;
}
"""
//JavaScript to add the CSS as a style element
because//cssString is to enter a new line template literal
let customFontJs = """
var style = document.createElement('style');
style.innerHTML = `\(cssString)`;
document.head.appendChild(style);
"""
//executes the JavaScript
webView.evaluateJavaScript(customFontJs, completionHandler: nil)
}
func getDataString(otf: String) -> String {
let path = Bundle.main.path(forResource: otf, ofType: "otf")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
return data.base64EncodedString()
}
}
WKWebView and Dynamic Type + Custom Fonts
I've finally managed to solve it, just add this chunk to the CSS
html {
font: -apple-system-body;
}
And leave body
like this, with no font-size
:
body {
font-family: 'MyCustomFont';
}
With just that, both things would work.
Use Custom Local Font in WKWebView
You did not provide a base URL when loading the HTML string, this will cause the font failing to load. Try accessing your bundle's main resource path, like this:
if let resourcePath = Bundle.main.resourcePath {
let url = URL.init(fileURLWithPath: resourcePath)
webView.loadHTMLString(getHtml(), baseURL: url)
}
WKWebView with custom font type and color
Firstly you can create a css file then add your fonts and styles inside this file
@font-face {
font-family: 'FONT_FAMILY';
src: local('FONT_FAMILY'),url('FONT_FILE_NAME.otf') format('opentype');
}
h1 {
font-family: 'FONT_FAMILY';
font-size: 20px;
font-weight: normal;
}
And load html string with css file
NSString *css = [NSString stringWithFormat:@""
""
""];
NSString *content = [NSString stringWithFormat:@""
"%@
"
@"", @"YOUR_TEXT"];
[_wkWebView loadHTMLString:[NSString stringWithFormat:@"%@%@", css, content]
baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"YOUR_CSS_FILE" ofType:@"css"]]];
You can change the style name h1 with yours
Xcode: Load custom locally stored font for remote content in WKWebView
I found a solution now. Maybe not the best but it's working.
First, I converted the Blastimo.ttf
file to a base64 encoded CSS embedded font with this converter.
This gives me the following (or similar):
@font-face {
font-family: 'Blastimo';
src: url(data:application/x-font-woff;charset=utf-8;base64,HERE_COMES_THE_QUITE_LONG_BASE64_CODE_CREATED_BY_THE_CONVERTER) format('woff');
font-weight: normal;
font-style: normal;
}
I imported/embedded a file called fonts.css
with this code (the code above from the converter) to my Xcode project. Add to targets
should be activated when importing/embedding.
In my ViewController.swift
file I have the following code (e.g. in viewDidLoad()
) to load the remote content and call the functions for the local CSS file:
if let url = URL(string: "https://www.example.com") {
let request = URLRequest(url: url)
webView.load(request)
}
injectToPage()
Additionally, these three functions have to be added somewhere to the ViewController.swift
file:
private func readFileBy(name: String, type: String) -> String {
guard let path = Bundle.main.path(forResource: name, ofType: type) else {
return "Failed to find path"
}
do {
return try String(contentsOfFile: path, encoding: .utf8)
} catch {
return "Unkown Error"
}
}
func injectToPage() {
let cssFile = readFileBy(name: "fonts", type: "css")
let cssStyle = """
javascript:(function() {
var parent = document.getElementsByTagName('head').item(0);
var style = document.createElement('style');
style.innerHTML = window.atob('\(encodeStringTo64(fromString: cssFile)!)');
parent.appendChild(style)})()
"""
let cssScript = WKUserScript(source: cssStyle, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webView.configuration.userContentController.addUserScript(cssScript)
}
private func encodeStringTo64(fromString: String) -> String? {
let plainData = fromString.data(using: .utf8)
return plainData?.base64EncodedString(options: [])
}
Now, I can use the locally in the app stored font in my WKWebView
although the content is loaded remotely.
In my case, I added this to the (html or php) file, that's loaded remotely from my web server:
<style>
* {
font-family:'Blastimo';
}
</style>
Note:
The file you're loading remotely needs to have element, since the font is injected at the end of this.
Related Topics
Disable Gesture to Pull Down Form/Page Sheet Modal Presentation
Swift Days Between Two Nsdates
Xcode iOS 8 Keyboard Types Not Supported
Unique Values of Array in Swift
How to Increase the Height of Navigation Bar in Xcode
Converting Escaped Utf8 Characters Back to Their Original Form
iOS 9: How to Change Volume Programmatically Without Showing System Sound Bar Popup
How to Save an Array of Objects to Nsuserdefault with Swift
How to Use Writetofile to Save Image in Document Directory
How to Reload Data in a Tableview from a Different Viewcontroller in Swift
Why Nsdateformatter Is Returning Null for a 19/10/2014 in a Brazilian Time Zone
Swift Nsdateformatter Not Working
Uibutton: How to Center an Image and a Text Using Imageedgeinsets and Titleedgeinsets
When Should We Use "Embedded Binaries" Rather Than "Linked Frameworks" in Xcode