Insert CSS into Loaded HTML in Uiwebview/Wkwebview

Insert CSS into loaded HTML in UIWebView / WKWebView

You can do it like this:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *cssString = @"body { font-family: Helvetica; font-size: 50px }"; // 1
NSString *javascriptString = @"var style = document.createElement('style'); style.innerHTML = '%@'; document.head.appendChild(style)"; // 2
NSString *javascriptWithCSSString = [NSString stringWithFormat:javascriptString, cssString]; // 3
[webView stringByEvaluatingJavaScriptFromString:javascriptWithCSSString]; // 4
}

What this code does:

// 1 : Define a string that contains all the CSS declarations

// 2 : Define a javascript string that creates a new HTML DOM element and inserts the CSS declarations into it. Actually the inserting is done in the next step, right now there is only the %@ placeholder. I did this to prevent the line from becoming too long, but step 2 and 3 could be done together.

// 3 : Combine the 2 strings

// 4 : Execute the javascript in the UIWebView

For this to work, your HTML has to have a element.

EDIT:

You can also load the css string from a local css file (named "styles.css" in this case). Just replace step //1 with the following:

NSString *path = [[NSBundle mainBundle] pathForResource:@"styles" ofType:@"css"];
NSString *cssString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

As another option you can just inject a element to the that loads the CSS file:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *path = [[NSBundle mainBundle] pathForResource:@"styles" ofType:@"css"];
NSString *javascriptString = @"var link = document.createElement('link'); link.href = '%@'; link.rel = 'stylesheet'; document.head.appendChild(link)";
NSString *javascriptWithPathString = [NSString stringWithFormat:javascriptString, path];
[webView stringByEvaluatingJavaScriptFromString:javascriptWithPathString];
}

This solution works best for large CSS files. Unfortunately it does not work with remote HTML files. You can only use this when you want to insert CSS into HTML that you have downloaded to your app.

UPDATE: WKWebView / Swift 3.x

When you are working with a WKWebView injecting a element does not work because of WKWebView's security settings.

You can still inject the css as a string. Either create the CSS string in your code //1 or put it in a local file //2. Just be aware that with WKWebView you have to do the injection in WKNavigationDelegate's webView(_:didFinish:) method:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
insertCSSString(into: webView) // 1
// OR
insertContentsOfCSSFile(into: webView) // 2
}

func insertCSSString(into webView: WKWebView) {
let cssString = "body { font-size: 50px; color: #f00 }"
let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);"
webView.evaluateJavaScript(jsString, completionHandler: nil)
}

func insertContentsOfCSSFile(into webView: WKWebView) {
guard let path = Bundle.main.path(forResource: "styles", ofType: "css") else { return }
let cssString = try! String(contentsOfFile: path).trimmingCharacters(in: .whitespacesAndNewlines)
let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);"
webView.evaluateJavaScript(jsString, completionHandler: nil)
}

Load .CSS file from within app in uiwebview

You are basically on the right track, but you should be able to add the css using the same stringByEvaluatingJavaScriptString method.

- (void)webViewDidFinishLoad:(UIWebView *)webView {


NSString *jsFile = @"storage.js";
NSString *jsFilePath = [[NSBundle mainBundle] pathForResource:jsFile ofType:nil];
NSURL *jsURL = [NSURL fileURLWithPath:jsFilePath];
NSString *javascriptCode = [NSString stringWithContentsOfFile:jsURL.path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:javascriptCode];

// Updated to load css from "styling.css" file.
NSString *cssFile = @"styling.css";
NSString *cssFilePath = [[NSBundle mainBundle] pathForResource:jsFile ofType:nil];
NSURL *cssURL = [NSURL fileURLWithPath:jsFilePath];
NSString *cssString = [NSString stringWithContentsOfFile:jsURL.path encoding:NSUTF8StringEncoding error:nil];

// NSString *cssString = @"body { font-family: Verdana, Geneva, sans-serif; font-size: 50px; color: #F00; }";

NSString *javascriptString = @"var style = document.createElement('style'); style.innerHTML = '%@'; document.head.appendChild(style)";
NSString *javascriptWithCSSString = [NSString stringWithFormat:javascriptString, cssString];
[webView stringByEvaluatingJavaScriptFromString:javascriptWithCSSString];

}

Once you do this, you can verify that the style is applied by using Safari remote debugging to view the source for the page displayed on the device / simulator. It can show you if some existing CSS is overriding yours.

Swift - Apply local css to web view

Add delegate method of UIWebView like this

func webViewDidFinishLoad(webView: UIWebView) {    
if let path = Bundle.main.path(forResource: "styles", ofType: "css") {
let javaScriptStr = "var link = document.createElement('link'); link.href = '%@'; link.rel = 'stylesheet'; document.head.appendChild(link)"
let javaScripthPath = String(format: javaScriptStr, path)
self.articleView.stringByEvaluatingJavaScript(from: javaScripthPath)
}

//Second way
do {
let cssContent = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding as NSStringEncoding);
let javaScrStr = "var style = document.createElement('style'); style.innerHTML = '%@'; document.head.appendChild(style)"
let JavaScrWithCSS = NSString(format: javaScrStr, cssContent)
self.articleView.stringByEvaluatingJavaScriptFromString(JavaScrWithCSS as String)
} catch let error as NSError {
print(error);
}
}

Hope this will help you.

WKWebView: How to insert text to HTML when loading local html

If you have full control over the HTML files you could insert a placeholder where you want to insert your value:

Then you can load the HTML content into a String and replace the placeholder with your value before loading the HTML into the WKWebView:

if let filepath = Bundle.main.path(forResource: "content", ofType: "html") {
do {
let rawHtmlString = try String(contentsOfFile: filepath)
let htmlString = rawHtmlString.replacingOccurrences(of: "@@index@@", with: "17.")
webView.loadHTMLString(htmlString, baseURL: nil)
} catch {
// contents could not be loaded
}
}

If you cannot insert a placeholder and have to use the HTML files as they are you could insert your value like this:

if let filepath = Bundle.main.path(forResource: "content", ofType: "html") {
do {
let rawHtmlString = try String(contentsOfFile: filepath)

// get the ranges of the h3 tags
if let h3OpeningTagRange = rawHtmlString.range(of: "<h3>"), let h3ClosingTagRange = rawHtmlString.range(of: "</h3>") {

// get the text inbetween the h3 tags
let h3Content = rawHtmlString[h3OpeningTagRange.upperBound..
// build the new html string
let htmlString =
// everything until and including the

tag


rawHtmlString[...h3OpeningTagRange.upperBound]
// the value you want to insert
+ "17. "
// the text inbetween the h3 tags
+ h3Content
// the rest of the hmtl including the

tag


+ rawHtmlString[h3ClosingTagRange.lowerBound...]

webView.loadHTMLString(String(htmlString), baseURL: nil)
}
} catch {
// contents could not be loaded
}
}

This gets the range of the opening

tag and the range of the closing

tag and constructs the HTML string using those ranges.

This is not a very robust way of doing this, but it might be an easy solution for your special case.



Related Topics



Leave a reply



Submit