Injecting a local css into UIWebView

10,179

Solution 1

I also had trouble doing this.

I was trying to load an HTML file from a server and change the styling using a local CSS file.

At first I used

[webView loadRequest:reqObj];

And when it hit - (void)webViewDidFinishLoad:(UIWebView *)webView i was trying to push the CSS file as a child to 'head':

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *cssPath = [path stringByAppendingPathComponent:@"style.css"]; 

NSString *js = [NSString stringWithFormat:@"var cssChild = document.createElement('link');"
                "cssChild = 'text/css';"
                "cssChild = 'stylesheet';"
                "cssChild = '%@';", cssPath];
js = [NSString stringWithFormat:@"%@ document.getElementsByTagName('head')[0].appendChild(cssChild);", js];
[webView stringByEvaluatingJavaScriptFromString:js];
}

So... it didn't work...

then i tried

NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];    
[webView loadHTMLString:htmlString baseURL:baseURL];

(I copied the HTML string into htmlString) and then, inside - (void)webViewDidFinishLoad:(UIWebView *)webView I injected the CSS as in the code above. And it worked!

But... my HTML file is stored in a remote server and I didn't have the HTML string, so I used

NSString* myFile = [NSString stringWithFormat:@"http://blablabla.com/file.html"];
NSString* myFileURLString = [myFile stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSData *myFileData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:myFileURLString]];
NSString* myFileHtml = [[[NSString alloc] initWithData:myFileData encoding:NSASCIIStringEncoding] autorelease];

To get the HTML. Now, I have the raw HTML text inside ' myFileHtml '. I now use

NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];    
[webView loadHTMLString:myFileHtml baseURL:baseURL];

And catching the response in ' webViewDidFinishLoad ', injecting my CSS file into it and it worked :)

Maybe there's another, more elegant, solution to this problem, but this is what I came up with...

Hope it helped.

Solution 2

cssNode.href = '%@';", cssPath];

The line above fails because it tries to fetch the file from the webserver. Using something like:

cssNode.href = 'file://%@';", cssPath];

accesses the local file system. You can use Safari's developer mode to inspect the iPhone simulator and see whether file is found and loaded.


I eventually ended up implementing inline stylesheets instead of linking to stylesheet. Here's the code that works for me

NSError *error;
NSString *css = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"stylesheet" ofType:@"css"] encoding:NSASCIIStringEncoding error:&error];
css = [css stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; // js dom inject doesn't accept line breaks, so remove them

NSString *js = [NSString stringWithFormat:@"var styleNode = document.createElement('style');"
                "styleNode.type = 'text/css';"
                "styleNode.innerHTML = ' %@ ';", css];
js = [NSString stringWithFormat:@"%@document.getElementsByTagName('head')[0].appendChild(styleNode);", js];

[_webView stringByEvaluatingJavaScriptFromString:js];

Solution 3

I ran into this while looking for an answer to the same question. I'm loading an HTML page from a web server into a UIWebView. The HTML already has lots of CSS, appropriate for web viewing. In my case I wanted to display:none a few irrelevant div's.

I didn't want to store the HTML locally then load from the file, so I came up with another solution, conceptually similar to others here but more to my tastes. This is Swift 3. Have this run after the page loads, but before it's displayed:

let css = "#someDiv {display:none;} #otherDiv {display:none;} .someClass {display:none;}"
let js = "var sheet = document.createElement('style');sheet.innerHTML = \"\(css)\";document.body.appendChild(sheet);"
webView.stringByEvaluatingJavaScript(from: js)
Share:
10,179
Gal
Author by

Gal

Updated on June 04, 2022

Comments

  • Gal
    Gal almost 2 years

    I'm trying to "inject" a local css file into downloaded xhtml file.

    I found many examples of how to do it, but it just doesn't work for me...

    Here is my code:

    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        NSString *path = [[NSBundle mainBundle] bundlePath];
        NSString *cssPath = [path stringByAppendingPathComponent:@"test.css"]; 
    
        NSString *js = [NSString stringWithFormat:@"var cssNode = document.createElement('link');"
                    "cssNode.type = 'text/css';"
                    "cssNode.rel = 'stylesheet';"
                    "cssNode.href = '%@';", cssPath];
        js = [NSString stringWithFormat:@"%@document.getElementsByTagName('head')[0].appendChild(cssNode);", js];
        //m_webview is a member 
        [m_webView stringByEvaluatingJavaScriptFromString:js];
    }
    

    What am I doing wrong here?

    Thanks,

  • Gal
    Gal over 12 years
    thanks, but it still looks the same. I wonder, how can I tell if 'stringByEvaluatingJavaScriptFromString' worked or failed?
  • Gal
    Gal over 12 years
    Thanks! That did work. I just had to add '[myFileData release];'